Skip to main content

ClaudeBuilder

Struct ClaudeBuilder 

Source
pub struct ClaudeBuilder { /* private fields */ }
Expand description

Builder for creating a Claude client.

§Example

use claude_wrapper::Claude;

let claude = Claude::builder()
    .env("AWS_REGION", "us-west-2")
    .timeout_secs(120)
    .build()?;

Implementations§

Source§

impl ClaudeBuilder

Source

pub fn binary(self, path: impl Into<PathBuf>) -> Self

Set the path to the claude binary.

If not set, the binary is resolved from PATH using which.

Source

pub fn working_dir(self, path: impl Into<PathBuf>) -> Self

Set the working directory for all commands.

The spawned process will use this as its current directory.

Source

pub fn env(self, key: impl Into<String>, value: impl Into<String>) -> Self

Add an environment variable to pass to all commands.

Source

pub fn envs( self, vars: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>, ) -> Self

Add multiple environment variables.

Source

pub fn clear_env(self) -> Self

Clear the inherited environment of every spawned Claude CLI child.

By default, children inherit the parent process environment and env / envs add or replace entries. With this option enabled, the inherited environment is cleared first and only explicitly configured entries are applied. The order in which clear_env, env, and envs are called does not affect the result.

Callers normally need to rebuild a minimal environment including PATH, locale settings, the Claude config directory, and the intended authentication selector.

This controls only the direct child process environment. It is not an operating-system sandbox and does not prevent a same-UID child from reading accessible files or inspecting other processes where the OS permits it.

§Example
use claude_wrapper::Claude;

let claude = Claude::builder()
    .clear_env()
    .env("PATH", "/usr/local/bin:/usr/bin:/bin")
    .env("CLAUDE_CONFIG_DIR", "/srv/claude/config")
    .build()?;
Source

pub fn timeout_secs(self, seconds: u64) -> Self

Set a default timeout for all commands (in seconds).

Source

pub fn timeout(self, duration: Duration) -> Self

Set a default timeout for all commands.

Source

pub fn arg(self, arg: impl Into<String>) -> Self

Add a global argument applied to all commands.

This is an escape hatch for flags not yet covered by the API.

Source

pub fn verbose(self) -> Self

Enable verbose output for all commands (--verbose).

Source

pub fn debug(self) -> Self

Enable debug output for all commands (--debug).

Source

pub fn retry(self, policy: RetryPolicy) -> Self

Set a default retry policy for all commands.

Individual commands can override this via their own retry settings.

§Example
use claude_wrapper::{Claude, RetryPolicy};
use std::time::Duration;

let claude = Claude::builder()
    .retry(RetryPolicy::new()
        .max_attempts(3)
        .initial_backoff(Duration::from_secs(2))
        .exponential()
        .retry_on_timeout(true))
    .build()?;
Source

pub fn tested_cli_version_range(self, min: CliVersion, max: CliVersion) -> Self

Declare the inclusive [min, max] range of claude CLI versions this client has been tested against.

The wrapper does not enforce the range – nothing errors when it’s set wrong. Use Claude::cli_version_status (or its sync mirror) at startup to classify the actually-installed CLI against this declaration; that call returns a typed CliVersionStatus AND emits a tracing::warn! when outside the range. Hosts (claude-server, application code) can additionally surface the status to operators.

§Why this exists

CLI semantics drift across minor / patch releases (e.g. claude agents was repurposed in 2.1.143). The min floor lets us say “we know it’s broken below this”; the max ceiling lets us say “we haven’t verified above this – proceed but expect surprises.”

§You usually do not need this

The crate declares its own range in TESTED_CLI_VERSION_MIN / TESTED_CLI_VERSION_MAX, and version checks use it by default, because only the crate knows what it was built and tested against. Set this only when a host has verified a different range itself.

§Example
use claude_wrapper::{Claude, CliVersion};

let claude = Claude::builder()
    .tested_cli_version_range(CliVersion::new(2, 1, 0), CliVersion::new(2, 1, 999))
    .build()?;
// Run once at startup to log a warning if the CLI is out of range.
let _status = claude.cli_version_status().await?;
Source

