[BUG] Desktop: Remote SSH session hangs after `Passing plugin(s) to SDK`, no server.spawn RPC ever issued

Resolved 💬 6 comments Opened Apr 24, 2026 by Tama831 Closed Apr 27, 2026

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?

Claude Desktop on macOS 26.3.1 hangs indefinitely when starting a Remote (SSH) Claude Code session.

The hang occurs immediately after Desktop logs [CCD] Passing N plugin(s) to SDK. After that line the SDK never proceeds to spawn the remote CLI — no server.spawn RPC is ever sent to the remote server --bridge. All worker threads sit idle in mach_msg, so it is not a CPU hang but an async await that never resolves.

Reproducible every time, including with:

  • a completely fresh ~/Library/Application Support/Claude/ (full re-login),
  • zero remote MCP connectors (single plugin: skills),
  • empty session persistence.

A direct SSH + claude CLI workflow on the same remote host works normally, which isolates the bug to the Desktop-side SDK → CLI spawn path (not the remote host and not the network itself).

What Should Happen?

After [CCD] Passing N plugin(s) to SDK, the Desktop SDK should either:

  1. issue a server.spawn RPC over the bridge and start ccd-cli on the remote within a few seconds, OR
  2. fail with a clear timeout / error surfaced in the UI so the user can act on it.

An indefinite, silent hang with no error, no timeout, and no UI feedback is the worst failure mode — the user cannot tell whether work is progressing, queued, or dead.

Error Messages/Logs

# Mac side main.log — the hang point (reproduces every attempt)
[info] Starting local session local_XXXXXX in /home/tama/ai-agent-team
[info] [SSH] Using remote spawn function for session ... (cli: /home/tama/.claude/remote/ccd-cli/2.1.111)
[info] [CCD] Using skills plugin at: .../local-agent-mode-sessions/skills-plugin/...
[info] [CCD] Passing 1 plugin(s) to SDK (skills: 1, remote: 0, local: 0)
[info] [EventLogging] Flushing N events                ← periodic flush continues, but no more real progress
[info] LocalSessions.checkGhAvailable: cwd=...          ← periodic repeat only; no session ever starts

# Mac side ssh.log — network-interface flap correlates with hangs
[info] [remote] network-interface change detected; probing SSH controllers
[info] [remote] network-interface change detected; probing SSH controllers
...
# Earlier incident showed a 15-minute handshake timeout from the same cause:
[error] [SSH2Connection] Connection error: Timed out while waiting for handshake
[error] [RemoteServerController] Connection failed (899990ms, trigger: warm_up)

# Remote side bridge RPC log — shows Desktop connects fine, then goes silent:
[Server] RPC request: method=server.capabilities, id=1  → ok
[Server] RPC request: method=server.ping,          id=2  → ok
[Server] RPC request: method=files.list,           id=3-5 → ok
[Server] RPC request: method=files.read,           id=6-7 → ok
(silence — no server.spawn RPC ever arrives)

Steps to Reproduce

  1. macOS 26.3.1 (arm64 Apple Silicon) with Claude Desktop 1.3883.0.
  2. Configure a Remote SSH host for Claude Code (Hetzner VPS, Linux amd64, ~300ms RTT).
  3. Launch Desktop. SSH handshake + bridge channel open in ~15s (logs [BinaryDeployment] Bridge channel opened, Connected to remote server). So far, so good.
  4. Send any prompt (even an empty ping) to kick off a session. Desktop logs:

Starting local session local_XXXXXX in <cwd>
[SSH] Using remote spawn function for session ... (cli: ~/.claude/remote/ccd-cli/2.1.111)
[CCD] Using skills plugin at: ...
[CCD] Passing 1 plugin(s) to SDK (skills: 1, remote: 0, local: 0)

  1. UI spins forever. No error. No further real log entries — only periodic EventLogging Flushing and checkGhAvailable repeats. On the remote, remote-server.log confirms no server.spawn RPC ever arrives.

