Expand description
tokio::process wrapping of the claude binary.
Β§I/O architecture
The subprocessβs stdin and stdout each run inside a dedicated
tokio task; the Subprocess surface talks to them over mpsc
channels. Two properties fall out:
- Cancel-safe reads. [
tokio::io::AsyncBufReadExt::read_line] is documented as not cancel-safe, but [mpsc::Receiver::recv] is. Driving stdout through a reader task lets callerstokio::select!overSubprocess::read_linewithout losing already-consumed bytes. - Concurrent writes. Cloning the writer-side mpsc is cheap
and
Send + 'static. TheSubprocess::clone_writerhelper hands out a clonable writer backed by the same writer task, so detached control-request dispatch can write concurrently with the reader without serialising on&mut self.
Re-exportsΒ§
use std::process::Stdio;πuse std::sync::Arc;πuse tokio::io::AsyncBufReadExt;πuse tokio::io::AsyncWriteExt;πuse tokio::io::BufReader;πuse tokio::process::Child;πuse tokio::process::ChildStderr;πuse tokio::process::ChildStdin;πuse tokio::process::ChildStdout;πuse tokio::process::Command;πuse tokio::sync::mpsc;πuse tokio::sync::oneshot;πuse tokio::task::JoinHandle;πuse tracing::debug;πuse tracing::warn;πuse crate::Error;πuse crate::argv::build_args;πuse crate::options::Options;πuse crate::options::WireTee;π
StructsΒ§
- Shared
Writer π - Cloneable writer half of
Subprocess- pushes onto the writer taskβs mpsc. Multiple clones can write concurrently; the writer task serialises onto the childβs stdin in arrival order. - Stderr
Tail π - The most recent drained stderr lines, capped at
STDERR_TAIL_CAPbytes. Oldest lines are dropped first: a failing CLI puts its reason last. - Subprocess
- A live
claudesubprocess driven over channels.
EnumsΒ§
- Closed π
- Why the writer taskβs stdin is gone, kept beside it so a later write names the cause rather than blaming a call that never ran.
- Writer
Cmd π - A write-side command dispatched to the writer task.
ConstantsΒ§
- CLOSE_
WAIT_ TIMEOUT - Default upper bound on
close()wait-for-exit. After this elapses, the child is SIGKILLβd. 5s is generous for a CLI thatβs draining in-flight turns; tests that want to verify the kill path drive against a process that ignores stdin EOF. Public so a consumer timing a wait over a sessionβs teardown can derive it from this budget rather than guess. - LOGGABLE_
FLAGS π - Every flag
build_argscan emit. A user-definedextra_argsname is not covered, except where it collides with one of these - forge routes--effortthat way, so the collision is the common case rather than a corner. - STDERR_
TAIL_ πCAP - Upper bound on the drained stderr retained for
Error::Process. Large enough for a CLI failure message and its context, small enough that a chatty child canβt pin unbounded memory for the life of the process. - STDIN_
WRITE_ πBOUND - How long one write to the CLIβs stdin, and its ack, may take before the write fails.
FunctionsΒ§
- check_
cli_ version - Check that the reported
claudeversion is at leastmin_version. Compares the parsed (major, minor, patch) components numerically. - closed_
stdin π - The error a write gets once the stream is closed, naming why it closed.
- drain_
stderr π - Background drain for the subprocess stderr pipe. Reads lines as UTF-8 (lossy on invalid bytes) and logs each, so the pipe never blocks.
- flag_
names π - The recognised flag names in an argv, and a count of the
--tokens that are neither recognised nor a declaredextra_argsname. - kill_
group π - SIGKILL every process left in
pgid, reporting a failure a caller should tell someone about. - label_
stderr_ πtail - Prefix the retained tail so it reads as the last thing the CLI wrote rather than as the cause. Nothing here can tell whether it is causal: a session whose only stderr was a startup warning attaches that warning to an exit hours later.
- parse_
semver_ πtriple - Parse
"<major>.<minor>.<patch>"(any trailing non-numeric suffix ignored). Missing minor/patch default to 0. - query_
cli_ version - Run
<binary> --versionsynchronously and return the stdout. - spawn_
error π - Name what actually failed. A spawn that cannot find the program and
one that cannot enter
current_dirboth surface asENOENT, so the cwd is re-checked here - this is the only point that holds it. - spawn_
reader_ πtask - spawn_
writer_ πtask - write_
one π - Write one line and flush it, as the writer taskβs unit of work.
- write_
stalled π - A stdin write, or its ack, that outlived
STDIN_WRITE_BOUND.
Type AliasesΒ§
- IoAck π
- Outcome of one writer-task operation. Sent back over a oneshot the caller provides.