Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions CLI/cmux.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3396,6 +3396,108 @@ struct CMUXCLI {
return true
}

private func localizedCoderouterAliases() -> String {
let defaultValue = "coderouter|cr [coderouter-args...] (aliases for the installed CodeRouter CLI)"
let bundle = CLIExecutableLocator.enclosingAppBundle() ?? .main
let catalogValue = String(
localized: "cli.coderouter.aliases",
defaultValue: "coderouter|cr [coderouter-args...] (aliases for the installed CodeRouter CLI)",
bundle: bundle
)
let explicitValue = CMUXDiffViewerLocalization.string(
"cli.coderouter.aliases",
defaultValue: defaultValue
)
return explicitValue == defaultValue ? catalogValue : explicitValue
}

private func localizedCoderouterNotFound() -> String {
let defaultValue = "Required CLI not found. Install the command and retry."
let bundle = CLIExecutableLocator.enclosingAppBundle() ?? .main
let catalogValue = String(
localized: "cli.coderouter.error.notFound",
defaultValue: "Required CLI not found. Install the command and retry.",
bundle: bundle
)
let explicitValue = CMUXDiffViewerLocalization.string(
"cli.coderouter.error.notFound",
defaultValue: defaultValue
)
return explicitValue == defaultValue ? catalogValue : explicitValue
}

private func localizedCoderouterLaunchFailed() -> String {
let defaultValue = "Could not start the required CLI. Check the installation and try again."
let bundle = CLIExecutableLocator.enclosingAppBundle() ?? .main
let catalogValue = String(
localized: "cli.coderouter.error.launchFailed",
defaultValue: "Could not start the required CLI. Check the installation and try again.",
bundle: bundle
)
let explicitValue = CMUXDiffViewerLocalization.string(
"cli.coderouter.error.launchFailed",
defaultValue: defaultValue
)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
return explicitValue == defaultValue ? catalogValue : explicitValue
}

/// Run the separately installed CodeRouter CLI without routing through the
/// cmux socket. Replace this process after resolving the executable so
/// stdin/stdout/stderr, signals, and the child exit status retain their
/// normal terminal semantics. The argv is built directly; arguments such
/// as prompts, paths, and shell metacharacters are never interpreted by a
/// shell.
private func runCoderouterAlias(commandArgs: [String]) throws {
let candidates = ["coderouter", "cr"]
guard let executablePath = candidates.lazy
.compactMap({ resolveExecutableInPath($0) })
.first else {
throw CLIError(
message: localizedCoderouterNotFound(),
exitCode: 127
)
}

// CodeRouter is an independent executable. Do not hand it cmux's ambient
// terminal/control-plane context: CMUX_* and CMUXD_* may carry socket
// paths, capabilities, passwords, auth state, or internal paths. There is
// intentionally no auth handoff here; a future handoff must be explicit
// and narrowly allowlisted.
let childEnvironment = ProcessInfo.processInfo.environment.filter { key, _ in
!key.hasPrefix("CMUX_") && !key.hasPrefix("CMUXD_")
}
var argv = ([executablePath] + commandArgs).map { strdup($0) }
let environmentStrings = childEnvironment.keys.sorted().map { key in
"\(key)=\(childEnvironment[key] ?? "")"
}
var environment = environmentStrings.map { strdup($0) }
defer {
for item in argv {
free(item)
}
for item in environment {
free(item)
}
}
argv.append(nil)
environment.append(nil)

let executionError = cliExecFailureErrno {
executablePath.withCString { executable in
_ = execve(executable, &argv, &environment)
}
}
let errorText = String(cString: strerror(executionError))
cliDebugLog(
"cli.coderouter.exec_failed executable=\(executablePath) "
+ "errno=\(executionError) error=\(errorText)"
)
throw CLIError(
message: localizedCoderouterLaunchFailed(),
exitCode: 127
)
}

