use anyhow::Result;
use clap::{Parser, Subcommand};
pub mod exit_code;
pub mod fold;
pub mod grind;
pub mod init;
pub mod interview;
pub mod plan;
pub mod play;
pub mod prompts;
pub mod rebuy;
pub mod status;
pub mod sweep;
pub use exit_code::ExitCode;
#[derive(Debug, Parser)]
#[command(
name = "pitboss",
version,
about = "Orchestrate coding agents through a phased plan"
)]
pub struct Cli {
#[arg(short = 'v', long = "verbose", action = clap::ArgAction::Count, global = true)]
pub verbose: u8,
#[command(subcommand)]
pub command: Command,
}
impl Cli {
pub fn verbose_filter(&self) -> Option<&'static str> {
match self.verbose {
0 => None,
1 => Some("debug"),
_ => Some("trace"),
}
}
pub fn is_tui_mode(&self) -> bool {
match &self.command {
Command::Play { tui, .. } | Command::Rebuy { tui, .. } => *tui,
Command::Grind(args) => args.tui,
Command::Init
| Command::Plan { .. }
| Command::Status
| Command::Fold { .. }
| Command::Sweep(_)
| Command::Prompts(_) => false,
}
}
}
#[derive(Debug, Subcommand)]
pub enum Command {
Init,
Plan {
goal: String,
#[arg(long)]
force: bool,
#[arg(long)]
interview: bool,
},
#[command(alias = "run")]
Play {
#[arg(long)]
tui: bool,
#[arg(long)]
pr: bool,
#[arg(long = "dry-run")]
dry_run: bool,
#[arg(long = "no-sweep", conflicts_with = "sweep")]
no_sweep: bool,
#[arg(long = "sweep")]
sweep: bool,
},
Status,
#[command(alias = "resume")]
Rebuy {
#[arg(long)]
tui: bool,
#[arg(long)]
pr: bool,
#[arg(long = "dry-run")]
dry_run: bool,
#[arg(long = "no-sweep", conflicts_with = "sweep")]
no_sweep: bool,
#[arg(long = "sweep")]
sweep: bool,
},
#[command(alias = "abort")]
Fold {
#[arg(long)]
checkout_original: bool,
},
Sweep(sweep::SweepArgs),
Prompts(prompts::PromptsArgs),
Grind(grind::GrindArgs),
}
pub async fn dispatch(cli: Cli) -> Result<ExitCode> {
match cli.command {
Command::Init => {
init::run(std::env::current_dir()?)?;
Ok(ExitCode::Success)
}
Command::Plan {
goal,
force,
interview,
} => {
plan::run(std::env::current_dir()?, goal, force, interview).await?;
Ok(ExitCode::Success)
}
Command::Play {
tui,
pr,
dry_run,
no_sweep,
sweep,
} => {
play::run(std::env::current_dir()?, tui, pr, dry_run, no_sweep, sweep).await?;
Ok(ExitCode::Success)
}
Command::Status => {
status::run(std::env::current_dir()?)?;
Ok(ExitCode::Success)
}
Command::Rebuy {
tui,
pr,
dry_run,
no_sweep,
sweep,
} => {
rebuy::run(std::env::current_dir()?, tui, pr, dry_run, no_sweep, sweep).await?;
Ok(ExitCode::Success)
}
Command::Sweep(args) => sweep::run(std::env::current_dir()?, args).await,
Command::Fold { checkout_original } => {
fold::run(std::env::current_dir()?, checkout_original).await?;
Ok(ExitCode::Success)
}
Command::Prompts(args) => {
prompts::run(std::env::current_dir()?, args)?;
Ok(ExitCode::Success)
}
Command::Grind(args) => grind::run(std::env::current_dir()?, args).await,
}
}