SSH remote passes local plugin paths and MCP configs to remote server, causing hang
Bug Description
When connecting to a remote server via SSH, Claude Code passes local macOS plugin paths and MCP server configurations to the remote ccd-cli process. These paths don't exist on the remote machine, causing it to hang indefinitely until the client times out with "Failed to load session".
Root Cause
The remote ccd-cli process is invoked with local paths and configs:
--plugin-dir /Users/<user>/.claude/plugins/cache/claude-plugins-official/pyright-lsp/1.0.0
--plugin-dir /Users/<user>/.claude/plugins/cache/claude-hud/claude-hud/0.0.1
--plugin-dir /Users/<user>/.claude/plugins/cache/claude-plugins-official/ralph-wiggum/15b07b46dab3
--plugin-dir /Users/<user>/.claude/plugins/cache/claude-plugins-official/swift-lsp/1.0.0
--mcp-config {"mcpServers":{"Claude in Chrome":{"type":"sdk","name":"Claude in Chrome"},"mcp-registry":{"type":"sdk","name":"mcp-registry"}}}
These /Users/<user>/... paths don't exist on the remote Linux server, and the MCP servers (Claude in Chrome, mcp-registry) aren't available remotely.
The ccd-cli process consumes ~280MB RAM, opens a socket to the API, but hangs indefinitely — presumably failing to load the non-existent plugins. Eventually the client times out and shows "Failed to load session".
Steps to Reproduce
- Install plugins and/or MCP servers locally (e.g., pyright-lsp, claude-hud, Claude in Chrome)
- Set up an SSH connection to a remote Linux server
- Connect via Claude Code SSH
- Observe
ccd-clion the remote server being passed local plugin paths via--plugin-dir
Expected Behavior
The SSH remote session should either:
- Not pass local plugin paths/MCP configs to the remote machine
- Resolve/sync plugins to the remote before launching
- Gracefully skip missing plugins instead of hanging
Environment
- Local: macOS (Darwin 25.2.0), Claude Code 2.1.42
- Remote: Ubuntu 18.04, x86_64
Related
- #25661 (SSH connection ignores Identity File setting)
Showing cached comments. Read the full discussion on GitHub ↗
7 Comments
Additionally, the error message shown to the user is just "Failed to load session" with no actionable information. There are no client-side logs indicating what went wrong, and the remote
ccd-cliprocess produces no stderr output despite hanging/failing.It took significant debugging (wrapping the binary, inspecting process args, reading remote server logs) to identify the root cause. A more descriptive error — or at minimum logging the
ccd-clicommand-line arguments and any plugin loading failures — would make this much easier to diagnose.Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Should be fixed in the next release, sorry about that.
<img width="395" height="234" alt="Image" src="https://github.com/user-attachments/assets/3e7bf58c-cc60-41e0-b77e-f1a06968623c" />
still seeing this with the update today
Hi any updates on this? Still experiencing this issue for latest version (Claude 1.569.0 (49894a) 2026-04-02T20:01:42.000Z)
Still reproducing as of April 23, 2026. Adding detailed logs that pinpoint the exact components involved — may help prioritize the fix.
Environment
9a871e263f5ad97516c97c8c8129f94990635ae7, built 2026-04-21)ccd-cli/2.1.111Root cause components
The culprits in Desktop's SSH bridge are two internal components visible in
~/Library/Logs/Claude/ssh.log:SshMcpServerManager— tries to start local MCP servers on the remoteRemoteStdioTransport:<ExtensionName>— stdio bridge for each MCPBoth log errors on every single remote session start, whether the user invokes MCP tools or not. They are spawned eagerly.
Reproducible error signature
On every connection attempt, Desktop's log shows exactly these errors (captured from my live logs, multiple occurrences on 2026-04-22 and 2026-04-23):
Even when
nodeIS available on the remote (node v20.20.2 in PATH, verified), the transport still fails:Note:
stderr tail:is empty — node exits silently with code 1 because the JS file path being passed is a local Mac path that doesn't exist on the remote:/Users/<macuser>/Library/Application Support/Claude/Claude Extensions/ant.dir.ant.figma.figma/server/index.jsI verified this by wrapping
/usr/bin/nodeon the remote with a logging shim. The shim captured Desktop invoking node with/Users/...paths that obviously don't exist on a Linux server.Contrast: plugins sync correctly
Interestingly,
RemotePluginSyncworks fine — it copies 209+ files from Mac to remote before spawning ccd-cli, and passes--plugin-dir /home/claude/.claude/remote/plugins/<hash>(remote paths):So the sync-then-remap mechanism already exists for plugins. MCP extensions just aren't using it. They need the same treatment — either sync to remote and remap paths, or skip entirely for SSH sessions.
UX impact
mcp-needs-auth-cache.jsonon the remote may also be involved — I found Google Drive/Gmail/Calendar listed there even though I never configured them on the remote userSuggested fixes (in order of effort)
--disable-remote-mcporskipLocalMcpInRemoteSessionstoggle to settingsRemotePluginSyncmechanism to MCP extensions — sync the MCP server code to remote and remap paths before passing to ccd-cliThis bug has been open since February. Given the rising popularity of SSH-remote workflows (and how many users install Figma/Filesystem MCPs by default), a fix would help a lot of people.
Happy to provide more log excerpts or run further diagnostics if helpful.
Hit a variant of this on an HPC cluster (SLURM/AWS ParallelCluster-style environment) behind a restrictive corporate egress proxy. In our case the remote path did get created (~/.claude/remote/plugins/<hash>/) and the plugin content was correctly copied over — but the SSH session hung indefinitely at "Setting up plugins..." because one plugin's install step (a Python-based plugin with a pyproject.toml) needed network access that the proxy silently drops rather than refuses. No timeout, no error, no indication of which plugin or host was blocking.
Workaround: removing all local plugin marketplaces (/plugin marketplace remove <name> for each) before connecting resolved it — confirms the hang comes from replicating the full local plugin/marketplace set to the remote with no opt-out.
Two separate gaps this suggests:
No timeout/error surfacing per-plugin during SSH session setup
Plugin/marketplace replication to SSH remotes has no independent opt-out from local config