You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Remote SSH worktrees (shipped in #407) can be driven from the terminal, but the "Open in…" actions are disabled for them — a remote worktree can't be opened in any GUI editor. Every modern editor Supacode already lists now has a first-class Remote-SSH mode, and Supacode already holds every input needed to launch them against the remote host (real diffs + editing next to the remote agent, not just a terminal). This issue proposes wiring that subset up.
This completes the remote beta rather than adding new surface area: it reuses the local | remote worktree split, the RemoteHost metadata (already sourced from ~/.ssh/config), and the generic CLI-launcher seam from #417/#423.
Motivation
After #407 a remote worktree is a first-class sidebar row with terminal + git + agent orchestration over SSH — but the only way to see the code is the terminal. Meanwhile the major editors all natively open a folder on a remote host over SSH, so Supacode is one launch argument away from a full remote editing session beside the remote agent.
Current behavior
Open / Reveal is deliberately rejected for remote worktrees at the reducer chokepoint:
// supacode/Features/App/Reducer/AppFeature.swift (openWorktreeEffect, ~L1263)
// Open / Reveal target local Finder / editors; a remote SSH path can't be
// reached, so reject it here regardless of the entry point ...
if worktree.host !=nil{
appLogger.info("Ignoring open of remote worktree ...")return.none
}
with matching gates in WorktreeDetailView (canOpenLocally = … host == nil) and the sidebar context menu (.disabled(worktree.host != nil)). This is correct today: for a remote worktree worktree.workingDirectory is a synthetic file:// URL over the remote path (Domain/RepositoryIdentity.swift, doc-commented "never hand it to FileManager"), so handing it to NSWorkspace/Process would open a nonexistent local path.
Proposed behavior
For editors that support Remote-SSH, branch instead of bail and launch the editor's CLI with a remote target:
Zed — zed ssh://[<user>@]<host>[:<port>]/<remotePath> (also accepts scp-style zed ssh://host:~/project and the zed://ssh/… hotlink form). Zed shells out to ssh on PATH and inherits ~/.ssh/config, and auto-provisions its headless server on the remote (nothing to pre-install). Requires Zed ≥ v0.159. (Bonus: Zed dev containers — Stable since Jan 2026, v0.218 — build on this same remote architecture, so a remote + containerized agent workflow is a natural follow-on.)
VS Code family / Cursor / Windsurf — code --remote ssh-remote+<sshHost> <remotePath> (equivalently --folder-uri vscode-remote://ssh-remote+<sshHost><remotePath>).
JetBrains — Gateway link / gateway CLI form.
Editors / apps with no remote mode (Finder, git GUIs, Xcode) stay disabled for remote rows — no behavior change.
The inputs already exist on every remote worktree:
RemoteHost.authority → user@host:port
WorktreeLocation.workingDirectoryPath → the absolute remote path
Where it plugs in
AppFeature.swiftopenWorktreeEffect (~L1263) — the universal chokepoint. The host != nil guard branches to a remote launch for the supported editor subset instead of returning .none.
Clients/Workspace/WorkspaceClient.swift (WorktreeOpener.perform, WorkspaceOpenResolver.resolve) — add an OpenTarget/OpenBehavior that emits the per-editor remote invocation, reusing the cliLauncher seam from Open each worktree in its own Zed window #417/Generalize worktree open targets #423 rather than NSWorkspace.open. (Zed is already wired to launch via its bundled CLI here, so it's the lowest-friction first editor.)
UI gates (WorktreeDetailViewcanOpenLocally, SidebarItemsView.disabled(...)) — relax for the supported editors only.
Host-alias mapping (per-editor, smaller than it looks)
The one wrinkle is how each editor names the remote host:
Zed takes a raw ssh://[user@]host[:port]/path URI and resolves it through ~/.ssh/config itself — so RemoteHost.authority + the remote path map directly, no alias lookup needed. This makes Zed the clean first target.
VS Code / Cursor / Windsurf want ssh-remote+<hostAlias>, where <hostAlias> is a ~/.ssh/configHost entry rather than a raw user@host:port. Since RemoteHost is already sourced from ~/.ssh/config (per Remote repositories over SSH #373/Add remote SSH repositories and worktrees #407), the alias should be recoverable, but the exact mapping wants verification before committing to an arg format.
Scope / non-goals
Editor subset only. No attempt to make Finder, git GUIs, or non-remote editors work over SSH.
No new per-host config knobs. Reuses existing RemoteHost data; nothing to configure beyond the editor being installed with its remote extension.
I'd be happy to contribute a PR implementing this. I'd suggest starting with Zed as the first editor — it's already wired through the cliLauncher seam and its zed ssh://… form resolves ~/.ssh/config directly, so it sidesteps the host-alias mapping — then extending to the VS Code family and JetBrains once the remote-launch path is proven. Happy to align on scope/approach before opening the PR.
Summary
Remote SSH worktrees (shipped in #407) can be driven from the terminal, but the "Open in…" actions are disabled for them — a remote worktree can't be opened in any GUI editor. Every modern editor Supacode already lists now has a first-class Remote-SSH mode, and Supacode already holds every input needed to launch them against the remote host (real diffs + editing next to the remote agent, not just a terminal). This issue proposes wiring that subset up.
This completes the remote beta rather than adding new surface area: it reuses the
local | remoteworktree split, theRemoteHostmetadata (already sourced from~/.ssh/config), and the generic CLI-launcher seam from #417/#423.Motivation
After #407 a remote worktree is a first-class sidebar row with terminal + git + agent orchestration over SSH — but the only way to see the code is the terminal. Meanwhile the major editors all natively open a folder on a remote host over SSH, so Supacode is one launch argument away from a full remote editing session beside the remote agent.
Current behavior
Open / Reveal is deliberately rejected for remote worktrees at the reducer chokepoint:
with matching gates in
WorktreeDetailView(canOpenLocally = … host == nil) and the sidebar context menu (.disabled(worktree.host != nil)). This is correct today: for a remote worktreeworktree.workingDirectoryis a syntheticfile://URL over the remote path (Domain/RepositoryIdentity.swift, doc-commented "never hand it to FileManager"), so handing it toNSWorkspace/Processwould open a nonexistent local path.Proposed behavior
For editors that support Remote-SSH, branch instead of bail and launch the editor's CLI with a remote target:
zed ssh://[<user>@]<host>[:<port>]/<remotePath>(also accepts scp-stylezed ssh://host:~/projectand thezed://ssh/…hotlink form). Zed shells out tosshonPATHand inherits~/.ssh/config, and auto-provisions its headless server on the remote (nothing to pre-install). Requires Zed ≥ v0.159. (Bonus: Zed dev containers — Stable since Jan 2026, v0.218 — build on this same remote architecture, so a remote + containerized agent workflow is a natural follow-on.)code --remote ssh-remote+<sshHost> <remotePath>(equivalently--folder-uri vscode-remote://ssh-remote+<sshHost><remotePath>).gatewayCLI form.The inputs already exist on every remote worktree:
RemoteHost.authority→user@host:portWorktreeLocation.workingDirectoryPath→ the absolute remote pathWhere it plugs in
AppFeature.swiftopenWorktreeEffect(~L1263) — the universal chokepoint. Thehost != nilguard branches to a remote launch for the supported editor subset instead of returning.none.Clients/Workspace/WorkspaceClient.swift(WorktreeOpener.perform,WorkspaceOpenResolver.resolve) — add anOpenTarget/OpenBehaviorthat emits the per-editor remote invocation, reusing thecliLauncherseam from Open each worktree in its own Zed window #417/Generalize worktree open targets #423 rather thanNSWorkspace.open. (Zed is already wired to launch via its bundled CLI here, so it's the lowest-friction first editor.)WorktreeDetailViewcanOpenLocally,SidebarItemsView.disabled(...)) — relax for the supported editors only.Host-alias mapping (per-editor, smaller than it looks)
The one wrinkle is how each editor names the remote host:
ssh://[user@]host[:port]/pathURI and resolves it through~/.ssh/configitself — soRemoteHost.authority+ the remote path map directly, no alias lookup needed. This makes Zed the clean first target.ssh-remote+<hostAlias>, where<hostAlias>is a~/.ssh/configHostentry rather than a rawuser@host:port. SinceRemoteHostis already sourced from~/.ssh/config(per Remote repositories over SSH #373/Add remote SSH repositories and worktrees #407), the alias should be recoverable, but the exact mapping wants verification before committing to an arg format.Scope / non-goals
RemoteHostdata; nothing to configure beyond the editor being installed with its remote extension.Prior art in this repo
OpenWorktreeAction.cliLauncher/AppLauncher), already the path non-NSWorkspacelaunches flow through; Zed already launches via its bundled CLI here.References
zed ssh://…, ≥ v0.159, inherits~/.ssh/config: https://zed.dev/docs/remote-development--remote ssh-remote+…,vscode-remote://): https://code.visualstudio.com/docs/remote/sshContribution
I'd be happy to contribute a PR implementing this. I'd suggest starting with Zed as the first editor — it's already wired through the
cliLauncherseam and itszed ssh://…form resolves~/.ssh/configdirectly, so it sidesteps the host-alias mapping — then extending to the VS Code family and JetBrains once the remote-launch path is proven. Happy to align on scope/approach before opening the PR.