Skip to main content

setup/
setup.rs

1//! Make sure a harness is installed + signed in before you run it.
2//!
3//! `cargo run --example setup`
4//!
5//! `readiness()` reports whether the CLI is installed and authenticated;
6//! `install()` installs it (npm for claude/codex; a bundled script for bob)
7//! and `login()` runs the CLI's own OAuth (`claude auth login` / `codex
8//! login`, which opens the browser). bob has no `login()` — store its API
9//! key instead (see the `bob-rs` crate).
10
11use std::sync::Arc;
12
13use harness::{Claude, Harness, HarnessError, InstallEvent};
14
15fn main() -> Result<(), HarnessError> {
16    let claude = Claude::new();
17
18    // A logger for the install/login progress stream.
19    let log: harness::InstallCallback = Arc::new(|ev| match ev {
20        InstallEvent::Step { text } => eprintln!("• {text}"),
21        InstallEvent::Stdout { text } | InstallEvent::Stderr { text } => eprintln!("  {text}"),
22        InstallEvent::Done { ok, .. } => eprintln!("done (ok={ok})"),
23    });
24
25    let r = claude.readiness();
26    // Fallible calls return the typed `HarnessError`; `?` propagates it.
27    if !r.installed {
28        claude.install(Arc::clone(&log))?; // npm i -g @anthropic-ai/claude-code
29    }
30    if !r.auth_configured {
31        claude.login(log)?; // `claude auth login` — opens the browser
32    }
33
34    println!("ready: {}", claude.readiness().ready);
35    Ok(())
36}