Problem
When the underlying claude CLI subprocess dies (e.g., SIGTERM, exit code 143), claude-code-acp enters a permanently broken state:
- The
ProcessTransport in the Claude Agent SDK detects the exit and sets ready = false
- The
Query async generator finishes or errors
- But the session remains in
this.sessions and claude-code-acp stays alive (due to process.stdin.resume())
- Any subsequent
session/prompt requests on that session fail with ProcessTransport is not ready for writing
- The error surfaces as an unhandled rejection:
Error handling request {
id: 6, jsonrpc: '2.0', method: 'session/prompt', ...
} {
code: -32603,
message: 'Internal error',
data: { details: 'Claude Code process exited with code 143' }
}
Unhandled Rejection at: Promise {
<rejected> Error: ProcessTransport is not ready for writing
The session is dead but claude-code-acp doesn't know it. There's no recovery path.
I'm seeing this frequently. I'm also running a multiplexing proxy in front of claude-code-acp (multiple ACP frontends sharing one agent), which may be contributing — but the core issue is that claude-code-acp has no recovery mechanism regardless of what's killing the subprocess.
Suggested fix
Each call to query() creates a new ProcessTransport and spawns a fresh claude CLI subprocess. The SDK already supports resume and continue options to pick up a conversation from its JSONL session file.
When prompt() detects that the underlying transport has died (e.g., query.next() returns done unexpectedly or throws a transport error), claude-code-acp could:
- Detect the transport death (distinguish it from normal cancellation/completion)
- Create a new
query() with resume: sessionId to spawn a fresh CLI process that replays the conversation
- Update
this.sessions[sessionId] with the new query/input
- Retry the prompt
This would make sessions resilient to transient CLI crashes without requiring the parent process or client to restart everything.
Written by Claude
Problem
When the underlying
claudeCLI subprocess dies (e.g., SIGTERM, exit code 143),claude-code-acpenters a permanently broken state:ProcessTransportin the Claude Agent SDK detects the exit and setsready = falseQueryasync generator finishes or errorsthis.sessionsandclaude-code-acpstays alive (due toprocess.stdin.resume())session/promptrequests on that session fail withProcessTransport is not ready for writingThe session is dead but
claude-code-acpdoesn't know it. There's no recovery path.I'm seeing this frequently. I'm also running a multiplexing proxy in front of
claude-code-acp(multiple ACP frontends sharing one agent), which may be contributing — but the core issue is thatclaude-code-acphas no recovery mechanism regardless of what's killing the subprocess.Suggested fix
Each call to
query()creates a newProcessTransportand spawns a freshclaudeCLI subprocess. The SDK already supportsresumeandcontinueoptions to pick up a conversation from its JSONL session file.When
prompt()detects that the underlying transport has died (e.g.,query.next()returnsdoneunexpectedly or throws a transport error),claude-code-acpcould:query()withresume: sessionIdto spawn a fresh CLI process that replays the conversationthis.sessions[sessionId]with the new query/inputThis would make sessions resilient to transient CLI crashes without requiring the parent process or client to restart everything.
Written by Claude