diff --git a/CHANGELOG.md b/CHANGELOG.md index 57cee0ae15a7..04576e46b5ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to cmux are documented here. +## [Unreleased] + +### Changed + +- `cmux ssh` now forwards `PATH`, `SHELL`, and `SSH_AUTH_SOCK` from the invoking shell by default, so ProxyCommand helpers and other tools on your shell PATH are reachable from the SSH session. Add `--inherit-env` to forward your full environment (stale cmux socket and workspace variables are scrubbed automatically). + ## [0.64.13] - 2026-06-04 ### Added diff --git a/CLI/cmux.swift b/CLI/cmux.swift index af21a82fc5a7..201ba1f178f3 100644 --- a/CLI/cmux.swift +++ b/CLI/cmux.swift @@ -7420,6 +7420,7 @@ struct CMUXCLI { let workspaceName: String? let windowRaw: String? let noFocus: Bool + let inheritEnvironment: Bool let sshOptions: [String] let extraArguments: [String] let agentSocketPath: String? @@ -7437,6 +7438,7 @@ struct CMUXCLI { workspaceName: String?, windowRaw: String? = nil, noFocus: Bool, + inheritEnvironment: Bool = false, sshOptions: [String], extraArguments: [String], agentSocketPath: String? = nil, @@ -7451,6 +7453,7 @@ struct CMUXCLI { self.workspaceName = workspaceName self.windowRaw = windowRaw self.noFocus = noFocus + self.inheritEnvironment = inheritEnvironment self.sshOptions = sshOptions self.extraArguments = extraArguments self.agentSocketPath = agentSocketPath @@ -7711,10 +7714,9 @@ struct CMUXCLI { var workspaceCreateParams: [String: Any] = [ "initial_command": initialSSHStartupCommand, ] - if let agentSocketPath = sshOptions.agentSocketPath { - workspaceCreateParams["initial_env"] = [ - "SSH_AUTH_SOCK": agentSocketPath, - ] + let startupEnvironment = sshStartupEnvironment(for: sshOptions) + if !startupEnvironment.isEmpty { + workspaceCreateParams["initial_env"] = startupEnvironment } try applyWindowOrCallerContext(to: &workspaceCreateParams, client: client, windowRaw: sshOptions.windowRaw) @@ -7890,6 +7892,7 @@ struct CMUXCLI { var workspaceName: String? var windowRaw: String? var noFocus = false + var inheritEnvironment = false var sshOptions: [String] = [] var extraArguments: [String] = [] var forwardAgentOverride: Bool? @@ -7938,6 +7941,9 @@ struct CMUXCLI { case "--no-focus": noFocus = true index += 1 + case "--inherit-env": + inheritEnvironment = true + index += 1 case "-A", "--forward-agent": forwardAgentOverride = true index += 1 @@ -7985,6 +7991,7 @@ struct CMUXCLI { workspaceName: workspaceName, windowRaw: windowRaw ?? windowOverride, noFocus: noFocus, + inheritEnvironment: inheritEnvironment, sshOptions: agentForwarding.sshOptions, extraArguments: extraArguments, agentSocketPath: agentForwarding.agentSocketPath, @@ -7993,6 +8000,57 @@ struct CMUXCLI { ) } + private static let safeSSHStartupEnvironmentKeys: [String] = [ + "PATH", + "SHELL", + "SSH_AUTH_SOCK", + ] + + private static let sshInheritedEnvironmentScrubbedKeys: Set = [ + "CMUX_BUNDLED_CLI_PATH", + "CMUX_SOCKET", + "CMUX_SOCKET_PATH", + "CMUX_SOCKET_PASSWORD", + "CMUX_WORKSPACE_ID", + "CMUX_SURFACE_ID", + "CMUX_PANEL_ID", + "CMUX_TAB_ID", + "CMUX_PANE_ID", + "CMUXD_UNIX_PATH", + "CMUX_DEBUG_LOG", + "CMUX_RELAY_ID", + "CMUX_RELAY_TOKEN", + ] + + private func sshStartupEnvironment(for options: SSHCommandOptions) -> [String: String] { + let environment = ProcessInfo.processInfo.environment + var startupEnvironment = options.inheritEnvironment + ? scrubbedSSHInheritedEnvironment(environment) + : safeSSHStartupEnvironment(environment) + if let agentSocketPath = options.agentSocketPath { + startupEnvironment["SSH_AUTH_SOCK"] = agentSocketPath + } + return startupEnvironment + } + + private func safeSSHStartupEnvironment(_ environment: [String: String]) -> [String: String] { + var result: [String: String] = [:] + for key in Self.safeSSHStartupEnvironmentKeys { + if let value = Self.normalizedEnvValue(environment[key]) { + result[key] = value + } + } + return result + } + + private func scrubbedSSHInheritedEnvironment(_ environment: [String: String]) -> [String: String] { + var result = environment.compactMapValues { Self.normalizedEnvValue($0) } + for key in Self.sshInheritedEnvironmentScrubbedKeys { + result.removeValue(forKey: key) + } + return result + } + private func resolvedSSHAgentForwarding( sshOptions: [String], override: Bool? @@ -13522,6 +13580,7 @@ struct CMUXCLI { -A, --forward-agent Forward the caller's SSH agent; also honors ForwardAgent yes from ssh_config -a, --no-forward-agent Disable SSH agent forwarding for this workspace --ssh-option Extra SSH -o option (repeatable) + --inherit-env Forward the caller environment after scrubbing stale cmux context --window Target window for the managed workspace --no-focus Create workspace without switching to it diff --git a/Resources/Localizable.xcstrings b/Resources/Localizable.xcstrings index 4f46da2a7826..a03ef4aed55a 100644 --- a/Resources/Localizable.xcstrings +++ b/Resources/Localizable.xcstrings @@ -11171,121 +11171,121 @@ "ar": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh [flags] [-- ]\n\nأنشئ مساحة عمل جديدة، وعلّمها كـ remote-SSH، وابدأ جلسة SSH داخلها.\nسينشئ cmux أيضًا نقطة نهاية وكيل SSH محلية حتى تخرج حركة مرور المتصفح من المضيف البعيد.\n\nFlags:\n --name عنوان اختياري لمساحة العمل\n --port <n> منفذ SSH\n --identity <path> مسار ملف هوية SSH\n -A, --forward-agent يمرر وكيل SSH الخاص بالمستدعي؛ ويحترم أيضًا ForwardAgent yes من ssh_config\n -a, --no-forward-agent يعطّل تمرير وكيل SSH لمساحة العمل هذه\n --ssh-option <opt> خيار SSH -o إضافي (قابل للتكرار)\n --window <id|ref|index> النافذة الهدف لمساحة العمل المُدارة\n --no-focus ينشئ مساحة العمل من دون الانتقال إليها\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nأنشئ مساحة عمل جديدة، وعلّمها كـ remote-SSH، وابدأ جلسة SSH داخلها.\nسينشئ cmux أيضًا نقطة نهاية وكيل SSH محلية حتى تخرج حركة مرور المتصفح من المضيف البعيد.\n\nFlags:\n --name <title> عنوان اختياري لمساحة العمل\n --port <n> منفذ SSH\n --identity <path> مسار ملف هوية SSH\n -A, --forward-agent يمرر وكيل SSH الخاص بالمستدعي؛ ويحترم أيضًا ForwardAgent yes من ssh_config\n -a, --no-forward-agent يعطّل تمرير وكيل SSH لمساحة العمل هذه\n --ssh-option <opt> خيار SSH -o إضافي (قابل للتكرار)\n --inherit-env يمرّر بيئة المستدعي الكاملة بعد حذف متغيرات مقبس cmux والمساحة الافتراضية القديمة\n --window <id|ref|index> النافذة الهدف لمساحة العمل المُدارة\n --no-focus ينشئ مساحة العمل من دون الانتقال إليها\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nKreira novi workspace, označava ga kao remote-SSH i pokreće SSH sesiju u tom workspaceu.\ncmux će također uspostaviti lokalnu SSH proxy krajnju tačku kako bi promet preglednika izlazio s udaljenog hosta.\n\nFlags:\n --name <title> Opcionalni naslov workspacea\n --port <n> SSH port\n --identity <path> Putanja do SSH identity datoteke\n -A, --forward-agent Prosljeđuje SSH agent pozivaoca; poštuje i ForwardAgent yes iz ssh_config\n -a, --no-forward-agent Onemogućava prosljeđivanje SSH agenta za ovaj workspace\n --ssh-option <opt> Dodatna SSH -o opcija (može se ponavljati)\n --window <id|ref|index> Ciljni prozor za upravljani workspace\n --no-focus Kreira workspace bez prelaska na njega\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nKreira novi workspace, označava ga kao remote-SSH i pokreće SSH sesiju u tom workspaceu.\ncmux će također uspostaviti lokalnu SSH proxy krajnju tačku kako bi promet preglednika izlazio s udaljenog hosta.\n\nFlags:\n --name <title> Opcionalni naslov workspacea\n --port <n> SSH port\n --identity <path> Putanja do SSH identity datoteke\n -A, --forward-agent Prosljeđuje SSH agent pozivaoca; poštuje i ForwardAgent yes iz ssh_config\n -a, --no-forward-agent Onemogućava prosljeđivanje SSH agenta za ovaj workspace\n --ssh-option <opt> Dodatna SSH -o opcija (može se ponavljati)\n --inherit-env Prosljeđuje cijelo okruženje pozivaoca SSH sesiji, uklanjajući zastarjele cmux socket i workspace varijable\n --window <id|ref|index> Ciljni prozor za upravljani workspace\n --no-focus Kreira workspace bez prelaska na njega\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "da": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nOpret et nyt arbejdsområde, markér det som remote-SSH, og start en SSH-session i det arbejdsområde.\ncmux opretter også et lokalt SSH-proxyendepunkt, så browsertrafik kan gå ud fra den eksterne vært.\n\nFlags:\n --name <title> Valgfri titel på arbejdsområdet\n --port <n> SSH-port\n --identity <path> Sti til SSH-identitetsfil\n -A, --forward-agent Videresend kalderens SSH-agent; respekterer også ForwardAgent yes fra ssh_config\n -a, --no-forward-agent Deaktiver SSH-agentvideresendelse for dette arbejdsområde\n --ssh-option <opt> Ekstra SSH -o-indstilling (kan gentages)\n --window <id|ref|index> Målvindue for det administrerede arbejdsområde\n --no-focus Opret arbejdsområdet uden at skifte til det\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nOpret et nyt arbejdsområde, markér det som remote-SSH, og start en SSH-session i det arbejdsområde.\ncmux opretter også et lokalt SSH-proxyendepunkt, så browsertrafik kan gå ud fra den eksterne vært.\n\nFlags:\n --name <title> Valgfri titel på arbejdsområdet\n --port <n> SSH-port\n --identity <path> Sti til SSH-identitetsfil\n -A, --forward-agent Videresend kalderens SSH-agent; respekterer også ForwardAgent yes fra ssh_config\n -a, --no-forward-agent Deaktiver SSH-agentvideresendelse for dette arbejdsområde\n --ssh-option <opt> Ekstra SSH -o-indstilling (kan gentages)\n --inherit-env Videresend kalderens fulde miljø til SSH-sessionen og fjern forældede cmux-socket- og arbejdsrumsvariabler\n --window <id|ref|index> Målvindue for det administrerede arbejdsområde\n --no-focus Opret arbejdsområdet uden at skifte til det\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "de": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nErstellt einen neuen Workspace, markiert ihn als remote-SSH und startet darin eine SSH-Sitzung.\ncmux richtet außerdem einen lokalen SSH-Proxy-Endpunkt ein, damit Browserverkehr vom Remote-Host ausgeht.\n\nFlags:\n --name <title> Optionaler Workspace-Titel\n --port <n> SSH-Port\n --identity <path> Pfad zur SSH-Identitätsdatei\n -A, --forward-agent Leitet den SSH-Agent des Aufrufers weiter; beachtet auch ForwardAgent yes aus ssh_config\n -a, --no-forward-agent Deaktiviert SSH-Agent-Weiterleitung für diesen Workspace\n --ssh-option <opt> Zusätzliche SSH-Option -o (wiederholbar)\n --window <id|ref|index> Zielfenster für den verwalteten Workspace\n --no-focus Workspace erstellen, ohne zu ihm zu wechseln\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nErstellt einen neuen Workspace, markiert ihn als remote-SSH und startet darin eine SSH-Sitzung.\ncmux richtet außerdem einen lokalen SSH-Proxy-Endpunkt ein, damit Browserverkehr vom Remote-Host ausgeht.\n\nFlags:\n --name <title> Optionaler Workspace-Titel\n --port <n> SSH-Port\n --identity <path> Pfad zur SSH-Identitätsdatei\n -A, --forward-agent Leitet den SSH-Agent des Aufrufers weiter; beachtet auch ForwardAgent yes aus ssh_config\n -a, --no-forward-agent Deaktiviert SSH-Agent-Weiterleitung für diesen Workspace\n --ssh-option <opt> Zusätzliche SSH-Option -o (wiederholbar)\n --inherit-env Die vollständige Umgebung des Aufrufers weiterleiten und veraltete cmux-Socket- und Workspace-Variablen entfernen\n --window <id|ref|index> Zielfenster für den verwalteten Workspace\n --no-focus Workspace erstellen, ohne zu ihm zu wechseln\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "en": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nCreate a new workspace, mark it as remote-SSH, and start an SSH session in that workspace.\ncmux will also establish a local SSH proxy endpoint so browser traffic can egress from the remote host.\n\nFlags:\n --name <title> Optional workspace title\n --port <n> SSH port\n --identity <path> SSH identity file path\n -A, --forward-agent Forward the caller's SSH agent; also honors ForwardAgent yes from ssh_config\n -a, --no-forward-agent Disable SSH agent forwarding for this workspace\n --ssh-option <opt> Extra SSH -o option (repeatable)\n --window <id|ref|index> Target window for the managed workspace\n --no-focus Create workspace without switching to it\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nCreate a new workspace, mark it as remote-SSH, and start an SSH session in that workspace.\ncmux will also establish a local SSH proxy endpoint so browser traffic can egress from the remote host.\n\nFlags:\n --name <title> Optional workspace title\n --port <n> SSH port\n --identity <path> SSH identity file path\n -A, --forward-agent Forward the caller's SSH agent; also honors ForwardAgent yes from ssh_config\n -a, --no-forward-agent Disable SSH agent forwarding for this workspace\n --ssh-option <opt> Extra SSH -o option (repeatable)\n --inherit-env Forward the caller environment after scrubbing stale cmux context\n --window <id|ref|index> Target window for the managed workspace\n --no-focus Create workspace without switching to it\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "es": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nCrea un nuevo espacio de trabajo, márcalo como remote-SSH e inicia una sesión SSH en ese espacio.\ncmux también establecerá un punto final de proxy SSH local para que el tráfico del navegador salga desde el host remoto.\n\nFlags:\n --name <title> Título opcional del espacio de trabajo\n --port <n> Puerto SSH\n --identity <path> Ruta del archivo de identidad SSH\n -A, --forward-agent Reenvía el agente SSH del proceso que llama; también respeta ForwardAgent yes de ssh_config\n -a, --no-forward-agent Desactiva el reenvío del agente SSH para este espacio de trabajo\n --ssh-option <opt> Opción SSH -o adicional (repetible)\n --window <id|ref|index> Ventana de destino para el espacio de trabajo administrado\n --no-focus Crea el espacio de trabajo sin cambiar a él\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nCrea un nuevo espacio de trabajo, márcalo como remote-SSH e inicia una sesión SSH en ese espacio.\ncmux también establecerá un punto final de proxy SSH local para que el tráfico del navegador salga desde el host remoto.\n\nFlags:\n --name <title> Título opcional del espacio de trabajo\n --port <n> Puerto SSH\n --identity <path> Ruta del archivo de identidad SSH\n -A, --forward-agent Reenvía el agente SSH del proceso que llama; también respeta ForwardAgent yes de ssh_config\n -a, --no-forward-agent Desactiva el reenvío del agente SSH para este espacio de trabajo\n --ssh-option <opt> Opción SSH -o adicional (repetible)\n --inherit-env Reenvía el entorno completo del invocador eliminando las variables obsoletas de socket y espacio de trabajo de cmux\n --window <id|ref|index> Ventana de destino para el espacio de trabajo administrado\n --no-focus Crea el espacio de trabajo sin cambiar a él\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nCrée un nouvel espace de travail, le marque comme remote-SSH et démarre une session SSH dans cet espace.\ncmux établira aussi un point de terminaison proxy SSH local afin que le trafic du navigateur sorte depuis l’hôte distant.\n\nFlags:\n --name <title> Titre facultatif de l’espace de travail\n --port <n> Port SSH\n --identity <path> Chemin du fichier d’identité SSH\n -A, --forward-agent Transfère l’agent SSH de l’appelant ; respecte aussi ForwardAgent yes depuis ssh_config\n -a, --no-forward-agent Désactive le transfert d’agent SSH pour cet espace de travail\n --ssh-option <opt> Option SSH -o supplémentaire (répétable)\n --window <id|ref|index> Fenêtre cible pour l’espace de travail géré\n --no-focus Crée l’espace de travail sans basculer dessus\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nCrée un nouvel espace de travail, le marque comme remote-SSH et démarre une session SSH dans cet espace.\ncmux établira aussi un point de terminaison proxy SSH local afin que le trafic du navigateur sorte depuis l’hôte distant.\n\nFlags:\n --name <title> Titre facultatif de l’espace de travail\n --port <n> Port SSH\n --identity <path> Chemin du fichier d’identité SSH\n -A, --forward-agent Transfère l’agent SSH de l’appelant ; respecte aussi ForwardAgent yes depuis ssh_config\n -a, --no-forward-agent Désactive le transfert d’agent SSH pour cet espace de travail\n --ssh-option <opt> Option SSH -o supplémentaire (répétable)\n --inherit-env Transmet l'environnement complet de l'appelant en supprimant les variables de socket et d'espace de travail cmux obsolètes\n --window <id|ref|index> Fenêtre cible pour l’espace de travail géré\n --no-focus Crée l’espace de travail sans basculer dessus\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "it": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nCrea un nuovo workspace, contrassegnalo come remote-SSH e avvia una sessione SSH in quel workspace.\ncmux creerà anche un endpoint proxy SSH locale in modo che il traffico del browser esca dall'host remoto.\n\nFlags:\n --name <title> Titolo opzionale del workspace\n --port <n> Porta SSH\n --identity <path> Percorso del file di identità SSH\n -A, --forward-agent Inoltra l'agente SSH del chiamante; rispetta anche ForwardAgent yes da ssh_config\n -a, --no-forward-agent Disattiva l'inoltro dell'agente SSH per questo workspace\n --ssh-option <opt> Opzione SSH -o aggiuntiva (ripetibile)\n --window <id|ref|index> Finestra di destinazione per il workspace gestito\n --no-focus Crea il workspace senza passarvi\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nCrea un nuovo workspace, contrassegnalo come remote-SSH e avvia una sessione SSH in quel workspace.\ncmux creerà anche un endpoint proxy SSH locale in modo che il traffico del browser esca dall'host remoto.\n\nFlags:\n --name <title> Titolo opzionale del workspace\n --port <n> Porta SSH\n --identity <path> Percorso del file di identità SSH\n -A, --forward-agent Inoltra l'agente SSH del chiamante; rispetta anche ForwardAgent yes da ssh_config\n -a, --no-forward-agent Disattiva l'inoltro dell'agente SSH per questo workspace\n --ssh-option <opt> Opzione SSH -o aggiuntiva (ripetibile)\n --inherit-env Inoltra l'ambiente completo del chiamante rimuovendo le variabili obsolete di socket e workspace di cmux\n --window <id|ref|index> Finestra di destinazione per il workspace gestito\n --no-focus Crea il workspace senza passarvi\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "ja": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\n新しいワークスペースを作成し、remote-SSH としてマークして、そのワークスペースで SSH セッションを開始します。\ncmux はローカル SSH プロキシエンドポイントも確立するため、ブラウザトラフィックはリモートホストから送信されます。\n\nFlags:\n --name <title> 任意のワークスペースタイトル\n --port <n> SSH ポート\n --identity <path> SSH identity ファイルパス\n -A, --forward-agent 呼び出し元の SSH エージェントを転送します。ssh_config の ForwardAgent yes も尊重します\n -a, --no-forward-agent このワークスペースでは SSH エージェント転送を無効にします\n --ssh-option <opt> 追加の SSH -o オプション(繰り返し可)\n --window <id|ref|index> 管理対象ワークスペースのターゲットウィンドウ\n --no-focus ワークスペースを作成しますが切り替えません\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\n新しいワークスペースを作成し、remote-SSH としてマークして、そのワークスペースで SSH セッションを開始します。\ncmux はローカル SSH プロキシエンドポイントも確立するため、ブラウザトラフィックはリモートホストから送信されます。\n\nFlags:\n --name <title> 任意のワークスペースタイトル\n --port <n> SSH ポート\n --identity <path> SSH identity ファイルパス\n -A, --forward-agent 呼び出し元の SSH エージェントを転送します。ssh_config の ForwardAgent yes も尊重します\n -a, --no-forward-agent このワークスペースでは SSH エージェント転送を無効にします\n --ssh-option <opt> 追加の SSH -o オプション(繰り返し可)\n --inherit-env 古い cmux コンテキストを除外して呼び出し元の環境を転送します\n --window <id|ref|index> 管理対象ワークスペースのターゲットウィンドウ\n --no-focus ワークスペースを作成しますが切り替えません\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "km": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nបង្កើត workspace ថ្មី សម្គាល់វាជា remote-SSH ហើយចាប់ផ្តើមសម័យ SSH នៅក្នុង workspace នោះ។\ncmux ក៏នឹងបង្កើតចំណុចបញ្ចប់ SSH proxy មូលដ្ឋាន ដើម្បីឱ្យចរាចរណ៍ browser ចេញពី host ពីចម្ងាយ។\n\nFlags:\n --name <title> ចំណងជើង workspace ស្រេចចិត្ត\n --port <n> ច្រក SSH\n --identity <path> ផ្លូវឯកសារ SSH identity\n -A, --forward-agent បញ្ជូនបន្ត SSH agent របស់អ្នកហៅ; ក៏គោរព ForwardAgent yes ពី ssh_config\n -a, --no-forward-agent បិទការបញ្ជូនបន្ត SSH agent សម្រាប់ workspace នេះ\n --ssh-option <opt> ជម្រើស SSH -o បន្ថែម (អាចប្រើម្តងហើយម្តងទៀត)\n --window <id|ref|index> បង្អួចគោលដៅសម្រាប់ workspace ដែលបានគ្រប់គ្រង\n --no-focus បង្កើត workspace ដោយមិនប្តូរទៅវា\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nបង្កើត workspace ថ្មី សម្គាល់វាជា remote-SSH ហើយចាប់ផ្តើមសម័យ SSH នៅក្នុង workspace នោះ។\ncmux ក៏នឹងបង្កើតចំណុចបញ្ចប់ SSH proxy មូលដ្ឋាន ដើម្បីឱ្យចរាចរណ៍ browser ចេញពី host ពីចម្ងាយ។\n\nFlags:\n --name <title> ចំណងជើង workspace ស្រេចចិត្ត\n --port <n> ច្រក SSH\n --identity <path> ផ្លូវឯកសារ SSH identity\n -A, --forward-agent បញ្ជូនបន្ត SSH agent របស់អ្នកហៅ; ក៏គោរព ForwardAgent yes ពី ssh_config\n -a, --no-forward-agent បិទការបញ្ជូនបន្ត SSH agent សម្រាប់ workspace នេះ\n --ssh-option <opt> ជម្រើស SSH -o បន្ថែម (អាចប្រើម្តងហើយម្តងទៀត)\n --inherit-env បញ្ជូនបរិស្ថានពេញលេញរបស់អ្នកហៅទៅ SSH session ដោយលុបអថេរ cmux socket និង workspace ដែលហួសសម័យ\n --window <id|ref|index> បង្អួចគោលដៅសម្រាប់ workspace ដែលបានគ្រប់គ្រង\n --no-focus បង្កើត workspace ដោយមិនប្តូរទៅវា\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "ko": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\n새 워크스페이스를 만들고 remote-SSH로 표시한 뒤, 그 워크스페이스에서 SSH 세션을 시작합니다.\ncmux는 브라우저 트래픽이 원격 호스트에서 나가도록 로컬 SSH 프록시 엔드포인트도 설정합니다.\n\nFlags:\n --name <title> 선택적 워크스페이스 제목\n --port <n> SSH 포트\n --identity <path> SSH identity 파일 경로\n -A, --forward-agent 호출자의 SSH 에이전트를 전달합니다. ssh_config의 ForwardAgent yes도 존중합니다\n -a, --no-forward-agent 이 워크스페이스에서 SSH 에이전트 전달을 비활성화합니다\n --ssh-option <opt> 추가 SSH -o 옵션(반복 가능)\n --window <id|ref|index> 관리되는 워크스페이스의 대상 창\n --no-focus 워크스페이스를 만들되 전환하지 않습니다\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\n새 워크스페이스를 만들고 remote-SSH로 표시한 뒤, 그 워크스페이스에서 SSH 세션을 시작합니다.\ncmux는 브라우저 트래픽이 원격 호스트에서 나가도록 로컬 SSH 프록시 엔드포인트도 설정합니다.\n\nFlags:\n --name <title> 선택적 워크스페이스 제목\n --port <n> SSH 포트\n --identity <path> SSH identity 파일 경로\n -A, --forward-agent 호출자의 SSH 에이전트를 전달합니다. ssh_config의 ForwardAgent yes도 존중합니다\n -a, --no-forward-agent 이 워크스페이스에서 SSH 에이전트 전달을 비활성화합니다\n --ssh-option <opt> 추가 SSH -o 옵션(반복 가능)\n --inherit-env 호출자의 전체 환경을 SSH 세션에 전달하고 오래된 cmux 소켓 및 워크스페이스 변수를 제거합니다\n --window <id|ref|index> 관리되는 워크스페이스의 대상 창\n --no-focus 워크스페이스를 만들되 전환하지 않습니다\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nOpprett et nytt arbeidsområde, merk det som remote-SSH, og start en SSH-økt i arbeidsområdet.\ncmux oppretter også et lokalt SSH-proxyendepunkt slik at nettlesertrafikk kan gå ut fra den eksterne verten.\n\nFlags:\n --name <title> Valgfri tittel på arbeidsområdet\n --port <n> SSH-port\n --identity <path> Sti til SSH-identitetsfil\n -A, --forward-agent Videresender innkallerens SSH-agent; respekterer også ForwardAgent yes fra ssh_config\n -a, --no-forward-agent Deaktiver SSH-agentvideresending for dette arbeidsområdet\n --ssh-option <opt> Ekstra SSH -o-alternativ (kan gjentas)\n --window <id|ref|index> Målvindu for det administrerte arbeidsområdet\n --no-focus Opprett arbeidsområdet uten å bytte til det\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nOpprett et nytt arbeidsområde, merk det som remote-SSH, og start en SSH-økt i arbeidsområdet.\ncmux oppretter også et lokalt SSH-proxyendepunkt slik at nettlesertrafikk kan gå ut fra den eksterne verten.\n\nFlags:\n --name <title> Valgfri tittel på arbeidsområdet\n --port <n> SSH-port\n --identity <path> Sti til SSH-identitetsfil\n -A, --forward-agent Videresender innkallerens SSH-agent; respekterer også ForwardAgent yes fra ssh_config\n -a, --no-forward-agent Deaktiver SSH-agentvideresending for dette arbeidsområdet\n --ssh-option <opt> Ekstra SSH -o-alternativ (kan gjentas)\n --inherit-env Videresend kallerens fulle miljø til SSH-sesjonen og fjern foreldede cmux-socket- og arbeidsområdevariabler\n --window <id|ref|index> Målvindu for det administrerte arbeidsområdet\n --no-focus Opprett arbeidsområdet uten å bytte til det\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nUtwórz nowy workspace, oznacz go jako remote-SSH i uruchom w nim sesję SSH.\ncmux utworzy także lokalny punkt końcowy proxy SSH, aby ruch przeglądarki wychodził ze zdalnego hosta.\n\nFlags:\n --name <title> Opcjonalny tytuł workspace\n --port <n> Port SSH\n --identity <path> Ścieżka pliku tożsamości SSH\n -A, --forward-agent Przekazuje agenta SSH wywołującego; respektuje też ForwardAgent yes z ssh_config\n -a, --no-forward-agent Wyłącza przekazywanie agenta SSH dla tego workspace\n --ssh-option <opt> Dodatkowa opcja SSH -o (można powtarzać)\n --window <id|ref|index> Okno docelowe dla zarządzanego workspace\n --no-focus Tworzy workspace bez przełączania się do niego\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nUtwórz nowy workspace, oznacz go jako remote-SSH i uruchom w nim sesję SSH.\ncmux utworzy także lokalny punkt końcowy proxy SSH, aby ruch przeglądarki wychodził ze zdalnego hosta.\n\nFlags:\n --name <title> Opcjonalny tytuł workspace\n --port <n> Port SSH\n --identity <path> Ścieżka pliku tożsamości SSH\n -A, --forward-agent Przekazuje agenta SSH wywołującego; respektuje też ForwardAgent yes z ssh_config\n -a, --no-forward-agent Wyłącza przekazywanie agenta SSH dla tego workspace\n --ssh-option <opt> Dodatkowa opcja SSH -o (można powtarzać)\n --inherit-env Przekazuje pełne środowisko wywołującego do sesji SSH, usuwając nieaktualne zmienne gniazda i obszaru roboczego cmux\n --window <id|ref|index> Okno docelowe dla zarządzanego workspace\n --no-focus Tworzy workspace bez przełączania się do niego\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nCrie um novo workspace, marque-o como remote-SSH e inicie uma sessão SSH nesse workspace.\nO cmux também estabelecerá um endpoint de proxy SSH local para que o tráfego do navegador saia pelo host remoto.\n\nFlags:\n --name <title> Título opcional do workspace\n --port <n> Porta SSH\n --identity <path> Caminho do arquivo de identidade SSH\n -A, --forward-agent Encaminha o agente SSH do chamador; também respeita ForwardAgent yes do ssh_config\n -a, --no-forward-agent Desativa o encaminhamento do agente SSH para este workspace\n --ssh-option <opt> Opção SSH -o extra (repetível)\n --window <id|ref|index> Janela de destino para o workspace gerenciado\n --no-focus Cria o workspace sem alternar para ele\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nCrie um novo workspace, marque-o como remote-SSH e inicie uma sessão SSH nesse workspace.\nO cmux também estabelecerá um endpoint de proxy SSH local para que o tráfego do navegador saia pelo host remoto.\n\nFlags:\n --name <title> Título opcional do workspace\n --port <n> Porta SSH\n --identity <path> Caminho do arquivo de identidade SSH\n -A, --forward-agent Encaminha o agente SSH do chamador; também respeita ForwardAgent yes do ssh_config\n -a, --no-forward-agent Desativa o encaminhamento do agente SSH para este workspace\n --ssh-option <opt> Opção SSH -o extra (repetível)\n --inherit-env Encaminha o ambiente completo do chamador para a sessão SSH, removendo variáveis obsoletas de socket e workspace do cmux\n --window <id|ref|index> Janela de destino para o workspace gerenciado\n --no-focus Cria o workspace sem alternar para ele\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nСоздает новый workspace, помечает его как remote-SSH и запускает в нем SSH-сеанс.\ncmux также создаст локальную конечную точку SSH-прокси, чтобы трафик браузера выходил с удаленного хоста.\n\nFlags:\n --name <title> Необязательный заголовок workspace\n --port <n> SSH-порт\n --identity <path> Путь к файлу идентификации SSH\n -A, --forward-agent Пересылает SSH-агент вызывающего процесса; также учитывает ForwardAgent yes из ssh_config\n -a, --no-forward-agent Отключает пересылку SSH-агента для этого workspace\n --ssh-option <opt> Дополнительная опция SSH -o (можно повторять)\n --window <id|ref|index> Целевое окно для управляемого workspace\n --no-focus Создает workspace без переключения на него\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nСоздает новый workspace, помечает его как remote-SSH и запускает в нем SSH-сеанс.\ncmux также создаст локальную конечную точку SSH-прокси, чтобы трафик браузера выходил с удаленного хоста.\n\nFlags:\n --name <title> Необязательный заголовок workspace\n --port <n> SSH-порт\n --identity <path> Путь к файлу идентификации SSH\n -A, --forward-agent Пересылает SSH-агент вызывающего процесса; также учитывает ForwardAgent yes из ssh_config\n -a, --no-forward-agent Отключает пересылку SSH-агента для этого workspace\n --ssh-option <opt> Дополнительная опция SSH -o (можно повторять)\n --inherit-env Передаёт полное окружение вызывающего в SSH-сеанс, удаляя устаревшие переменные сокета и рабочего пространства cmux\n --window <id|ref|index> Целевое окно для управляемого workspace\n --no-focus Создает workspace без переключения на него\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "th": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nสร้าง workspace ใหม่ ทำเครื่องหมายเป็น remote-SSH และเริ่มเซสชัน SSH ใน workspace นั้น\ncmux จะตั้งค่าปลายทาง SSH proxy ภายในเครื่องด้วย เพื่อให้ทราฟฟิกของเบราว์เซอร์ออกจากโฮสต์ระยะไกล\n\nFlags:\n --name <title> ชื่อ workspace ที่ระบุได้\n --port <n> พอร์ต SSH\n --identity <path> พาธไฟล์ SSH identity\n -A, --forward-agent ส่งต่อ SSH agent ของผู้เรียก และเคารพ ForwardAgent yes จาก ssh_config ด้วย\n -a, --no-forward-agent ปิดการส่งต่อ SSH agent สำหรับ workspace นี้\n --ssh-option <opt> ตัวเลือก SSH -o เพิ่มเติม (ระบุซ้ำได้)\n --window <id|ref|index> หน้าต่างเป้าหมายสำหรับ workspace ที่จัดการ\n --no-focus สร้าง workspace โดยไม่สลับไปยัง workspace นั้น\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nสร้าง workspace ใหม่ ทำเครื่องหมายเป็น remote-SSH และเริ่มเซสชัน SSH ใน workspace นั้น\ncmux จะตั้งค่าปลายทาง SSH proxy ภายในเครื่องด้วย เพื่อให้ทราฟฟิกของเบราว์เซอร์ออกจากโฮสต์ระยะไกล\n\nFlags:\n --name <title> ชื่อ workspace ที่ระบุได้\n --port <n> พอร์ต SSH\n --identity <path> พาธไฟล์ SSH identity\n -A, --forward-agent ส่งต่อ SSH agent ของผู้เรียก และเคารพ ForwardAgent yes จาก ssh_config ด้วย\n -a, --no-forward-agent ปิดการส่งต่อ SSH agent สำหรับ workspace นี้\n --ssh-option <opt> ตัวเลือก SSH -o เพิ่มเติม (ระบุซ้ำได้)\n --inherit-env ส่งต่อสภาพแวดล้อมทั้งหมดของผู้เรียกไปยังเซสชัน SSH โดยลบตัวแปร socket และ workspace ของ cmux ที่ล้าสมัยออก\n --window <id|ref|index> หน้าต่างเป้าหมายสำหรับ workspace ที่จัดการ\n --no-focus สร้าง workspace โดยไม่สลับไปยัง workspace นั้น\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nYeni bir workspace oluşturur, onu remote-SSH olarak işaretler ve bu workspace içinde bir SSH oturumu başlatır.\ncmux ayrıca tarayıcı trafiğinin uzak hosttan çıkabilmesi için yerel bir SSH proxy uç noktası kurar.\n\nFlags:\n --name <title> İsteğe bağlı workspace başlığı\n --port <n> SSH portu\n --identity <path> SSH identity dosya yolu\n -A, --forward-agent Çağıranın SSH agent'ını iletir; ssh_config içindeki ForwardAgent yes ayarını da dikkate alır\n -a, --no-forward-agent Bu workspace için SSH agent iletmeyi devre dışı bırakır\n --ssh-option <opt> Ek SSH -o seçeneği (tekrarlanabilir)\n --window <id|ref|index> Yönetilen workspace için hedef pencere\n --no-focus Workspace'i ona geçmeden oluşturur\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nYeni bir workspace oluşturur, onu remote-SSH olarak işaretler ve bu workspace içinde bir SSH oturumu başlatır.\ncmux ayrıca tarayıcı trafiğinin uzak hosttan çıkabilmesi için yerel bir SSH proxy uç noktası kurar.\n\nFlags:\n --name <title> İsteğe bağlı workspace başlığı\n --port <n> SSH portu\n --identity <path> SSH identity dosya yolu\n -A, --forward-agent Çağıranın SSH agent'ını iletir; ssh_config içindeki ForwardAgent yes ayarını da dikkate alır\n -a, --no-forward-agent Bu workspace için SSH agent iletmeyi devre dışı bırakır\n --ssh-option <opt> Ek SSH -o seçeneği (tekrarlanabilir)\n --inherit-env Çağrıcının tam ortamını SSH oturumuna iletir ve eski cmux soket ile çalışma alanı değişkenlerini temizler\n --window <id|ref|index> Yönetilen workspace için hedef pencere\n --no-focus Workspace'i ona geçmeden oluşturur\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nСтворює новий workspace, позначає його як remote-SSH і запускає в ньому SSH-сеанс.\ncmux також створить локальну кінцеву точку SSH-проксі, щоб трафік браузера виходив із віддаленого хоста.\n\nFlags:\n --name <title> Необов’язкова назва workspace\n --port <n> SSH-порт\n --identity <path> Шлях до файлу ідентифікації SSH\n -A, --forward-agent Пересилає SSH-агент процесу-викликача; також враховує ForwardAgent yes із ssh_config\n -a, --no-forward-agent Вимикає пересилання SSH-агента для цього workspace\n --ssh-option <opt> Додаткова опція SSH -o (можна повторювати)\n --window <id|ref|index> Цільове вікно для керованого workspace\n --no-focus Створює workspace без перемикання на нього\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\nСтворює новий workspace, позначає його як remote-SSH і запускає в ньому SSH-сеанс.\ncmux також створить локальну кінцеву точку SSH-проксі, щоб трафік браузера виходив із віддаленого хоста.\n\nFlags:\n --name <title> Необов’язкова назва workspace\n --port <n> SSH-порт\n --identity <path> Шлях до файлу ідентифікації SSH\n -A, --forward-agent Пересилає SSH-агент процесу-викликача; також враховує ForwardAgent yes із ssh_config\n -a, --no-forward-agent Вимикає пересилання SSH-агента для цього workspace\n --ssh-option <opt> Додаткова опція SSH -o (можна повторювати)\n --inherit-env Передає повне середовище викликача до SSH-сеансу, видаляючи застарілі змінні сокета та робочого простору cmux\n --window <id|ref|index> Цільове вікно для керованого workspace\n --no-focus Створює workspace без перемикання на нього\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\n创建一个新工作区,将其标记为 remote-SSH,并在该工作区中启动 SSH 会话。\ncmux 还会建立本地 SSH 代理端点,使浏览器流量可以从远程主机发出。\n\nFlags:\n --name <title> 可选的工作区标题\n --port <n> SSH 端口\n --identity <path> SSH identity 文件路径\n -A, --forward-agent 转发调用方的 SSH agent;也会遵循 ssh_config 中的 ForwardAgent yes\n -a, --no-forward-agent 为此工作区禁用 SSH agent 转发\n --ssh-option <opt> 额外的 SSH -o 选项(可重复)\n --window <id|ref|index> 托管工作区的目标窗口\n --no-focus 创建工作区但不切换到它\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\n创建一个新工作区,将其标记为 remote-SSH,并在该工作区中启动 SSH 会话。\ncmux 还会建立本地 SSH 代理端点,使浏览器流量可以从远程主机发出。\n\nFlags:\n --name <title> 可选的工作区标题\n --port <n> SSH 端口\n --identity <path> SSH identity 文件路径\n -A, --forward-agent 转发调用方的 SSH agent;也会遵循 ssh_config 中的 ForwardAgent yes\n -a, --no-forward-agent 为此工作区禁用 SSH agent 转发\n --ssh-option <opt> 额外的 SSH -o 选项(可重复)\n --inherit-env 清除过时的 cmux socket 和工作区变量后,将调用方的完整环境转发到 SSH 会话\n --window <id|ref|index> 托管工作区的目标窗口\n --no-focus 创建工作区但不切换到它\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\n建立新的工作區,將其標記為 remote-SSH,並在該工作區中啟動 SSH 工作階段。\ncmux 也會建立本機 SSH 代理端點,讓瀏覽器流量可以從遠端主機送出。\n\nFlags:\n --name <title> 選用的工作區標題\n --port <n> SSH 連接埠\n --identity <path> SSH identity 檔案路徑\n -A, --forward-agent 轉送呼叫端的 SSH agent;也會遵循 ssh_config 中的 ForwardAgent yes\n -a, --no-forward-agent 對此工作區停用 SSH agent 轉送\n --ssh-option <opt> 額外的 SSH -o 選項(可重複)\n --window <id|ref|index> 受管理工作區的目標視窗\n --no-focus 建立工作區但不切換到該工作區\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" + "value": "Usage: cmux ssh <destination> [flags] [-- <remote-command-args>]\n\n建立新的工作區,將其標記為 remote-SSH,並在該工作區中啟動 SSH 工作階段。\ncmux 也會建立本機 SSH 代理端點,讓瀏覽器流量可以從遠端主機送出。\n\nFlags:\n --name <title> 選用的工作區標題\n --port <n> SSH 連接埠\n --identity <path> SSH identity 檔案路徑\n -A, --forward-agent 轉送呼叫端的 SSH agent;也會遵循 ssh_config 中的 ForwardAgent yes\n -a, --no-forward-agent 對此工作區停用 SSH agent 轉送\n --ssh-option <opt> 額外的 SSH -o 選項(可重複)\n --inherit-env 清除過時的 cmux socket 和工作區變數後,將呼叫端的完整環境轉發至 SSH 工作階段\n --window <id|ref|index> 受管理工作區的目標視窗\n --no-focus 建立工作區但不切換到該工作區\n\nExample:\n cmux ssh dev@my-host\n cmux ssh dev@my-host --name \"gpu-box\" --port 2222 --identity ~/.ssh/id_ed25519\n cmux ssh dev@my-host --forward-agent\n cmux ssh dev@my-host --ssh-option UserKnownHostsFile=/dev/null --ssh-option StrictHostKeyChecking=no" } } } diff --git a/Sources/GhosttyTerminalView.swift b/Sources/GhosttyTerminalView.swift index a9fb3d4fc239..5f233704edaf 100644 --- a/Sources/GhosttyTerminalView.swift +++ b/Sources/GhosttyTerminalView.swift @@ -6281,7 +6281,8 @@ final class TerminalSurface: Identifiable, ObservableObject { } if let cliBinPath = Bundle.main.resourceURL?.appendingPathComponent("bin").path { - let currentPath = env["PATH"] + let currentPath = initialEnvironmentOverrides["PATH"] + ?? env["PATH"] ?? getenv("PATH").map { String(cString: $0) } ?? ProcessInfo.processInfo.environment["PATH"] ?? "" diff --git a/cmux.xcodeproj/project.pbxproj b/cmux.xcodeproj/project.pbxproj index 095aef60cadc..991b6455ef38 100644 --- a/cmux.xcodeproj/project.pbxproj +++ b/cmux.xcodeproj/project.pbxproj @@ -611,7 +611,7 @@ 619D509BC9B1EA946CBD6A8A /* WorkspaceRuntimeSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9960CC3992F3C44489E7627C /* WorkspaceRuntimeSettings.swift */; }; F0F0A001A1B2C3D4E5F60718 /* WorkspaceSidebarScrollUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0F0A002A1B2C3D4E5F60718 /* WorkspaceSidebarScrollUITests.swift */; }; 6B524A0CB34FD46A771335AB /* WorkspaceSplitStartupCommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71F8ED92A4B55D34BE6A0668 /* WorkspaceSplitStartupCommandTests.swift */; }; - F6120000A1B2C3D4E5F60718 /* WorkspaceSSHFishShellTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6120001A1B2C3D4E5F60718 /* WorkspaceSSHFishShellTests.swift */; }; + F6120000A1B2C3D4E5F60718 /* WorkspaceSSHTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6120001A1B2C3D4E5F60718 /* WorkspaceSSHTests.swift */; }; FA000000A1B2C3D4E5F60718 /* WorkspaceStressProfileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA000001A1B2C3D4E5F60718 /* WorkspaceStressProfileTests.swift */; }; D7AB34400000000000000001 /* WorkspaceSurfaceConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7AB34400000000000000002 /* WorkspaceSurfaceConfig.swift */; }; C0DE32470000000000000003 /* WorkspaceSurfaceIdentifierClipboardText.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DE32470000000000000004 /* WorkspaceSurfaceIdentifierClipboardText.swift */; }; @@ -1255,7 +1255,7 @@ 9960CC3992F3C44489E7627C /* WorkspaceRuntimeSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App/WorkspaceRuntimeSettings.swift; sourceTree = "<group>"; }; F0F0A002A1B2C3D4E5F60718 /* WorkspaceSidebarScrollUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspaceSidebarScrollUITests.swift; sourceTree = "<group>"; }; 71F8ED92A4B55D34BE6A0668 /* WorkspaceSplitStartupCommandTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspaceSplitStartupCommandTests.swift; sourceTree = "<group>"; }; - F6120001A1B2C3D4E5F60718 /* WorkspaceSSHFishShellTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspaceSSHFishShellTests.swift; sourceTree = "<group>"; }; + F6120001A1B2C3D4E5F60718 /* WorkspaceSSHTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspaceSSHTests.swift; sourceTree = "<group>"; }; FA000001A1B2C3D4E5F60718 /* WorkspaceStressProfileTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspaceStressProfileTests.swift; sourceTree = "<group>"; }; D7AB34400000000000000002 /* WorkspaceSurfaceConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspaceSurfaceConfig.swift; sourceTree = "<group>"; }; C0DE32470000000000000004 /* WorkspaceSurfaceIdentifierClipboardText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspaceSurfaceIdentifierClipboardText.swift; sourceTree = "<group>"; }; @@ -1877,7 +1877,7 @@ F6001001A1B2C3D4E5F60718 /* ShortcutUnbindingTests.swift */, F6100001A1B2C3D4E5F60718 /* WorkspaceRemoteConnectionTests.swift */, F6355601A1B2C3D4E5F60718 /* SSHStartupSignalLifecycleTests.swift */, - F6120001A1B2C3D4E5F60718 /* WorkspaceSSHFishShellTests.swift */, + F6120001A1B2C3D4E5F60718 /* WorkspaceSSHTests.swift */, F7000001A1B2C3D4E5F60718 /* WorkspaceContentViewVisibilityTests.swift */, F8000001A1B2C3D4E5F60718 /* SocketControlPasswordStoreTests.swift */, F9000001A1B2C3D4E5F60718 /* GhosttyEnsureFocusWindowActivationTests.swift */, @@ -2930,7 +2930,7 @@ DCC935C5F55C1DCB33E25521 /* WorkspacePullRequestSidebarTests.swift in Sources */, F6100000A1B2C3D4E5F60718 /* WorkspaceRemoteConnectionTests.swift in Sources */, 6B524A0CB34FD46A771335AB /* WorkspaceSplitStartupCommandTests.swift in Sources */, - F6120000A1B2C3D4E5F60718 /* WorkspaceSSHFishShellTests.swift in Sources */, + F6120000A1B2C3D4E5F60718 /* WorkspaceSSHTests.swift in Sources */, FA000000A1B2C3D4E5F60718 /* WorkspaceStressProfileTests.swift in Sources */, 6B524A0BA34FD46A771335AB /* WorkspaceUnitTests.swift in Sources */, ); diff --git a/cmuxTests/WorkspaceSSHFishShellTests.swift b/cmuxTests/WorkspaceSSHTests.swift similarity index 75% rename from cmuxTests/WorkspaceSSHFishShellTests.swift rename to cmuxTests/WorkspaceSSHTests.swift index 395e5f79ca9d..18866550578c 100644 --- a/cmuxTests/WorkspaceSSHFishShellTests.swift +++ b/cmuxTests/WorkspaceSSHTests.swift @@ -1,6 +1,6 @@ import XCTest -final class WorkspaceSSHFishShellTests: XCTestCase { +final class WorkspaceSSHTests: XCTestCase { private struct ProcessRunResult { let status: Int32; let stderr: String; let timedOut: Bool } private final class MockSocketServerState: @unchecked Sendable { @@ -13,7 +13,6 @@ final class WorkspaceSSHFishShellTests: XCTestCase { func testSSHBootstrapStartupCommandPassesRemoteInstallScriptAsSingleSSHCommand() throws { let cliPath = try bundledCLIPath() let python3Path = try requireExecutable(["/opt/homebrew/bin/python3", "/usr/local/bin/python3", "/usr/bin/python3"], name: "python3") - let fishExecutable = try requireExecutable(["/opt/homebrew/bin/fish", "/usr/local/bin/fish", "/usr/bin/fish", "/bin/fish"], name: "fish") let socketPath = makeSocketPath("sshboot") let listenerFD = try bindUnixSocket(at: socketPath) let state = MockSocketServerState() @@ -45,6 +44,7 @@ final class WorkspaceSSHFishShellTests: XCTestCase { ok: true, result: [ "workspace_id": workspaceID, + "surface_id": "22222222-2222-2222-2222-222222222222", "window_id": windowID, ] ) @@ -151,7 +151,7 @@ final class WorkspaceSSHFishShellTests: XCTestCase { startupEnvironment["PATH"] = "\(fakeBin.path):/usr/bin:/bin:/usr/sbin:/sbin" startupEnvironment["CMUX_FAKE_SSH_LOG"] = fakeSSHLog.path startupEnvironment["CMUX_TEST_PYTHON3"] = python3Path - startupEnvironment["CMUX_TEST_LOCAL_SHELL"] = fishExecutable + startupEnvironment["CMUX_TEST_LOCAL_SHELL"] = "/bin/sh" startupEnvironment["CMUX_SOCKET_PATH"] = socketPath startupEnvironment["CMUX_WORKSPACE_ID"] = workspaceID startupEnvironment["CMUX_CLI_SENTRY_DISABLED"] = "1" @@ -232,17 +232,6 @@ final class WorkspaceSSHFishShellTests: XCTestCase { 0, "Expected LocalCommand shell snippet to parse cleanly, stderr: \(localCommandSyntaxCheck.stderr)" ) - let fishLocalCommandCheck = runProcess( - executablePath: fishExecutable, - arguments: ["-n", "-c", localCommand], - environment: ProcessInfo.processInfo.environment, - timeout: 5 - ) - XCTAssertEqual( - fishLocalCommandCheck.status, - 0, - "Expected LocalCommand wrapper to parse cleanly when the user's login shell is fish, stderr: \(fishLocalCommandCheck.stderr)" - ) let destinationIndex = try XCTUnwrap(firstInvocation.lastIndex(of: "cmux-macmini")) let remoteCommandArgs = Array(firstInvocation.suffix(from: firstInvocation.index(after: destinationIndex))) @@ -275,18 +264,6 @@ final class WorkspaceSSHFishShellTests: XCTestCase { secondRemoteCommand.contains("cmux_bootstrap_tty=") || secondRemoteCommand.contains("cmux_bootstrap_tty\\\""), "Expected staged remote bootstrap command body in \(secondRemoteCommand)" ) - let remoteFishCommandCheck = runProcess( - executablePath: fishExecutable, - arguments: ["-n", "-c", secondRemoteCommand], - environment: ProcessInfo.processInfo.environment, - timeout: 5 - ) - XCTAssertEqual( - remoteFishCommandCheck.status, - 0, - "Expected staged remote command wrapper to parse cleanly when the remote login shell is fish, stderr: \(remoteFishCommandCheck.stderr)" - ) - XCTAssertEqual(foregroundAuthState.commands.count, 1) let foregroundAuthPayloadData = try XCTUnwrap(foregroundAuthState.commands.first?.data(using: .utf8)) let foregroundAuthPayload = try XCTUnwrap( @@ -298,6 +275,155 @@ final class WorkspaceSSHFishShellTests: XCTestCase { XCTAssertEqual(foregroundAuthParams["foreground_auth_token"] as? String, foregroundAuthToken) } + @MainActor + func testSSHForwardsSafeCallerEnvironmentByDefault() throws { + let captured = try captureSSHWorkspaceCreateParams( + arguments: ["ssh", "work.jumpgate-workspace"], + environmentOverrides: [ + "PATH": "/opt/work/bin:/usr/bin:/bin", + "SHELL": "/opt/homebrew/bin/fish", + "SSH_AUTH_SOCK": "/tmp/fake-ssh-agent.sock", + "WORK_TOKEN": "secret-token", + ] + ) + let initialEnv = try XCTUnwrap(captured["initial_env"] as? [String: String]) + XCTAssertEqual(initialEnv["PATH"], "/opt/work/bin:/usr/bin:/bin") + XCTAssertEqual(initialEnv["SHELL"], "/opt/homebrew/bin/fish") + XCTAssertEqual(initialEnv["SSH_AUTH_SOCK"], "/tmp/fake-ssh-agent.sock") + XCTAssertNil(initialEnv["WORK_TOKEN"]) + } + + @MainActor + func testSSHInheritEnvForwardsCallerEnvironmentAndScrubsCmuxContext() throws { + let workspaceID = "11111111-1111-1111-1111-111111111111" + let surfaceID = "22222222-2222-2222-2222-222222222222" + let captured = try captureSSHWorkspaceCreateParams( + arguments: ["ssh", "--inherit-env", "work.jumpgate-workspace"], + environmentOverrides: [ + "PATH": "/opt/work/bin:/usr/bin:/bin", + "SHELL": "/opt/homebrew/bin/fish", + "SSH_AUTH_SOCK": "/tmp/fake-ssh-agent.sock", + "WORK_TOKEN": "secret-token", + "CMUX_SOCKET": "__SOCKET_PATH__", + "CMUX_WORKSPACE_ID": workspaceID, + "CMUX_SURFACE_ID": surfaceID, + "CMUX_PANEL_ID": surfaceID, + "CMUX_TAB_ID": workspaceID, + "CMUX_PANE_ID": surfaceID, + "CMUX_RELAY_ID": "relay-id-abc", + "CMUX_RELAY_TOKEN": "relay-token-xyz", + "CMUX_BUNDLED_CLI_PATH": "/tmp/fake-tagged-build/bin/cmux", + ] + ) + let initialEnv = try XCTUnwrap(captured["initial_env"] as? [String: String]) + XCTAssertEqual(initialEnv["PATH"], "/opt/work/bin:/usr/bin:/bin") + XCTAssertEqual(initialEnv["SHELL"], "/opt/homebrew/bin/fish") + XCTAssertEqual(initialEnv["SSH_AUTH_SOCK"], "/tmp/fake-ssh-agent.sock") + XCTAssertEqual(initialEnv["WORK_TOKEN"], "secret-token") + XCTAssertNil(initialEnv["CMUX_SOCKET"]) + XCTAssertNil(initialEnv["CMUX_SOCKET_PATH"]) + XCTAssertNil(initialEnv["CMUX_WORKSPACE_ID"]) + XCTAssertNil(initialEnv["CMUX_SURFACE_ID"]) + XCTAssertNil(initialEnv["CMUX_PANEL_ID"]) + XCTAssertNil(initialEnv["CMUX_TAB_ID"]) + XCTAssertNil(initialEnv["CMUX_PANE_ID"]) + XCTAssertNil(initialEnv["CMUX_RELAY_ID"]) + XCTAssertNil(initialEnv["CMUX_RELAY_TOKEN"]) + XCTAssertNil(initialEnv["CMUX_BUNDLED_CLI_PATH"]) + } + + private func captureSSHWorkspaceCreateParams( + arguments: [String], + environmentOverrides: [String: String] + ) throws -> [String: Any] { + let cliPath = try bundledCLIPath() + let socketPath = makeSocketPath("sshenv") + let listenerFD = try bindUnixSocket(at: socketPath) + let state = MockSocketServerState() + let workspaceID = "11111111-1111-1111-1111-111111111111" + let workspaceRef = "workspace:8" + let windowID = "33333333-3333-3333-3333-333333333333" + + defer { + Darwin.close(listenerFD) + unlink(socketPath) + } + + let serverHandled = startMockServer(listenerFD: listenerFD, state: state) { line in + guard let data = line.data(using: .utf8), + let payload = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], + let id = payload["id"] as? String, + let method = payload["method"] as? String else { + return self.v2Response( + id: "unknown", + ok: false, + error: ["code": "unexpected", "message": "Unexpected payload"] + ) + } + + switch method { + case "workspace.create": + return self.v2Response( + id: id, + ok: true, + result: [ + "workspace_id": workspaceID, + "surface_id": "22222222-2222-2222-2222-222222222222", + "window_id": windowID, + ] + ) + case "workspace.rename": + return self.v2Response(id: id, ok: true, result: ["workspace_id": workspaceID]) + case "workspace.remote.configure": + return self.v2Response( + id: id, + ok: true, + result: [ + "workspace_id": workspaceID, + "workspace_ref": workspaceRef, + "remote": [ + "enabled": true, + "state": "disconnected", + ], + ] + ) + case "workspace.select": + return self.v2Response(id: id, ok: true, result: ["workspace_id": workspaceID]) + default: + return self.v2Response( + id: id, + ok: false, + error: ["code": "unexpected", "message": "Unexpected method \(method)"] + ) + } + } + + var environment = ProcessInfo.processInfo.environment + for (key, value) in environmentOverrides { + environment[key] = value == "__SOCKET_PATH__" ? socketPath : value + } + environment["CMUX_SOCKET_PATH"] = socketPath + environment["CMUX_CLI_SENTRY_DISABLED"] = "1" + environment["CMUX_CLAUDE_HOOK_SENTRY_DISABLED"] = "1" + + let result = runProcess( + executablePath: cliPath, + arguments: arguments, + environment: environment, + timeout: 5 + ) + + wait(for: [serverHandled], timeout: 5) + XCTAssertFalse(result.timedOut, result.stderr) + XCTAssertEqual(result.status, 0, result.stderr) + + let requests = try state.commands.map { line -> [String: Any] in + let data = try XCTUnwrap(line.data(using: .utf8)) + return try XCTUnwrap(JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]) + } + return try XCTUnwrap(requests.first { $0["method"] as? String == "workspace.create" }?["params"] as? [String: Any]) + } + private func makeSocketPath(_ name: String) -> String { let shortID = UUID().uuidString.replacingOccurrences(of: "-", with: "").prefix(8) return "/tmp/cli-\(name.prefix(6))-\(shortID).sock" diff --git a/docs/cli-contract.md b/docs/cli-contract.md index 45677e3ff091..b13f1cfbd2b0 100644 --- a/docs/cli-contract.md +++ b/docs/cli-contract.md @@ -98,7 +98,7 @@ Environment: | `move-tab-to-new-workspace` | Move a tab or surface into a newly created workspace. | | `list-workspaces` | List workspaces. | | `new-workspace` | Create a workspace, optionally with cwd, command, description, and layout. | -| `ssh` | Open an SSH-backed workspace. Preserves the caller's live `SSH_AUTH_SOCK` for app-launched OpenSSH processes so `ForwardAgent yes` from ssh_config works normally. Supports `-A` / `--forward-agent` to request forwarding and `-a` / `--no-forward-agent` to disable forwarding for a workspace. Agent forwarding remains opt-in because forwarded agents can be used by processes on the remote host while the SSH session is active. | +| `ssh` | Open an SSH-backed workspace. Forwards `PATH`, `SHELL`, and `SSH_AUTH_SOCK` from the invoking shell by default so ProxyCommand helpers and other tools on the user's shell PATH are reachable. Use `--inherit-env` to forward the full caller environment after scrubbing stale cmux socket and workspace variables. Supports `-A` / `--forward-agent` to request agent forwarding and `-a` / `--no-forward-agent` to disable it; agent forwarding remains opt-in because forwarded agents can be used by processes on the remote host while the SSH session is active. | | `remote-daemon-status` | Print bundled remote daemon version, asset, checksum, and cache status. | | `ssh-session-list` | List persisted SSH PTY sessions for one remote workspace or all remote workspaces. Supports `--json`. | | `ssh-session-attach` | Create a local terminal surface that reattaches to an existing persisted SSH PTY session. | diff --git a/web/app/[locale]/docs/ssh/page.tsx b/web/app/[locale]/docs/ssh/page.tsx index 8adeb52c121c..c267bf8dd7be 100644 --- a/web/app/[locale]/docs/ssh/page.tsx +++ b/web/app/[locale]/docs/ssh/page.tsx @@ -51,6 +51,7 @@ cmux ssh user@remote -i ~/.ssh/id_ed25519`}</CodeBlock> <tr><td><code>-i, --identity</code></td><td>{t("flagIdentity")}</td></tr> <tr><td><code>-o, --ssh-option</code></td><td>{t("flagSshOption")}</td></tr> <tr><td><code>--no-focus</code></td><td>{t("flagNoFocus")}</td></tr> + <tr><td><code>--inherit-env</code></td><td>{t("flagInheritEnv")}</td></tr> </tbody> </table> diff --git a/web/messages/ar.json b/web/messages/ar.json index ba6af0f692ca..97c097a1520c 100644 --- a/web/messages/ar.json +++ b/web/messages/ar.json @@ -1254,6 +1254,7 @@ "flagIdentity": "المسار إلى ملف الهوية", "flagSshOption": "تمرير خيارات SSH التعسفية (على سبيل المثال -o StrictHostKeyChecking=no)", "flagNoFocus": "قم بإنشاء مساحة العمل دون التبديل إليها", + "flagInheritEnv": "إعادة توجيه البيئة الكاملة للمستدعي إلى جلسة SSH مع حذف متغيرات مقبس cmux والمساحة الافتراضية القديمة", "deepLinksTitle": "روابط SSH العميقة", "deepLinksDesc": "استخدم الروابط العميقة لـ cmux SSH عندما يريد موقع ويب أو أداة تقديم زر فتح في cmux. يفتح الرابط cmux، ويعرض رسالة تأكيد، ثم يقوم بتشغيل أمر cmux ssh المكافئ بعد تأكيد المستخدم.", "deepLinksWebFallbackDesc": "استخدم عنوان URL الاحتياطي cmux.com لأزرار موقع الويب. يفتح الرابط الأصلي ويعرض التنزيل إذا لم يتم تثبيت cmux.", diff --git a/web/messages/bs.json b/web/messages/bs.json index 0502d8074454..ba4904903436 100644 --- a/web/messages/bs.json +++ b/web/messages/bs.json @@ -1254,6 +1254,7 @@ "flagIdentity": "Put do datoteke identiteta", "flagSshOption": "Proslijedi proizvoljne SSH opcije (npr. -o StrictHostKeyChecking=no)", "flagNoFocus": "Kreirajte radni prostor bez prelaska na njega", + "flagInheritEnv": "Proslijedi cijelo okruženje pozivatelja SSH sesiji, uklanjajući zastarjele cmux socket i workspace varijable", "deepLinksTitle": "SSH duboke veze", "deepLinksDesc": "Koristite cmux SSH dubinske veze kada web lokacija ili alat želi ponuditi dugme Otvori u cmux. Veza otvara cmux, prikazuje prompt za potvrdu, a zatim pokreće ekvivalentnu cmux ssh naredbu nakon što korisnik potvrdi.", "deepLinksWebFallbackDesc": "Koristite zamjenski URL cmux.com za dugmad web stranice. Otvara izvornu vezu i prikazuje preuzimanje ako cmux nije instaliran.", diff --git a/web/messages/da.json b/web/messages/da.json index bdc22f4fa66b..ba8a8fa8dba7 100644 --- a/web/messages/da.json +++ b/web/messages/da.json @@ -1254,6 +1254,7 @@ "flagIdentity": "Sti til identitetsfil", "flagSshOption": "Bestå vilkårlige SSH-indstillinger (f.eks. -o StrictHostKeyChecking=no)", "flagNoFocus": "Opret arbejdsområdet uden at skifte til det", + "flagInheritEnv": "Videresend kalderens fulde miljø til SSH-sessionen og fjern forældede cmux-socket- og arbejdsrumsvariabler", "deepLinksTitle": "SSH dybe links", "deepLinksDesc": "Brug cmux SSH-dybe links, når et websted eller et værktøj ønsker at tilbyde en Åbn i cmux-knap. Linket åbner cmux, viser en bekræftelsesprompt og kører derefter den tilsvarende cmux ssh-kommando, efter at brugeren har bekræftet.", "deepLinksWebFallbackDesc": "Brug cmux.com reserve-URL til webstedsknapper. Det åbner det oprindelige link og viser download, hvis cmux ikke er installeret.", diff --git a/web/messages/de.json b/web/messages/de.json index 42c9238e4c9f..65ed84050a2a 100644 --- a/web/messages/de.json +++ b/web/messages/de.json @@ -1254,6 +1254,7 @@ "flagIdentity": "Pfad zur Identitätsdatei", "flagSshOption": "Übergeben Sie beliebige SSH-Optionen (z. B. -o StrictHostKeyChecking=no)", "flagNoFocus": "Erstellen Sie den Arbeitsbereich, ohne dorthin zu wechseln", + "flagInheritEnv": "Die vollständige Umgebung des Aufrufers an die SSH-Sitzung weiterleiten und veraltete cmux-Socket- und Workspace-Variablen entfernen", "deepLinksTitle": "SSH-Deep-Links", "deepLinksDesc": "Verwenden Sie cmux-SSH-Deep-Links, wenn eine Website oder ein Tool eine Schaltfläche „In cmux öffnen“ anbieten möchte. Der Link öffnet cmux, zeigt eine Bestätigungsaufforderung an und führt dann den entsprechenden cmux-ssh-Befehl aus, nachdem der Benutzer dies bestätigt hat.", "deepLinksWebFallbackDesc": "Verwenden Sie die Fallback-URL cmux.com für Website-Schaltflächen. Es öffnet den nativen Link und zeigt den Download an, wenn cmux nicht installiert ist.", diff --git a/web/messages/en.json b/web/messages/en.json index b4dfe53c6811..7b734b8507ef 100644 --- a/web/messages/en.json +++ b/web/messages/en.json @@ -1336,6 +1336,7 @@ "flagIdentity": "Path to identity file", "flagSshOption": "Pass arbitrary SSH options (e.g. -o StrictHostKeyChecking=no)", "flagNoFocus": "Create the workspace without switching to it", + "flagInheritEnv": "Forward the caller's full environment to the SSH session, scrubbing stale cmux socket and workspace variables", "deepLinksTitle": "SSH deep links", "deepLinksDesc": "Use cmux SSH deep links when a website or tool wants to offer an Open in cmux button. The link opens cmux, shows a confirmation prompt, then runs the equivalent cmux ssh command after the user confirms.", "deepLinksWebFallbackDesc": "Use the cmux.com fallback URL for website buttons. It opens the native link and shows the download if cmux is not installed.", diff --git a/web/messages/es.json b/web/messages/es.json index 6ade2357204a..d74bf2189f7d 100644 --- a/web/messages/es.json +++ b/web/messages/es.json @@ -1254,6 +1254,7 @@ "flagIdentity": "Ruta al archivo de identidad", "flagSshOption": "Pasar opciones SSH arbitrarias (por ejemplo, -o StrictHostKeyChecking=no)", "flagNoFocus": "Cree el espacio de trabajo sin cambiar a él", + "flagInheritEnv": "Reenviar el entorno completo del invocador a la sesión SSH, eliminando las variables obsoletas de socket y espacio de trabajo de cmux", "deepLinksTitle": "Enlaces profundos SSH", "deepLinksDesc": "Utilice enlaces profundos SSH de cmux cuando un sitio web o herramienta quiera ofrecer un botón Abrir en cmux. El enlace abre cmux, muestra un mensaje de confirmación y luego ejecuta el comando cmux ssh equivalente después de que el usuario confirma.", "deepLinksWebFallbackDesc": "Utilice la URL alternativa de cmux.com para los botones del sitio web. Abre el enlace nativo y muestra la descarga si cmux no está instalado.", diff --git a/web/messages/fr.json b/web/messages/fr.json index 601523948ae9..d24bdb9015b1 100644 --- a/web/messages/fr.json +++ b/web/messages/fr.json @@ -1254,6 +1254,7 @@ "flagIdentity": "Chemin d'accès au fichier d'identité", "flagSshOption": "Passez des options SSH arbitraires (par exemple -o StrictHostKeyChecking=no)", "flagNoFocus": "Créez l'espace de travail sans y accéder", + "flagInheritEnv": "Transmettre l'environnement complet de l'appelant à la session SSH en supprimant les variables de socket et d'espace de travail cmux obsolètes", "deepLinksTitle": "Liens profonds SSH", "deepLinksDesc": "Utilisez les liens profonds cmux SSH lorsqu'un site Web ou un outil souhaite proposer un bouton Ouvrir dans cmux. Le lien ouvre cmux, affiche une invite de confirmation, puis exécute la commande cmux ssh équivalente après confirmation de l'utilisateur.", "deepLinksWebFallbackDesc": "Utilisez l'URL de secours cmux.com pour les boutons du site Web. Il ouvre le lien natif et affiche le téléchargement si cmux n'est pas installé.", diff --git a/web/messages/it.json b/web/messages/it.json index 26374beedd65..3a65b8e615f3 100644 --- a/web/messages/it.json +++ b/web/messages/it.json @@ -1254,6 +1254,7 @@ "flagIdentity": "Percorso del file di identità", "flagSshOption": "Passa opzioni SSH arbitrarie (ad esempio -o StrictHostKeyChecking=no)", "flagNoFocus": "Crea l'area di lavoro senza passare ad essa", + "flagInheritEnv": "Inoltra l'ambiente completo del chiamante alla sessione SSH, rimuovendo le variabili obsolete di socket e workspace di cmux", "deepLinksTitle": "Collegamenti diretti SSH", "deepLinksDesc": "Utilizza i collegamenti diretti cmux SSH quando un sito Web o uno strumento desidera offrire un pulsante Apri in cmux. Il collegamento apre cmux, mostra una richiesta di conferma, quindi esegue il comando cmux ssh equivalente dopo la conferma dell'utente.", "deepLinksWebFallbackDesc": "Utilizzare l'URL di fallback cmux.com per i pulsanti del sito Web. Apre il collegamento nativo e mostra il download se cmux non è installato.", diff --git a/web/messages/ja.json b/web/messages/ja.json index 56e8e296364a..1b07ece6a668 100644 --- a/web/messages/ja.json +++ b/web/messages/ja.json @@ -1494,6 +1494,7 @@ "flagIdentity": "ID ファイルへのパス", "flagSshOption": "任意の SSH オプションを渡します (例: -o StrictHostKeyChecking=no)", "flagNoFocus": "ワークスペースに切り替えずに作成する", + "flagInheritEnv": "古いcmuxソケットおよびワークスペース変数を除いた呼び出し元の環境をSSHセッションに転送する", "deepLinksTitle": "SSHディープリンク", "deepLinksDesc": "Web サイトまたはツールで [cmux で開く] ボタンを提供する必要がある場合は、cmux SSH ディープ リンクを使用します。リンクにより cmux が開き、確認プロンプトが表示され、ユーザーが確認した後に同等の cmux ssh コマンドが実行されます。", "deepLinksWebFallbackDesc": "Web サイトのボタンには cmux.com フォールバック URL を使用します。 cmux がインストールされていない場合は、ネイティブ リンクが開き、ダウンロードが表示されます。", diff --git a/web/messages/km.json b/web/messages/km.json index 942f52e964b7..de94761b56b1 100644 --- a/web/messages/km.json +++ b/web/messages/km.json @@ -1254,6 +1254,7 @@ "flagIdentity": "ផ្លូវទៅកាន់ឯកសារអត្តសញ្ញាណ", "flagSshOption": "ឆ្លងកាត់ជម្រើស SSH បំពាន (ឧ. -o StrictHostKeyChecking=no)", "flagNoFocus": "បង្កើតកន្លែងធ្វើការដោយមិនចាំបាច់ប្តូរទៅវា។", + "flagInheritEnv": "បញ្ជូនបរិស្ថានពេញលេញរបស់អ្នកហៅទៅកាន់វគ្គ SSH ដោយលុបអថេរ socket និង workspace cmux ដែលហួសសម័យ", "deepLinksTitle": "តំណភ្ជាប់ជ្រៅ SSH", "deepLinksDesc": "ប្រើតំណភ្ជាប់ជ្រៅ cmux SSH នៅពេលដែលគេហទំព័រ ឬឧបករណ៍ចង់ផ្តល់ប៊ូតុង Open in cmux ។ តំណបើក cmux បង្ហាញប្រអប់បញ្ជាក់ បន្ទាប់មកដំណើរការពាក្យបញ្ជា cmux ssh ដែលសមមូលបន្ទាប់ពីអ្នកប្រើប្រាស់បញ្ជាក់។", "deepLinksWebFallbackDesc": "ប្រើ cmux.com fallback URL សម្រាប់ប៊ូតុងគេហទំព័រ។ វាបើកតំណដើម ហើយបង្ហាញការទាញយក ប្រសិនបើ cmux មិនត្រូវបានដំឡើង។", diff --git a/web/messages/ko.json b/web/messages/ko.json index f26afef4dc95..3c9ef884752f 100644 --- a/web/messages/ko.json +++ b/web/messages/ko.json @@ -1254,6 +1254,7 @@ "flagIdentity": "ID 파일 경로", "flagSshOption": "임의 SSH 옵션 전달(예: -o StrictHostKeyChecking=no)", "flagNoFocus": "작업공간으로 전환하지 않고 작업공간 만들기", + "flagInheritEnv": "호출자의 전체 환경을 SSH 세션에 전달하고 오래된 cmux 소켓 및 워크스페이스 변수를 제거합니다", "deepLinksTitle": "SSH 딥링크", "deepLinksDesc": "웹사이트나 도구가 cmux에서 열기 버튼을 제공하려는 경우 cmux SSH 딥 링크를 사용하세요. 링크는 cmux를 열고 확인 프롬프트를 표시한 다음 사용자가 확인한 후 해당 cmux ssh 명령을 실행합니다.", "deepLinksWebFallbackDesc": "웹사이트 버튼에는 cmux.com 대체 URL을 사용하세요. 기본 링크가 열리고 cmux가 설치되지 않은 경우 다운로드가 표시됩니다.", diff --git a/web/messages/no.json b/web/messages/no.json index b65e97fdb4cb..b2cfb289db62 100644 --- a/web/messages/no.json +++ b/web/messages/no.json @@ -1254,6 +1254,7 @@ "flagIdentity": "Sti til identitetsfil", "flagSshOption": "Send vilkårlige SSH-alternativer (f.eks. -o StrictHostKeyChecking=no)", "flagNoFocus": "Lag arbeidsområdet uten å bytte til det", + "flagInheritEnv": "Videresend kallerens fulle miljø til SSH-sesjonen og fjern foreldede cmux-socket- og arbeidsområdevariabler", "deepLinksTitle": "SSH dyplenker", "deepLinksDesc": "Bruk cmux SSH-dypkoblinger når et nettsted eller et verktøy ønsker å tilby en Åpne i cmux-knapp. Koblingen åpner cmux, viser en bekreftelsesmelding, og kjører deretter den tilsvarende cmux ssh-kommandoen etter at brukeren har bekreftet.", "deepLinksWebFallbackDesc": "Bruk cmux.com reserve-URL for nettsideknapper. Den åpner den opprinnelige koblingen og viser nedlastingen hvis cmux ikke er installert.", diff --git a/web/messages/pl.json b/web/messages/pl.json index 41ae00380a12..09a8c86ebbaa 100644 --- a/web/messages/pl.json +++ b/web/messages/pl.json @@ -1254,6 +1254,7 @@ "flagIdentity": "Ścieżka do pliku tożsamości", "flagSshOption": "Przekaż dowolne opcje SSH (np. -o StrictHostKeyChecking=no)", "flagNoFocus": "Utwórz obszar roboczy bez przełączania się na niego", + "flagInheritEnv": "Przekaż pełne środowisko wywołującego do sesji SSH, usuwając nieaktualne zmienne gniazda i obszaru roboczego cmux", "deepLinksTitle": "Głębokie linki SSH", "deepLinksDesc": "Użyj głębokich linków cmux SSH, gdy witryna lub narzędzie chce zaoferować przycisk Otwórz w cmux. Link otwiera cmux, wyświetla monit o potwierdzenie, a następnie uruchamia równoważne polecenie cmux ssh po potwierdzeniu przez użytkownika.", "deepLinksWebFallbackDesc": "Użyj zastępczego adresu URL cmux.com dla przycisków witryny. Otwiera natywny link i pokazuje pobieranie, jeśli cmux nie jest zainstalowany.", diff --git a/web/messages/pt-BR.json b/web/messages/pt-BR.json index 5b8899dfa60f..f0d1d7bf1ef5 100644 --- a/web/messages/pt-BR.json +++ b/web/messages/pt-BR.json @@ -1254,6 +1254,7 @@ "flagIdentity": "Caminho para o arquivo de identidade", "flagSshOption": "Passe opções SSH arbitrárias (por exemplo, -o StrictHostKeyChecking=no)", "flagNoFocus": "Crie o espaço de trabalho sem mudar para ele", + "flagInheritEnv": "Encaminhar o ambiente completo do chamador para a sessão SSH, removendo variáveis obsoletas de socket e workspace do cmux", "deepLinksTitle": "Links diretos SSH", "deepLinksDesc": "Use links diretos SSH do cmux quando um site ou ferramenta quiser oferecer um botão Abrir no cmux. O link abre o cmux, mostra um prompt de confirmação e executa o comando cmux ssh equivalente após a confirmação do usuário.", "deepLinksWebFallbackDesc": "Use o URL substituto cmux.com para botões de sites. Ele abre o link nativo e mostra o download caso o cmux não esteja instalado.", diff --git a/web/messages/ru.json b/web/messages/ru.json index c3ec648bc961..c033c3bd0377 100644 --- a/web/messages/ru.json +++ b/web/messages/ru.json @@ -1254,6 +1254,7 @@ "flagIdentity": "Путь к идентификационному файлу", "flagSshOption": "Передайте произвольные параметры SSH (например, -o StrictHostKeyChecking=no)", "flagNoFocus": "Создайте рабочее пространство, не переключаясь на него", + "flagInheritEnv": "Передать полное окружение вызывающей стороны в SSH-сеанс, удаляя устаревшие переменные сокета и рабочего пространства cmux", "deepLinksTitle": "Глубокие ссылки SSH", "deepLinksDesc": "Используйте глубокие ссылки cmux SSH, когда веб-сайт или инструмент хочет предложить кнопку «Открыть в cmux». Ссылка открывает cmux, отображает запрос на подтверждение, а затем запускает эквивалентную команду cmux ssh после подтверждения пользователя.", "deepLinksWebFallbackDesc": "Используйте резервный URL-адрес cmux.com для кнопок веб-сайта. Он открывает собственную ссылку и показывает загрузку, если cmux не установлен.", diff --git a/web/messages/th.json b/web/messages/th.json index d2ff2e403b1e..83594dd8ab37 100644 --- a/web/messages/th.json +++ b/web/messages/th.json @@ -1254,6 +1254,7 @@ "flagIdentity": "เส้นทางไปยังไฟล์ข้อมูลประจำตัว", "flagSshOption": "ส่งผ่านตัวเลือก SSH ที่กำหนดเอง (เช่น -o StrictHostKeyChecking=no)", "flagNoFocus": "สร้างพื้นที่ทำงานโดยไม่ต้องสลับไปใช้", + "flagInheritEnv": "ส่งต่อสภาพแวดล้อมทั้งหมดของผู้เรียกไปยังเซสชัน SSH โดยลบตัวแปร socket และ workspace ของ cmux ที่ล้าสมัยออก", "deepLinksTitle": "ลิงก์ในรายละเอียด SSH", "deepLinksDesc": "ใช้ลิงก์ในรายละเอียด cmux SSH เมื่อเว็บไซต์หรือเครื่องมือต้องการเสนอปุ่มเปิดใน cmux ลิงก์จะเปิด cmux แสดงพร้อมท์การยืนยัน จากนั้นรันคำสั่ง cmux ssh ที่เทียบเท่ากันหลังจากที่ผู้ใช้ยืนยัน", "deepLinksWebFallbackDesc": "ใช้ URL ทางเลือก cmux.com สำหรับปุ่มเว็บไซต์ จะเปิดลิงก์ดั้งเดิมและแสดงการดาวน์โหลดหากไม่ได้ติดตั้ง cmux", diff --git a/web/messages/tr.json b/web/messages/tr.json index 936677288791..6106acadb378 100644 --- a/web/messages/tr.json +++ b/web/messages/tr.json @@ -1254,6 +1254,7 @@ "flagIdentity": "Kimlik dosyasının yolu", "flagSshOption": "İsteğe bağlı SSH seçeneklerini iletin (ör. -o StrictHostKeyChecking=no)", "flagNoFocus": "Geçiş yapmadan çalışma alanını oluşturun", + "flagInheritEnv": "Çağrıcının tam ortamını SSH oturumuna ilet ve eski cmux soket ile çalışma alanı değişkenlerini temizle", "deepLinksTitle": "SSH derin bağlantıları", "deepLinksDesc": "Bir web sitesi veya araç cmux'da aç düğmesi sunmak istediğinde cmux SSH derin bağlantılarını kullanın. Bağlantı cmux'u açar, bir onay istemi gösterir ve kullanıcı onayladıktan sonra eşdeğer cmux ssh komutunu çalıştırır.", "deepLinksWebFallbackDesc": "Web sitesi düğmeleri için cmux.com yedek URL'sini kullanın. Yerel bağlantıyı açar ve cmux yüklü değilse indirme işlemini gösterir.", diff --git a/web/messages/uk.json b/web/messages/uk.json index b28b525f2bdd..19babb21a3d8 100644 --- a/web/messages/uk.json +++ b/web/messages/uk.json @@ -1339,6 +1339,7 @@ "flagIdentity": "Шлях до файлу ідентифікації", "flagSshOption": "Передавати довільні параметри SSH (наприклад, -o StrictHostKeyChecking=no)", "flagNoFocus": "Створіть робочу область, не переходячи на неї", + "flagInheritEnv": "Передати повне середовище викликаючої сторони до SSH-сеансу, видаляючи застарілі змінні сокета та робочого простору cmux", "deepLinksTitle": "Глибокі посилання SSH", "deepLinksDesc": "Використовуйте глибокі посилання cmux SSH, коли веб-сайт або інструмент хоче запропонувати кнопку «Відкрити в cmux». Посилання відкриває cmux, показує запит на підтвердження, а потім запускає еквівалентну команду cmux ssh після підтвердження користувача.", "deepLinksWebFallbackDesc": "Використовуйте резервну URL-адресу cmux.com для кнопок веб-сайту. Він відкриває рідне посилання та показує завантаження, якщо cmux не встановлено.", diff --git a/web/messages/zh-CN.json b/web/messages/zh-CN.json index fd9635386d06..74486c935c36 100644 --- a/web/messages/zh-CN.json +++ b/web/messages/zh-CN.json @@ -1254,6 +1254,7 @@ "flagIdentity": "身份文件的路径", "flagSshOption": "传递任意 SSH 选项(例如 -o StrictHostKeyChecking=no)", "flagNoFocus": "创建工作区而不切换到它", + "flagInheritEnv": "将调用者的完整环境转发到 SSH 会话,清除过时的 cmux socket 和工作区变量", "deepLinksTitle": "SSH 深层链接", "deepLinksDesc": "当网站或工具想要提供“在 cmux 中打开”按钮时,请使用 cmux SSH 深层链接。该链接将打开 cmux,显示确认提示,然后在用户确认后运行等效的 cmux ssh 命令。", "deepLinksWebFallbackDesc": "使用网站按钮的 cmux.com 后备 URL。如果未安装 cmux,它将打开本机链接并显示下载。", diff --git a/web/messages/zh-TW.json b/web/messages/zh-TW.json index f3af0a278220..9e58c4e8caab 100644 --- a/web/messages/zh-TW.json +++ b/web/messages/zh-TW.json @@ -1254,6 +1254,7 @@ "flagIdentity": "身分檔案的路徑", "flagSshOption": "傳遞任意 SSH 選項(例如 -o StrictHostKeyChecking=no)", "flagNoFocus": "建立工作區而不切換到它", + "flagInheritEnv": "將呼叫者的完整環境轉發至 SSH 工作階段,清除過時的 cmux socket 和工作區變數", "deepLinksTitle": "SSH 深層鏈接", "deepLinksDesc": "當網站或工具想要提供「在 cmux 中開啟」按鈕時,請使用 cmux SSH 深層連結。該連結將開啟 cmux,顯示確認提示,然後在使用者確認後執行等效的 cmux ssh 命令。", "deepLinksWebFallbackDesc": "使用網站按鈕的 cmux.com 後備 URL。如果未安裝 cmux,它將開啟本機連結並顯示下載。",