use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(name = "hanzo", version, about = "Hanzo AI — one CLI + SDK for the whole ecosystem")]
struct Cli {
#[arg(long, global = true, env = "HANZO_BASE_URL")]
base_url: Option<String>,
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand)]
enum Command {
Chat {
#[arg(short, long, default_value = "default")]
model: String,
prompt: String,
},
Embed {
#[arg(short, long, default_value = "default")]
model: String,
text: String,
},
Models,
}
fn build_client(cli: &Cli) -> hanzo::Client {
let mut client = match &cli.base_url {
Some(b) => hanzo::Client::new(b.clone()),
None => hanzo::Client::from_env(),
};
if let Ok(key) = std::env::var("HANZO_API_KEY") {
client = client.with_api_key(key);
}
client
}
fn run(cli: Cli) -> hanzo::Result<()> {
let client = build_client(&cli);
match cli.command {
Command::Chat { model, prompt } => {
let resp = client.engine().chat(&model, &[hanzo::msg("user", prompt)])?;
println!("{}", resp.text());
}
Command::Embed { model, text } => {
let resp = client.engine().embeddings(&model, vec![text])?;
if let Some(e) = resp.data.first() {
let preview: Vec<String> =
e.embedding.iter().take(6).map(|x| format!("{x:.4}")).collect();
println!("dim={} [{}, ...]", e.embedding.len(), preview.join(", "));
}
}
Command::Models => {
for m in client.engine().models()?.data {
println!("{}", m.id);
}
}
}
Ok(())
}
fn main() {
let cli = Cli::parse();
if let Err(e) = run(cli) {
eprintln!("hanzo: error: {e}");
std::process::exit(1);
}
}