[BUG] Claude Desktop SSH Remote: ccd-cli 2.1.128 crashes on initialize when hooks are configured in settings.json

Resolved 💬 3 comments Opened May 12, 2026 by danieleelti Closed May 12, 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 SSH Remote crashes immediately when starting a session on a remote VPS that has hooks configured.

The desktop app connects to the server over SSH successfully, deploys ccd-cli 2.1.128 to ~/.claude/remote/, selects a folder, and creates a session. But the moment any prompt is sent, the ccd-cli process is spawned, receives a control_request of type "initialize" with a hooks payload on stdin (1073-1139 bytes), and immediately exits with code 1. No stderr is surfaced to the UI — only a generic "Claude Code process exited with code 1" error.

This is deterministic and reproducible: every retry crashes the same way.

Critically: blanking the server-side ~/.claude/settings.json to remove all hooks does NOT fix the crash. The new stdin payload still contains "hooks":{"PreT..." — meaning the hooks payload is injected by the Desktop client, not read from the server's settings.json.

The same server, same user, same ~/.claude/ configuration works perfectly with browser-based CloudCLI and with direct ccd-cli invocation in an interactive shell (the "Trust this folder?" wizard appears normally and the session starts).

What Should Happen?

Claude Desktop should successfully start a Claude Code session on the remote server via SSH, regardless of the user's existing hooks configuration (server-side or client-side).

If there's an incompatibility in the hooks payload, the error should be surfaced to the UI with a meaningful message — not a silent exit code 1.

The server's own ccd-cli, when launched manually in an interactive shell, works fine. So the issue is specifically in how Desktop constructs and sends the initialize payload to ccd-cli.

Error Messages/Logs

Server-side log from ~/.claude/remote/remote-server.log (the crash event):


07:25:21 [Server] RPC request: method=process.spawn, id=449
07:25:21 [process.Manager] Process db607e86-d83a-4820-a820-ff8d099a5b35 started, PID=1541637, command=/root/.claude/remote/ccd-cli/2.1.128
07:25:21 [process.Manager] Starting stderr streaming for process db607e86-...
07:25:21 [process.Manager] Starting stdout streaming for process db607e86-...
07:25:22 [Server] RPC request: method=process.stdin, id=450
07:25:22 [process.Manager] WriteStdin called for process db607e86-... with 1139 bytes
07:25:22 [process.Manager] drainStdin db607e86-...: 1139 bytes, preview "{\"request_id\":\"pl44ng4l1ee\",\"type\":\"control_request\",\"request\":{\"subtype\":\"initialize\",\"hooks\":{\"Pre..."
07:25:22 [process.Manager] Process db607e86-... exited with code 1


Note: stderr streaming was started but no stderr lines were captured before the exit. The process died immediately after receiving the initialize payload on stdin.

Verification:
- `~/.claude/remote/ccd-cli/2.1.128 --version` → `2.1.128 (Claude Code)` (binary is healthy)
- Manual interactive launch of the same binary works correctly (Trust folder wizard, session starts)
- Same user, same ~/.claude/, works perfectly with browser-based CloudCLI

Steps to Reproduce

  1. Install Claude Desktop on Windows (claude.com/download), sign in with Claude Max plan.
  2. Use a Linux VPS (root user, fresh Ubuntu/Debian) that already has Claude Code installed via the standard CLI, with a customized ~/.claude/settings.json containing hooks (SessionStart, PreToolUse, PostToolUse — any combination).
  3. In the Desktop app, go to the Code tab → click "Locale" at the bottom → switch to SSH → configure connection: root@<host>, port 22, ed25519 SSH key.
  4. Connection succeeds; the app auto-deploys its remote infrastructure to ~/.claude/remote/ (server binary + ccd-cli/2.1.128).
  5. Click "Seleziona cartella" and pick any directory (e.g. /root/scripts).
  6. Type any prompt (e.g. "What version of Claude Code is installed?") and press Enter.
  7. Result: red error banner — "Claude Code è andato in crash / Claude Code process exited with code 1".
  8. "Riprova" reproduces the crash deterministically.

Additional confirmation steps performed:

  • ~/.claude/remote/ccd-cli/2.1.128 --version → returns "2.1.128 (Claude Code)" — binary is healthy.
  • Manual interactive launch (~/.claude/remote/ccd-cli/2.1.128) → opens Trust folder wizard, accepts input, session starts normally.
  • Blanking server's ~/.claude/settings.json to remove all hooks does NOT fix the crash. The stdin payload sent by Desktop still contains "hooks":{"PreT..." — hooks are injected client-side, not read from server.
  • Same server works perfectly with browser-based CloudCLI using the same settings.json.

Claude Model

Opus

Is this a regression?

No, this never worked

Last Working Version

N/A - first time setup

Claude Code Version

2.1.128 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Other

Additional Information

Context clarifications

  • Client: Claude Desktop GUI (Windows 11), latest version downloaded today from claude.com/download. The crash happens inside the Desktop app's Code tab, NOT in a terminal. The "Terminal/Shell" field above doesn't really apply — I picked the closest option but no terminal is involved on the client side.
  • Server: Linux VPS (Debian/Ubuntu on Elestio, Hetzner backend), root user, fully configured Claude Code environment with ~113 skills, custom GSD hooks framework, multiple MCP servers (n8n, Supabase, Stripe, HubSpot, etc.). All actively used and stable for months via the standard CLI and browser-based CloudCLI.
  • Plan: Claude Max, authenticated via OAuth from the Desktop sign-in flow. No API key is involved.
  • ccd-cli auto-deployed by Desktop on first connection: version 2.1.128, placed at /root/.claude/remote/ccd-cli/2.1.128. The deploy itself works fine (server binary, ccd-cli binary, rpc.sock all created correctly). The crash happens later, when Desktop sends the initialize payload.

Why this is significant

This bug effectively blocks Claude Desktop SSH for any power user who has customized their server-side Claude Code config with hooks — a common setup for autonomous overnight sessions, statusline customization, context monitoring, MCP auth caching, etc.

Workaround attempted (blanking server-side settings.json) does not work, because the hooks payload is constructed and sent by the Desktop client, independent of what the server actually reads. So affected users currently have no way to use Desktop SSH at all, unless they completely strip their setup — which defeats the purpose of running on a remote server in the first place.

Related issue

This appears to be a different failure mode than #46845 (which is about the Trust folder wizard at first run). In my case the trust wizard was resolved by launching ccd-cli manually once. The crash now is on the initialize control_request with hooks, not on first-run setup.

Server log details available

I have full ~/.claude/remote/remote-server.log (~20 KB) showing the complete RPC sequence around the crash. Happy to attach the full file or provide additional traces (strace, ltrace, full stdin payload dump) on request.

View original on GitHub ↗

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