use clap::Parser;
#[derive(Debug, Parser)]
#[command(name = "capo", version, about = "Capo — a Rust coding agent")]
pub struct Cli {
#[arg(short = 'p', long = "prompt")]
pub prompt: Option<String>,
#[arg(long)]
pub model: Option<String>,
#[arg(long = "provider")]
pub provider: Option<String>,
#[arg(short = 'v', long = "verbose", action = clap::ArgAction::Count)]
pub verbosity: u8,
#[arg(short = 'n', long = "no-context-files")]
pub no_context_files: bool,
#[arg(long = "no-skills")]
pub no_skills: bool,
#[arg(short = 'c', long = "continue")]
pub continue_session: bool,
#[arg(long = "session")]
pub session: Option<String>,
#[arg(short = 'r', long = "resume")]
pub resume: bool,
}
pub enum Mode {
Print(String),
InteractiveStub,
}
impl Cli {
pub fn mode(&self) -> Mode {
if let Some(p) = &self.prompt {
Mode::Print(p.clone())
} else {
Mode::InteractiveStub
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use clap::Parser;
#[test]
fn print_mode_flag() {
let cli = Cli::parse_from(["capo", "-p", "hello"]);
assert!(matches!(cli.mode(), Mode::Print(s) if s == "hello"));
}
#[test]
fn model_flag() {
let cli = Cli::parse_from(["capo", "-p", "x", "--model", "claude-opus-4-7"]);
assert_eq!(cli.model.as_deref(), Some("claude-opus-4-7"));
}
#[test]
fn no_context_files_flag() {
let cli = Cli::parse_from(["capo", "-p", "x", "-n"]);
assert!(cli.no_context_files);
let cli = Cli::parse_from(["capo", "-p", "x"]);
assert!(!cli.no_context_files);
}
#[test]
fn no_skills_flag() {
let cli = Cli::parse_from(["capo", "--no-skills"]);
assert!(cli.no_skills);
let cli = Cli::parse_from(["capo"]);
assert!(!cli.no_skills);
}
#[test]
fn provider_flag_parses() {
let cli = Cli::parse_from(["capo", "--provider", "claude-code"]);
assert_eq!(cli.provider.as_deref(), Some("claude-code"));
}
#[test]
fn session_flags_parse() {
let cli = Cli::parse_from(["capo", "-c"]);
assert!(cli.continue_session);
let cli = Cli::parse_from(["capo", "--session", "01ABC"]);
assert_eq!(cli.session.as_deref(), Some("01ABC"));
let cli = Cli::parse_from(["capo", "-r"]);
assert!(cli.resume);
}
#[test]
fn print_mode_with_continue_flag_parses() {
let cli = Cli::parse_from(["capo", "-p", "x", "-c"]);
assert!(cli.continue_session);
assert_eq!(cli.prompt.as_deref(), Some("x"));
}
}