claude-code - 💡(How to fix) Fix [BUG] Desktop GUI SSH: opening multiple Claude Code sessions on the same remote host invalidates each other's auth token, all sessions hang [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#54179Fetched 2026-04-29 06:34:10
View on GitHub
Comments
0
Participants
1
Timeline
5
Reactions
0
Author
Participants
Timeline (top)
labeled ×5

When using the macOS Claude Code Desktop app's GUI SSH feature to drive Claude Code on a remote Linux host, opening more than one session against the same remote host causes all sessions to hang indefinitely. With a single session everything works; the second session is what triggers the failure.

The root cause on the remote side is that each new Desktop session spawns a brand-new ~/.claude/remote/server --serve with a brand-new auth token, invalidating the previous --serve's token. Older sessions' bridges are then rejected with Unauthorized request and disconnected.

Error Message

Actual: Neither session returns. The chat UI hangs with no error.

Root Cause

The root cause on the remote side is that each new Desktop session spawns a brand-new ~/.claude/remote/server --serve with a brand-new auth token, invalidating the previous --serve's token. Older sessions' bridges are then rejected with Unauthorized request and disconnected.

Fix Action

Fix / Workaround

  • ✅ 1 Desktop session ↔ 1 remote host: works, indefinitely.
  • ❌ 2+ Desktop sessions ↔ same remote host: all hang.
  • ✅ Workaround for users needing multiple sessions: SSH into the host in a regular terminal and run claude there (terminal CLI does not exhibit token churn).

Code Example

PID    CMD
389774 .../server --serve --token-file token.<hashA>   (10:52)
390185 .../server --serve --token-file token.<hashB>   (10:53)
395604 .../server --serve --token-file token.<hashC>   (10:58)
400203 .../server --serve --token-file token.<hashD>   (11:02)
403026 .../server --serve --token-file token.<hashE>   (11:06)

---

[Server] New connection from: @
[Server] RPC request:  method=server.capabilities, id=1
[Server] RPC response sent: id=1, hasError=false        ← bridge A authenticated, healthy
[Server] RPC request:  method=server.ping, id=2
[Server] RPC response sent: id=2, hasError=false
[Server] New connection from: @                         ← bridge B (a second session) connects
[Server] RPC request:  method=server.ping, id=0         ← fresh client, RPC counter restarts at 0
[Server] Unauthorized request: method=server.ping, id=0 ← rejected: presents the previous --serve's token
[Server] Connection closed: @

---

pkill -f 'claude/remote/server'
    rm -f ~/.claude/remote/rpc.sock ~/.claude/remote/token.*

---

[Server] RPC request:  method=server.ping, id=N   → hasError=false
[Server] RPC request:  method=server.ping, id=N+1 → hasError=false
...
RAW_BUFFERClick to expand / collapse

Summary

When using the macOS Claude Code Desktop app's GUI SSH feature to drive Claude Code on a remote Linux host, opening more than one session against the same remote host causes all sessions to hang indefinitely. With a single session everything works; the second session is what triggers the failure.

The root cause on the remote side is that each new Desktop session spawns a brand-new ~/.claude/remote/server --serve with a brand-new auth token, invalidating the previous --serve's token. Older sessions' bridges are then rejected with Unauthorized request and disconnected.

Environment

ComponentVersion
Local: macOS Claude Code Desktop1.4758.0 (fb266c) 2026-04-24 (latest)
Remote: ccd-cli (bundled & pushed by Desktop client)2.1.119
Remote: ~/.claude/remote/serverclaude-ssh e9237552c61a71aae8c0e586311078ab3275a0f2 (built 2026-04-22)
Remote OSUbuntu 24.04.4 LTS, x86_64, kernel 6.8
ConnectionmacOS Desktop → GUI SSH → single remote Linux host

Steps to reproduce

  1. Launch macOS Claude Code Desktop.
  2. Connect to a remote Linux host via GUI SSH; start a Claude Code session against a project on that host. Confirm replies come back normally. ✅
  3. While the first session is still open, open a second session in the Desktop GUI against the same remote host (any project).
  4. Send a message in either session.

Expected: Both sessions remain functional and independent, or the second session reuses the existing remote bridge.

Actual: Neither session returns. The chat UI hangs with no error.

Root cause (remote-side evidence)

1. Each new Desktop session spawns a new --serve with a new token

Within ~10 minutes of repeated GUI-SSH activity, multiple --serve generations stacked up, each with a different --token-file:

PID    CMD
389774 .../server --serve --token-file token.<hashA>   (10:52)
390185 .../server --serve --token-file token.<hashB>   (10:53)
395604 .../server --serve --token-file token.<hashC>   (10:58)
400203 .../server --serve --token-file token.<hashD>   (11:02)
403026 .../server --serve --token-file token.<hashE>   (11:06)

Multiple --bridge processes existed concurrently, but only the most recent one held a valid token.

2. Unauthorized request in ~/.claude/remote/remote-server.log

