cli-agents
API Reference

run

The run() function, RunHandle, RunResult, and RunStats

run

run()

Launches an agent run. This is the main entry point for the library.

pub fn run(
    opts: RunOptions,
    on_event: Option<Arc<dyn Fn(StreamEvent) + Send + Sync>>,
) -> RunHandle

Parameters:

  • opts — Configuration for the run. See RunOptions.
  • on_event — Optional callback invoked for each streaming event. Called synchronously from the reader task, so keep it fast. The final StreamEvent::Done is always emitted.

Returns: A RunHandle with the result future and cancellation token.

Behavior:

  1. Resolves which CLI to use — either from opts.cli or via auto-discovery (Claude → Codex → Gemini priority)
  2. Spawns the CLI subprocess with the appropriate adapter (Claude, Codex, or Gemini)
  3. Streams stdout line-by-line, parsing provider-specific JSON into unified StreamEvent values
  4. Tracks idle timeout, total timeout, and consecutive tool failures
  5. On completion or cancellation, emits StreamEvent::Done and returns the RunResult
use cli_agents::{run, RunOptions, StreamEvent};
use std::sync::Arc;

let opts = RunOptions {
    task: "What is 2+2?".into(),
    skip_permissions: true,
    ..Default::default()
};

let handle = run(opts, Some(Arc::new(|event: StreamEvent| {
    if let StreamEvent::TextDelta { text } = &event {
        print!("{text}");
    }
})));

let result = handle.result.await.unwrap().unwrap();

RunHandle

Returned by run(). Holds the async result and cancellation mechanism.

pub struct RunHandle {
    pub result: tokio::task::JoinHandle<Result<RunResult>>,
    pub cancel: CancellationToken,
}
FieldTypeDescription
resultJoinHandle<Result<RunResult>>Awaitable future that resolves to the run result
cancelCancellationTokenToken to abort the run — triggers process group kill

Methods

abort()

pub fn abort(&self)

Cancels the running agent by triggering the cancellation token. The process group is killed and the result will have success: false.

let handle = run(opts, None);

// Cancel after 30 seconds
let cancel = handle.cancel.clone();
tokio::spawn(async move {
    tokio::time::sleep(Duration::from_secs(30)).await;
    cancel.cancel();
});

let result = handle.result.await.unwrap().unwrap();

RunResult

The outcome of a completed run.

pub struct RunResult {
    pub success: bool,
    pub text: Option<String>,
    pub exit_code: Option<i32>,
    pub stats: Option<RunStats>,
    pub session_id: Option<String>,
    pub stderr: Option<String>,
    pub cost_usd: Option<f64>,
}
FieldTypeDescription
successboolWhether the run completed successfully
textOption<String>Final text output from the agent
exit_codeOption<i32>CLI process exit code
statsOption<RunStats>Token usage and timing statistics
session_idOption<String>Session ID for resuming the conversation later
stderrOption<String>Captured stderr from the CLI process
cost_usdOption<f64>Estimated cost in USD (Claude only)

RunResult implements Serialize and Deserialize with camelCase field names, making it easy to pass to frontends.

RunStats

Token usage and timing statistics from the run.

pub struct RunStats {
    pub input_tokens: Option<u64>,
    pub output_tokens: Option<u64>,
    pub total_tokens: Option<u64>,
    pub cached_tokens: Option<u64>,
    pub duration_ms: Option<u64>,
    pub tool_calls: Option<u32>,
}
FieldTypeDescription
input_tokensOption<u64>Number of input tokens consumed
output_tokensOption<u64>Number of output tokens generated
total_tokensOption<u64>Total tokens (Gemini)
cached_tokensOption<u64>Tokens served from cache
duration_msOption<u64>Wall-clock duration of the run
tool_callsOption<u32>Number of tool calls made

Not all providers report all fields. Check for None before using.

On this page