agent-harness 0.5.2

Drive LLM coding agents — Claude Code, OpenAI Codex, and local Ollama / OpenAI-compatible models — from Rust behind one trait, with a normalized streaming event vocabulary. Bring your own agent too.
Documentation
//! **Claude Code** — run a prompt and stream the normalized events.
//!
//! ```text
//! cargo run --example claude   # needs the `claude` CLI, installed + signed in
//! ```
//!
//! Every other example uses this same loop. Only the constructor changes.

use harness::{Claude, Harness, Error, RunEvent, RunRequest};

fn main() -> Result<(), Error> {
    // Drives the `claude` CLI. See `codex.rs` for the same loop, one line apart.
    let claude = Claude::new();

    // `run()` starts the run and hands back the events on a channel,
    // so there's no callback/`Sender` plumbing to write by hand. It returns
    // immediately; events arrive on background threads. (`start()` is the push
    // form — forwarding straight onto a Tauri Channel or SSE sink from inside a
    // callback, where a channel would be a wasted hop.)
    //
    // Keep `_handle` to `.cancel()`; dropping it does NOT stop the run.
    let prompt = "In one sentence, what is a Markdown heading?";
    let (_handle, events) = claude.run(RunRequest {
        run_id: "demo".into(),
        prompt: prompt.into(),
        ..Default::default()
    })?;

    // ONE normalized event stream, regardless of the backing CLI. The channel
    // hangs up on its own when the run ends, so this loop terminates without
    // touching the handle:
    for event in events {
        match event {
            RunEvent::Text { delta, .. } => print!("{delta}"), // the answer
            RunEvent::Thinking { delta, .. } => eprint!("{delta}"), // model reasoning
            RunEvent::ToolStart { title, .. } => eprintln!("\n[tool] {title}"),
            RunEvent::Error { message, .. } => eprintln!("\n[error] {message}"),
            RunEvent::Exited { .. } => break,
            _ => {}
        }
    }
    Ok(())
}