[Server] New connection from: @
[Server] RPC request:  method=server.capabilities, id=1
[Server] RPC response sent: id=1, hasError=false        ← bridge A authenticated, healthy
[Server] RPC request:  method=server.ping, id=2
[Server] RPC response sent: id=2, hasError=false
[Server] New connection from: @                         ← bridge B (a second session) connects
[Server] RPC request:  method=server.ping, id=0         ← fresh client, RPC counter restarts at 0
[Server] Unauthorized request: method=server.ping, id=0 ← rejected: presents the previous --serve's token
[Server] Connection closed: @

Unauthorized can only be emitted when a bridge presents a token that the current --serve does not recognize — i.e. at least two clients started against two different --serve generations, which is exactly the multi-session scenario.

3. Downstream: SSH reconnect storm

Once older bridges are kicked, the Desktop client auto-reconnects, spawning yet another --serve, which invalidates the latest token again. journalctl -u ssh shows new Accepted publickey lines every 5–10 seconds for the same source until the user quits the Desktop app. This looks similar to #48530 but is a consequence of token churn here, not a single-session connection flood.

How I recovered (verified)

After hitting this hang, the following sequence reliably recovers the host:

  1. On the Mac: Cmd+Q to fully quit Claude Code Desktop (closing windows alone is not enough — make sure no menu-bar icon is left and no remote-driving process is still alive).

  2. On the remote host: kill the residual server processes and remove the stale socket / token files:

    pkill -f 'claude/remote/server'
    rm -f ~/.claude/remote/rpc.sock ~/.claude/remote/token.*
  3. On the Mac: relaunch Claude Code Desktop and open only one session against the remote host. Send a message — it returns normally.

After step 3, remote-server.log shows a clean, steady heartbeat with no Unauthorized:

[Server] RPC request:  method=server.ping, id=N   → hasError=false
[Server] RPC request:  method=server.ping, id=N+1 → hasError=false
...

ps shows exactly one --serve and one --bridge; journalctl -u ssh shows ~4 Accepted publickey lines per 2 minutes (normal keepalive), no reconnect storm. The single --serve instance keeps its token stable for the lifetime of the session.

Current confirmed working configuration

On the same versions listed above (Desktop 1.4758.0, ccd-cli 2.1.119, server build e923755…), the GUI-SSH feature is only usable with one session per remote host at a time. As long as the user opens exactly one session, it remains stable indefinitely — which strongly suggests the bug is specifically in the per-session bring-up logic on the remote side (spawning a fresh --serve instead of reusing the existing one), not in the steady-state path.

Concretely:

  • ✅ 1 Desktop session ↔ 1 remote host: works, indefinitely.
  • ❌ 2+ Desktop sessions ↔ same remote host: all hang.
  • ✅ Workaround for users needing multiple sessions: SSH into the host in a regular terminal and run claude there (terminal CLI does not exhibit token churn).

Why this is distinct from existing issues

  • #48530 — single-client SSH connection flood; remote-server.log is empty because --serve never starts. Here --serve starts (multiple times) and the log clearly shows Unauthorized.
  • #27658 — multi-session cross-contamination, but explicitly local Desktop only, no SSH.
  • #43252 — "shared connection" hang within a single session's Code/Chat tabs, not multiple sessions.
  • #24317 — OAuth refresh race, unrelated to the per-host --serve token.

Suggested fix direction

The Desktop GUI should either:

  1. Reuse a single --serve + bridge per remote host across all sessions (preferred — also eliminates the SSH reconnect storm), or
  2. When spawning a new --serve is unavoidable, atomically migrate existing bridges to the new token instead of leaving them with a stale one and disconnecting them with Unauthorized.

extent analysis

TL;DR

To fix the issue of multiple GUI SSH sessions hanging when connected to the same remote host, the Desktop GUI should reuse a single --serve and bridge per remote host across all sessions.

Guidance

  • Identify the root cause: multiple --serve instances are spawned with different tokens when new sessions are opened, causing older sessions to be disconnected with Unauthorized request.
  • Verify the issue by checking the ~/.claude/remote/remote-server.log for Unauthorized request errors and the presence of multiple --serve processes.
  • To mitigate the issue, users can work around it by using a regular terminal to SSH into the host and run claude or by ensuring only one session is open per remote host.
  • To fix the issue, the Desktop GUI should be modified to reuse a single --serve and bridge per remote host or migrate existing bridges to a new token when a new --serve is spawned.

Example

No code snippet is provided as the issue is related to the GUI SSH feature and the spawning of --serve processes.

Notes

The suggested fix direction is to reuse a single --serve and bridge per remote host or to migrate existing bridges to a new token when a new --serve is spawned. This would eliminate the SSH reconnect storm and prevent multiple sessions from hanging.

Recommendation

Apply a workaround by ensuring only one session is open per remote host or by using a regular terminal to SSH into the host and run claude. A permanent fix would require modifying the Desktop GUI to reuse a single --serve and bridge per remote host or to migrate existing bridges to a new token when a new --serve is spawned.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix [BUG] Desktop GUI SSH: opening multiple Claude Code sessions on the same remote host invalidates each other's auth token, all sessions hang [1 participants]