Repository navigation
Conversation
Add SSH as a desktop-managed server type alongside WSL. The app connects through the system ssh client (SSH config, keys, and agents work as-is), starts `opencode serve` on the remote host over a single connection with a -L tunnel, and manages lifecycle from Settings -> Servers: add with ~/.ssh/config host suggestions, probe, install/update opencode remotely, reconnect/disconnect/open terminal, start on launch. - main: ssh controller, tunnel sidecar with random remote port retry and stdin watchdog cleanup, ssh_config parser, ssh-servers-* IPC - renderer/app: sshServers platform bridge, connection merge, settings rows, add dialog, ssh: startup fallback - i18n: ssh.* and desktop.ssh.error.* keys translated for all locales
|
Hey! Your PR title Please update it to start with one of:
Where See CONTRIBUTING.md for details. |
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
Match the WSL add-server dialog visual language: card-style host list with row separators and hover states, consistent 16px body padding, section title typography, and grouped input+hint spacing.
|
link to issue #33273 |
|
Automated PR Cleanup Thank you for contributing to opencode. Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions. This PR was closed because it matched the following cleanup criteria:
PRs created within the last month are not affected by this cleanup. If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate. Thanks again for taking the time to contribute. |
Issue for this PR
Implements #33273
Type of change
What does this PR do?
Adds native SSH connections to the desktop app, following the same architecture as the existing WSL integration. The
ServerConnection.Sshtype already existed in the app package but had no implementation.How it works: the main process spawns the system
sshclient (so~/.ssh/config, keys, agents and ProxyJump all apply) with a single connection per server:ssh -L 127.0.0.1:<local>:127.0.0.1:<remote> -- <host> sh -se, piping a script over stdin that resolves the remoteopencodebinary (~/.opencode/binor PATH) and execsopencode serveon the forwarded port with per-session basic-auth credentials. The app then talks to the remote server through the tunnel like any other HTTP connection, so chat, PTY terminal (WebSocket) and the server-side directory picker work unchanged.Details worth reviewing:
/dev/nullas fd 0, so the original stdin is saved to fd 9 first — without that the watchdog would kill the server immediately at startup.[user@]host[:port], bracketed/bare IPv6) and always passed after--, so nothing typed can become an ssh option.BatchMode=yeseverywhere: no TTY in the main process, so auth must be non-interactive; failures surface the real ssh stderr plus a hint to runssh <host>once in a terminal, and each server row has an "Open terminal" action.~/.ssh/config(includingInclude), a connect probe, and remote install/update of opencode pinned to the desktop version via the official install script. Servers persist, auto-connect on launch, and fall back to the local sidecar at startup when not ready.ssh.*,desktop.ssh.error.*) added to all 28 locales; parity test passes.How did you verify your code works?
bun test.node:sqliteissue indraft-store.test.ts, present without these changes).tsgo -bclean in both packages; productionelectron-vite buildsucceeds.Screenshots / recordings
Checklist