mod commands;
mod ui;
use clap::{Parser, Subcommand};
use std::time::Instant;
#[derive(Parser)]
#[command(name = "flow")]
#[command(about = "Workflow CLI for multi-agent development", long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
#[arg(long, global = true)]
no_timing: bool,
}
#[derive(Subcommand)]
enum Commands {
Branch {
name: String,
#[arg(short, long, default_value = "main")]
base: String,
},
Switch {
query: Option<String>,
},
Worktree {
#[command(subcommand)]
action: commands::worktree::WorktreeAction,
},
Sync,
#[command(alias = "scan")]
Audit {
#[arg(long)]
all: bool,
},
Status {
#[arg(long)]
mobile: bool,
},
Serve {
#[arg(short, long, default_value = "3456")]
port: u16,
#[arg(long)]
no_open: bool,
#[arg(long)]
public_dir: Option<String>,
},
Features {
#[command(subcommand)]
action: FeatureAction,
#[arg(long, global = true)]
db: Option<String>,
},
#[command(alias = "tui")]
Monitor,
Theme {
#[command(subcommand)]
action: ThemeAction,
},
}
#[derive(Subcommand)]
enum FeatureAction {
List,
Add {
name: String,
#[arg(short, long, default_value = "")]
description: String,
#[arg(short, long, default_value = "")]
category: String,
},
Ready,
Claim {
id: i64,
},
Pass {
id: i64,
},
Fail {
id: i64,
},
Graph,
}
#[derive(Subcommand)]
enum ThemeAction {
List,
Set {
name: String,
},
}
fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
let start = Instant::now();
let result = match cli.command {
Commands::Branch { name, base } => commands::branch::run(&name, &base),
Commands::Switch { query } => commands::switch::run(query.as_deref()),
Commands::Worktree { action } => commands::worktree::run(action),
Commands::Sync => commands::sync::run(),
Commands::Audit { all } => commands::scan::run(all),
Commands::Status { mobile } => commands::status::run(mobile),
Commands::Serve {
port,
no_open,
public_dir,
} => commands::serve::run(port, no_open, public_dir),
Commands::Features { action, db } => {
let db_ref = db.as_deref();
match action {
FeatureAction::List => commands::features::list(db_ref),
FeatureAction::Add {
name,
description,
category,
} => commands::features::add(db_ref, &name, &description, &category),
FeatureAction::Ready => commands::features::ready(db_ref),
FeatureAction::Claim { id } => commands::features::claim(db_ref, id),
FeatureAction::Pass { id } => commands::features::pass(db_ref, id),
FeatureAction::Fail { id } => commands::features::fail(db_ref, id),
FeatureAction::Graph => commands::features::graph(db_ref),
}
}
Commands::Monitor => commands::monitor::run(),
Commands::Theme { action } => match action {
ThemeAction::List => commands::theme_cmd::list(),
ThemeAction::Set { name } => commands::theme_cmd::set(&name),
},
};
if !cli.no_timing {
ui::print_timing(start.elapsed());
}
result
}