Ports _internal/transport/subprocess_cli.py. Spawns the claude CLI with
--output-format stream-json --input-format stream-json --verbose, then
exposes a split (TransportReader, TransportWriter, TransportHandle) trio.
The split is the key difference from the Python single-class transport:
the reader half owns stdout exclusively and is moved into a background
task; the writer half is Arc/Mutex over stdin and clones freely. A single
mutex over the whole transport would deadlock the moment the reader
blocked on stdin — which it does after each turn.
Other notes:
- find_cli() mirrors the Python search path (PATH, then ~/.npm-global/bin,
/usr/local/bin, ~/.local/bin, ~/node_modules/.bin, ~/.yarn/bin,
~/.claude/local/claude).
- build_command() faithfully ports _build_command() with the v0.1 option
subset.
- Env handling matches Python: filter CLAUDECODE on inherit, set
CLAUDE_CODE_ENTRYPOINT=sdk-rust, layer user env, stamp
CLAUDE_AGENT_SDK_VERSION last.
- Stdout JSON parsing speculatively accumulates until serde_json succeeds
or max_buffer_size (1 MiB default) overflows — same buffer-and-retry
loop as the Python TextReceiveStream path. Non-JSON chatter
([SandboxDebug] etc.) is skipped between frames.
- TransportHandle::close() gives the subprocess a 5s graceful shutdown
window after stdin EOF before SIGKILL, mirroring the #625 fix in the
Python SDK.
- Drop on TransportHandle starts a best-effort kill so abandoned clients
do not leak claude processes.
Unit tests cover the JSON accumulator (full + partial + complete,
non-JSON skip, overflow, multiline split) and the version parser.