func run() throws {
let processEnv = ProcessInfo.processInfo.environment
let cliBundleIdentifier = CLISocketPathResolver.currentAppBundleIdentifier()
Expand Down Expand Up @@ -3465,6 +3567,10 @@ struct CMUXCLI {

let command = args[index]
let rawCommandArgs = Array(args[(index + 1)...])
if command == "coderouter" || command == "cr" {
try runCoderouterAlias(commandArgs: rawCommandArgs)
return
}
let passesThroughProviderArguments = managedProviderArgumentsPassThrough(command: command)
let presentationOptions: (jsonOutput: Bool, idFormat: String?, remaining: [String])
if passesThroughProviderArguments {
Expand Down Expand Up @@ -36722,6 +36828,7 @@ export default CMUXSessionRestore;
events [--after <seq>] [--cursor-file <path>] [--name <event>] [--category <category>] [--reconnect] [--limit <n>] [--no-ack] [--no-heartbeat]
auth <status|login|logout>
login | logout (aliases for auth login/logout)
\(localizedCoderouterAliases())
vm <base|new|ls|status|snapshot|fork|restore|rm|exec|shell|ssh> [args...] (alias: cloud)
remotes <list|add|remove> [--route <host:port>] [--tag <tag>] [--json] (alias: remote)
ai-accounts <list|upload|remove> [--team <id>] [--json]
Expand Down
75 changes: 75 additions & 0 deletions Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -266470,6 +266470,81 @@
}
}
}
},
"cli.coderouter.aliases": {
"extractionState": "manual",
"localizations": {
"ar": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (بدائل لـ CodeRouter CLI المثبّت)" } },
"bs": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (aliasi za instalirani CodeRouter CLI)" } },
"da": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (aliasser for den installerede CodeRouter CLI)" } },
"de": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (Aliase für die installierte CodeRouter-CLI)" } },
"en": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (aliases for the installed CodeRouter CLI)" } },
"es": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (alias para la CLI de CodeRouter instalada)" } },
"fr": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (alias de la CLI CodeRouter installée)" } },
"it": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (alias per la CLI CodeRouter installata)" } },
"ja": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (インストール済み CodeRouter CLI のエイリアス)" } },
"km": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (ឈ្មោះកាត់សម្រាប់ CodeRouter CLI ដែលបានដំឡើង)" } },
"ko": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (설치된 CodeRouter CLI의 별칭)" } },
"nb": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (aliaser for den installerte CodeRouter CLI)" } },
"pl": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (aliasy zainstalowanego CodeRouter CLI)" } },
"pt-BR": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (aliases para a CLI do CodeRouter instalada)" } },
"ru": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (псевдонимы для установленного CodeRouter CLI)" } },
"th": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (ชื่อเรียกแทนสำหรับ CodeRouter CLI ที่ติดตั้งไว้)" } },
"tr": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (yüklü CodeRouter CLI için takma adlar)" } },
"uk": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (псевдоніми для встановленого CodeRouter CLI)" } },
"zh-Hans": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (已安装 CodeRouter CLI 的别名)" } },
"zh-Hant": { "stringUnit": { "state": "translated", "value": "coderouter|cr [coderouter-args...] (已安裝 CodeRouter CLI 的別名)" } }
}
},
"cli.coderouter.error.launchFailed": {
"extractionState": "manual",
"localizations": {
"ar": { "stringUnit": { "state": "translated", "value": "تعذر تشغيل أداة سطر الأوامر المطلوبة. تحقّق من التثبيت ثم أعد المحاولة." } },
"bs": { "stringUnit": { "state": "translated", "value": "Traženi CLI nije moguće pokrenuti. Provjerite instalaciju i pokušajte ponovo." } },
"da": { "stringUnit": { "state": "translated", "value": "Den nødvendige CLI kunne ikke startes. Kontrollér installationen, og prøv igen." } },
"de": { "stringUnit": { "state": "translated", "value": "Die erforderliche CLI konnte nicht gestartet werden. Überprüfen Sie die Installation und versuchen Sie es erneut." } },
"en": { "stringUnit": { "state": "translated", "value": "Could not start the required CLI. Check the installation and try again." } },
Comment thread
coderabbitai[bot] marked this conversation as resolved.
"es": { "stringUnit": { "state": "translated", "value": "No se pudo iniciar la CLI necesaria. Comprueba la instalación y vuelve a intentarlo." } },
"fr": { "stringUnit": { "state": "translated", "value": "Impossible de démarrer la CLI requise. Vérifiez l’installation, puis réessayez." } },
"it": { "stringUnit": { "state": "translated", "value": "Impossibile avviare la CLI richiesta. Verifica l'installazione e riprova." } },
"ja": { "stringUnit": { "state": "translated", "value": "必要な CLI を起動できませんでした。インストールを確認して、もう一度お試しください。" } },
"km": { "stringUnit": { "state": "translated", "value": "មិនអាចចាប់ផ្ដើម CLI ដែលត្រូវការ។ សូមពិនិត្យការដំឡើង ហើយព្យាយាមម្ដងទៀត។" } },
"ko": { "stringUnit": { "state": "translated", "value": "필요한 CLI를 시작할 수 없습니다. 설치를 확인한 후 다시 시도하세요." } },
"nb": { "stringUnit": { "state": "translated", "value": "Kunne ikke starte den nødvendige CLI-en. Kontroller installasjonen og prøv igjen." } },
"pl": { "stringUnit": { "state": "translated", "value": "Nie można uruchomić wymaganej biblioteki CLI. Sprawdź instalację i spróbuj ponownie." } },
"pt-BR": { "stringUnit": { "state": "translated", "value": "Não foi possível iniciar a CLI necessária. Verifique a instalação e tente novamente." } },
"ru": { "stringUnit": { "state": "translated", "value": "Не удалось запустить необходимый CLI. Проверьте установку и повторите попытку." } },
"th": { "stringUnit": { "state": "translated", "value": "ไม่สามารถเริ่ม CLI ที่จำเป็นได้ โปรดตรวจสอบการติดตั้งแล้วลองอีกครั้ง" } },
"tr": { "stringUnit": { "state": "translated", "value": "Gerekli CLI başlatılamadı. Kurulumu kontrol edip tekrar deneyin." } },
"uk": { "stringUnit": { "state": "translated", "value": "Не вдалося запустити потрібний CLI. Перевірте встановлення та повторіть спробу." } },
"zh-Hans": { "stringUnit": { "state": "translated", "value": "无法启动所需的 CLI。请检查安装并重试。" } },
"zh-Hant": { "stringUnit": { "state": "translated", "value": "無法啟動必要的 CLI。請檢查安裝後再試一次。" } }
}
},
"cli.coderouter.error.notFound": {
"extractionState": "manual",
"localizations": {
"ar": { "stringUnit": { "state": "translated", "value": "تعذر العثور على أداة سطر الأوامر المطلوبة. ثبّت الأمر ثم أعد المحاولة." } },
"bs": { "stringUnit": { "state": "translated", "value": "Traženi CLI nije pronađen. Instalirajte naredbu i pokušajte ponovo." } },
"da": { "stringUnit": { "state": "translated", "value": "Den nødvendige CLI blev ikke fundet. Installer kommandoen, og prøv igen." } },
"de": { "stringUnit": { "state": "translated", "value": "Die erforderliche CLI wurde nicht gefunden. Installieren Sie den Befehl und versuchen Sie es erneut." } },
"en": { "stringUnit": { "state": "translated", "value": "Required CLI not found. Install the command and retry." } },
"es": { "stringUnit": { "state": "translated", "value": "No se encontró la CLI necesaria. Instala el comando y vuelve a intentarlo." } },
"fr": { "stringUnit": { "state": "translated", "value": "La CLI requise est introuvable. Installez la commande, puis réessayez." } },
"it": { "stringUnit": { "state": "translated", "value": "La CLI richiesta non è stata trovata. Installa il comando e riprova." } },
"ja": { "stringUnit": { "state": "translated", "value": "必要な CLI が見つかりません。コマンドをインストールして、もう一度お試しください。" } },
"km": { "stringUnit": { "state": "translated", "value": "រកមិនឃើញ CLI ដែលត្រូវការ។ សូមដំឡើងពាក្យបញ្ជា ហើយព្យាយាមម្ដងទៀត។" } },
"ko": { "stringUnit": { "state": "translated", "value": "필요한 CLI를 찾을 수 없습니다. 명령을 설치한 후 다시 시도하세요." } },
"nb": { "stringUnit": { "state": "translated", "value": "Fant ikke den nødvendige CLI-en. Installer kommandoen og prøv igjen." } },
"pl": { "stringUnit": { "state": "translated", "value": "Nie znaleziono wymaganej CLI. Zainstaluj polecenie i spróbuj ponownie." } },
"pt-BR": { "stringUnit": { "state": "translated", "value": "A CLI necessária não foi encontrada. Instale o comando e tente novamente." } },
"ru": { "stringUnit": { "state": "translated", "value": "Не удалось найти необходимый CLI. Установите команду и повторите попытку." } },
"th": { "stringUnit": { "state": "translated", "value": "ไม่พบ CLI ที่จำเป็น โปรดติดตั้งคำสั่งแล้วลองอีกครั้ง" } },
"tr": { "stringUnit": { "state": "translated", "value": "Gerekli CLI bulunamadı. Komutu yükleyip tekrar deneyin." } },
"uk": { "stringUnit": { "state": "translated", "value": "Не знайдено потрібний CLI. Установіть команду та повторіть спробу." } },
"zh-Hans": { "stringUnit": { "state": "translated", "value": "未找到所需的 CLI。请安装该命令后重试。" } },
"zh-Hant": { "stringUnit": { "state": "translated", "value": "找不到必要的 CLI。請安裝該命令後再試一次。" } }
}
}
},
"version": "1.0"
Expand Down
Loading