Persists after each of the following, tried in isolation:

  • clearing ~/Library/Application Support/Claude/local-agent-mode-sessions/
  • clearing claude-code-sessions/
  • clearing claude-code/ and claude-code-vm/ CLI caches
  • clearing local-agent-mode-sessions/skills-plugin/
  • moving the entire ~/Library/Application Support/Claude/ aside and re-logging in
  • disabling every Connector on claude.ai/settings/connectors (plugin load = skills only, remote: 0)
  • swapping the Desktop-deployed binary at ~/.claude/remote/ccd-cli/2.1.111 with the content of the user's native ~/.local/share/claude/versions/2.1.119 (still hangs — rules out "version-specific to 2.1.111")

Claude Model

Not sure / Multiple models

Is this a regression?

Yes, this worked in a previous version

Last Working Version

Unknown — Desktop 1.3883.0 initially worked for Remote SSH sessions to the same host earlier today (and in previous days/weeks); the hang started appearing without an obvious trigger, possibly correlated with a macOS network-interface flap event.

Claude Code Version

2.1.119 (Claude Code) — user's native install used by direct SSH, which works fine 2.1.111 — Desktop-deployed CLI at ~/.claude/remote/ccd-cli/2.1.111, which hangs

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Other

Additional Information

sample(1) of hung Desktop process

All threads idle in mach_msg — no stuck CPU loop, consistent with an unresolved async await:

  • Main thread[NSApplication run] → _nextEventMatchingEventMask → _CFRunLoopRun → mach_msg2_trap (100% idle).
  • libuv-worker × 4 — all in mach_msg.
  • tokio-runtime-worker × 8 — all in mach_msg.
  • V8Worker × 3 — all in mach_msg.

Experiment: CLI version swap rules out version specificity

Replaced the Desktop-deployed ccd-cli/2.1.111 binary with the content of the user's working versions/2.1.119 (filename kept as 2.1.111 so Desktop's [BinaryDeployment] CLI v2.1.111 cached path accepts it). Still hangs identically. This rules out "older CLI version" as the root cause and points at the Desktop → CLI spawn bridge, or at state/handshake happening before the child process is actually invoked — consistent with the fact that no server.spawn RPC is ever sent.

Correlated signal: network-interface flapping

Mac ssh.log shows [remote] network-interface change detected; probing SSH controllers events in the same window as hangs, including during an earlier separate 15-minute SSH handshake timeout (Connection failed (899990ms, trigger: warm_up)). Hypothesis: in-flight SSH/HTTP calls spawned by the SDK are orphaned on interface flap and lack a watchdog timeout, so the SDK's internal await never settles.

Related (but distinct) issues

  • #52734 — Desktop SSH session hangs 3–10 min on "Starting session…" after a utun network-interface flap. Same Desktop 1.3883 and same deployed ccd-cli/2.1.111, but the hang is before Passing plugin(s) to SDK (in [remote] probing SSH controllers) and recovers on its own after a few minutes. This report is different: hang is after Passing plugin(s) to SDK, no server.spawn RPC is ever issued, and it never recovers.
  • #52122 — flagged by auto-triage as a possible duplicate of #52734.

Common thread across all three: Desktop 1.3883 + remote-spawn pipeline on macOS, different phases of the pipeline stuck.

Full logs and diagnostics

Complete main.log, ssh.log, sample output, and remote remote-server.log are available in a private GitHub repo. Happy to share directly with Anthropic engineers — please comment or DM for access.

The logs contain per-account identifiers so are not included inline here.

Environment (extended)

| Component | Version |
|---|---|
| Claude Desktop | 1.3883.0 |
| CCD / Claude Code CLI (Desktop-deployed) | 2.1.111 |
| Claude Code CLI (native, working via direct SSH) | 2.1.119 |
| macOS | 26.3.1 (25D2128), arm64 Apple Silicon (MacBook Air) |
| Node (bundled in Electron) | 24.14.0 |
| Remote host | Linux amd64, ~300ms RTT from client |
| Remote claude-ssh binary | 9a871e263f5ad97516c97c8c8129f94990635ae7 (built 2026-04-21) |

View original on GitHub ↗

This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