🤖 feat: add SSH agent forwarding support#2560
Conversation
Add forwardAgent toggle to SSH workspace runtime so users can forward their local SSH agent to the remote host (enables git clone/push over SSH on remote machines). Changes: - Schema: add forwardAgent boolean to SSH runtime schema - Types: add forwardAgent to ParsedRuntime SSH variant and buildRuntimeConfig - SSHConnectionConfig: add forwardAgent field - runtimeFactory: pass forwardAgent through to SSH transports - OpenSSHTransport: add -A flag to ssh args when forwardAgent is set - SSH2ConnectionPool: pass agentForward:true in connect options - useDraftWorkspaceSettings: persist/restore forwardAgent in SSH config - CreationControls: add 'Forward SSH agent' checkbox for SSH mode
# Conflicts: # src/node/runtime/SSH2ConnectionPool.ts
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6b9e70580d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6b9e70580d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… keys Fix two bugs found by Codex review: 1. In CreationControls.tsx, three call sites that construct SSH runtime objects were missing the forwardAgent field, causing it to be silently reset to false when the runtime was persisted: - Auto-switch to SSH mode (disabled runtime guard) - SSH tab click handler - Host text field onChange handler 2. In both SSH2ConnectionPool.ts and sshConnectionPool.ts, the makeConnectionKey function did not include forwardAgent in the connection pool key. This meant connections with different agent-forwarding settings could incorrectly share a pooled connection.
|
@codex review |
1 similar comment
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d3599eeca5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- writeSshRuntimeConfig: skip persisting forwardAgent when undefined, so mode switches and Coder selection don't overwrite the stored value - CreationControls: pass undefined (not false) for forwardAgent when the current mode isn't SSH, preventing destructive overwrites
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0f0ea99b8e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
When switching from a non-SSH runtime to SSH, forwardAgent was set to undefined in the in-memory state. While writeSshRuntimeConfig correctly skips writing undefined values (preserving persisted state), the in-memory runtime object used for workspace creation lacked forwardAgent, silently disabling agent forwarding. Follow the same fallback pattern used for sshHost: expose sshForwardAgentFallback from useDraftWorkspaceSettings (sourced from lastSshState.forwardAgent), thread it through useCreationWorkspace, and use it in CreationControls when switching to SSH from another mode.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 03df9af259
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4949250edb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
|
@codex review |
3bf5a05 to
a3d77f9
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3bf5a05dc3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 13ffeff458
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const isNonCoderSsh = | ||
| selectedRuntime.mode === RUNTIME_MODE.SSH && | ||
| selectedRuntime.host !== CODER_RUNTIME_PLACEHOLDER | ||
| ? selectedRuntime.host | ||
| : props.sshHostFallback; | ||
| selectedRuntime.host !== CODER_RUNTIME_PLACEHOLDER; |
There was a problem hiding this comment.
Require coder absence in non-Coder SSH detection
The isNonCoderSsh predicate only checks whether the host is not coder://, so Coder runtimes that use a concrete host (for example existing workspaces like name.coder) are treated as plain SSH. In that case this branch pulls sshForwardAgent from selectedRuntime.forwardAgent (typically undefined for Coder flows) instead of sshForwardAgentFallback, so switching from Coder back to SSH can silently clear the user’s forwarding setting and break agent-dependent Git/SSH commands until manually re-enabled.
Useful? React with 👍 / 👎.
Summary
Add SSH agent forwarding support to SSH workspace provider, allowing git operations, nested SSH connections, and other tools that rely on
SSH_AUTH_SOCKto work on remote hosts.Background
SSH workspaces currently don't forward the user's SSH agent to the remote host.
SSH_AUTH_SOCKis read locally only for authenticating Mux's own connection — it's never forwarded to remote sessions. Docker and Devcontainer runtimes already have a "Share credentials" checkbox; SSH workspaces needed an equivalent "Forward SSH agent" toggle.Implementation
Adds a
forwardAgentboolean field threaded through the full stack:forwardAgent: z.boolean().optional()on the SSH runtime schema,forwardAgent?: booleanonParsedRuntimeSSH variantforwardAgentonSSHConnectionConfig, threaded throughruntimeFactory-Aflag added tobuildSSHArgs()when enabledagentForward: truepassed at connection level inSSH2ConnectionPool.connect()(correct placement for the ssh2 library — it's aConnectConfigoption, not per-exec/shell)forwardAgentadded toSshRuntimeConfig/SshRuntimeState, persisted viareadRuntimeConfigFrom/setLastRuntimeConfigCredentialSharingCheckboxpattern9 files changed, +50/-4 lines.
Additionally, all SSH runtime update call sites in
CreationControls.tsxpreserveforwardAgentacross mode switches and host edits, and bothmakeConnectionKeyimplementations (SSH2 and OpenSSH pools) includeforwardAgentin the connection identity to prevent pooled connection reuse with mismatched forwarding state.Generated with
mux• Model:anthropic:claude-opus-4-6• Thinking:high• Cost:$3.74