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}