pub fn process_group(self, enabled: bool) -> Self

Control whether spawned claude children are placed in their own process group on Unix. Defaults to true.

Own group (the default): cancellation and timeouts kill the child’s whole process tree, but the child no longer shares the host terminal’s process group, so terminal-generated signals (Ctrl-C) do not reach it; terminating a run is the wrapper’s job via drop, timeout, or explicit kill. This is the right contract for supervisors (daemons, MCP servers, worker queues).

Shared group (false): the child stays in the host’s process group, so a terminal Ctrl-C reaches the whole run directly, but a wrapper-side kill only reaches the direct child and any subprocesses it spawned for tool use survive it. This is the right contract for terminal-attached hosts that shell out synchronously and rely on the terminal as the supervisor.

No effect on non-Unix targets.

Source

pub fn kill_grace(self, grace: Duration) -> Self

Grace period between SIGTERM and SIGKILL when a run is killed by a timeout or a duplex shutdown overrun (Unix). Default: none; kills are immediate SIGKILL.

With a grace set, the child’s whole process group gets SIGTERM first so claude can flush its transcript and session state, and SIGKILL follows once the grace elapses. The full grace is waited before the timeout error returns, so keep it short (500ms to 2s). Dropping a future cannot wait, so drop-path cancellation stays immediate SIGKILL, and the grace applies only while the child is in its own process group (see process_group).

Source

pub fn on_spawn(self, observer: SpawnObserver) -> Self

Observe every child this client spawns, at spawn time.

The observer receives a SpawnInfo before the run produces output, which is what makes it useful to a supervisor: recording the pid only once a run finishes leaves nothing to reconcile after a crash mid-run. Fires for one-shot runs, streaming runs, and duplex sessions alike, and on retry it fires once per attempt, since each attempt is a distinct process.

The observer runs inline on the spawning thread, so it must not block. Write a pidfile or push to a channel; do not do I/O that can stall.

§Why a callback rather than a return value

The crash case needs the pid to be durable before the run can be orphaned. A pid on the result type arrives too late for exactly the scenario that motivates recording it.

§Example
use std::sync::Arc;
use claude_wrapper::Claude;

let claude = Claude::builder()
    .on_spawn(Arc::new(|info| {
        eprintln!("spawned pid {} (group {:?})", info.pid, info.pgid);
    }))
    .build()?;
Source

pub fn die_with_parent(self, enabled: bool) -> Self

Ask the kernel to kill spawned children when this process dies.

Linux only. Check die_with_parent_supported rather than assuming; elsewhere this is accepted and does nothing.

§The problem it addresses

Every other cleanup path in this crate is a destructor: kill_on_drop, and the process-group kill on drop, timeout, or stream error. None of them run when this process is SIGKILLed. The child is then reparented to init, and because it leads its own process group (see process_group) terminal signals cannot reach it either. It keeps running, keeps billing, and keeps appending to the session transcript, so a restarted supervisor that resumes the same session id can find itself interleaving with an orphan still writing.

On Linux PR_SET_PDEATHSIG closes that: the kernel delivers SIGKILL to the child the moment its parent dies, with no cooperation from either side.

§What it does not cover
  • Non-Linux targets. macOS has no equivalent. A supervisor that needs the guarantee there has to poll and kill by pid; recording the pid is what on_spawn is for.
  • Re-parenting. The signal fires when the immediate parent dies. If the crate’s caller is itself an intermediate process that exits normally, the child dies then, which is usually what you want but is worth knowing if you daemonize between building the client and spawning.
  • The fork/prctl window. Handled: the hook re-checks getppid() after arming and exits if the parent already changed. Without that check a parent dying in that window leaves exactly the orphan this option exists to prevent.

Off by default, because killing children on parent exit is the right default for a supervisor and the wrong one for a CLI that deliberately backgrounds work.

Source

pub fn build(self) -> Result<Claude>

Build the Claude client, resolving the binary path.

Trait Implementations§

Source§

impl Debug for ClaudeBuilder

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ClaudeBuilder

Source§

fn default() -> ClaudeBuilder

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more