[Desktop] SSH sessions: remote server probes SSH_AUTH_SOCK with empty connections on every spawn, killing a forwarded Windows OpenSSH agent
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Setup: Claude Desktop on Windows 11, Code tab, with an SSH connection to a VS Code Dev Container. The container runs sshd, and VS Code Dev Containers forwards the Windows OpenSSH Authentication Agent into it as /tmp/vscode-ssh-auth-<uuid>.sock. A login-shell profile script exports that socket as SSH_AUTH_SOCK.
Symptom: Within minutes of using a Desktop SSH session, the Windows ssh-agent stops accepting connections. The ssh-agent service stays Running, but \\.\pipe\openssh-ssh-agent disappears. Every agent client then fails: the container, VS Code, and Windows itself. Recovery takes Restart-Service ssh-agent plus a full VS Code restart, and the fault comes back with the next few Desktop git refreshes.
This started with the Desktop update of 2026-09-24 (remote server f6010b97…, ccd-cli 2.1.281). It still reproduces on remote server c8e2f083a63593e9adf0bbebc99debff07a5545f with ccd-cli 2.1.295 (2026-10-12).
Cause: Desktop asks the remote server to spawn processes for session start and for every git status and diff refresh. If a spawn's environment has no SSH_AUTH_SOCK, the server reads the login shell's SSH_AUTH_SOCK and checks that it is alive. It does this by connecting and closing without sending a byte (agentSocketSource.Live, probeLoginShellAgentSocket), once per spawn. One git refresh is 8–17 spawns, so 8–17 empty connections arrive in under a second.
VS Code relays each connection to a connect and close on the Windows named pipe. Win32-OpenSSH's listener does not survive that burst. Process Monitor shows Code.exe CreateFile and CloseFile on \Device\NamedPipe\openssh-ssh-agent with no WriteFile, then PIPE NOT AVAILABLE retries. The agent's FSCTL_PIPE_LISTEN then returns PIPE CLOSING, and the agent stops listening for good.
That listener fragility is a Win32-OpenSSH bug (reproduced on inbox 9.5 and on 10.0.0.0p2-Preview). But this probe is the only client that produces the pattern. Real agent clients such as ssh-add -l and git over ssh send a request on every connection, and they don't trigger it.
Evidence:
- The probe is the server's. A logging relay in front of the socket (SO_PEERCRED) attributed the connections to
~/.claude/remote/srv/<hash>/server --serve: about 9 connections in 0.5 s, 0 bytes each way, about 4 s after each spawn. - Diff refreshes reproduce it. Opening the diff pane three times:
ssh-add -lworks after the first burst and fails withcommunication with agent failedafter the second or third. - It happens in normal use. The agent was alive at 08:37:33 and dead by 08:40:06. Over those 3 minutes the
command=gitspawn count inremote-server.logrose from 8 to 40. - Users can't turn it off.
SpawnParamshas adisableShellAgentSocketfield, but the Windows app never sets it (no reference in itsapp.asar). The session connection forcesForwardAgentoff, so the server never has anSSH_AUTH_SOCKof its own that would skip the probe.
What Should Happen?
A Desktop SSH session should not make the user's SSH agent unusable. Any of these would fix it:
- Probe with a real request or not at all. Check liveness with
SSH2_AGENTC_REQUEST_IDENTITIES(whatssh-add -lsends) rather than a bare connect, or skip the check and let a dead socket fail in the consumer. - Probe less often. Check once and cache the result rather than once per spawned process. Skip app-internal git that never talks to a remote (status, diff).
- Expose an opt-out, for example a per-connection
sshConfigsfield that setsdisableShellAgentSocket.
Error Messages/Logs
~/.claude/remote/run/<id>/remote-server.log
2026/10/12 08:37:09 [shellenv] The login shell exports SSH_AUTH_SOCK=/tmp/vscode-ssh-auth-<uuid>.sock
2026/10/12 08:37:09 [process.Manager] Process … started, PID=…, command=git (8 in the same second)
Container, minutes later:
$ ssh-add -l
error fetching identities: communication with agent failed
Windows:
PS> Test-Path \\.\pipe\openssh-ssh-agent
False
PS> (Get-Service ssh-agent).Status
Running
Steps to Reproduce
- On Windows 11, run the OpenSSH Authentication Agent with a key loaded.
- Open a folder in a VS Code Dev Container that runs sshd. VS Code forwards the agent as
/tmp/vscode-ssh-auth-<uuid>.sock. - In the container, make login shells export that socket, for example
/etc/profile.d/withexport SSH_AUTH_SOCK=/tmp/vscode-ssh-auth-<uuid>.sock. - In Claude Desktop, add an SSH connection to the container's sshd and start a Code session there.
- Open or refresh the diff pane two or three times.
- In the container, run
ssh-add -l: it fails withcommunication with agent failed. On Windows,Test-Path \\.\pipe\openssh-ssh-agentreturnsFalse.
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
The Desktop build before the 2026-09-24 remote-server update (f6010b97…, ccd-cli 2.1.281)
Claude Code Version
ccd-cli 2.1.295 (remote), Claude Desktop 2.31226.1 (857652) 2026-10-09T17:56:07.000Z
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Other
Additional Information
- Related: #29717 (SSH_AUTH_SOCK in Desktop SSH sessions; this probe may be what fixed it), #68057 (a local-side agent probe on macOS), #96661 (app-initiated git uses the agent with no opt-out).
- Host-side workarounds:
- Tested: a container-side relay that connects upstream only on a client's first byte absorbs the probes. We ran it for a day.
- Not yet tested live: sshd
SetEnv SSH_AUTH_SOCK=…should make the server skip the probe, because the spawn environment would then already have the variable.
Both depend on internals, which is why we'd like a supported fix.