use std::path::PathBuf;
use anyhow::{Context, Result};
use clap::{Parser, Subcommand};
mod cmd;
#[derive(Parser)]
#[command(
name = "teamctl",
version,
about = "Declarative CLI for persistent AI agent teams",
long_about = None,
)]
struct Cli {
#[arg(long, short = 'C', env = "TEAMCTL_ROOT", default_value = ".")]
root: PathBuf,
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand)]
enum Command {
Validate,
Up,
Down,
Reload,
Status,
Logs {
target: String,
},
Send {
target: String,
text: String,
},
Bridge {
#[command(subcommand)]
action: BridgeAction,
},
Pending,
Approve {
id: i64,
#[arg(long)]
note: Option<String>,
},
Deny {
id: i64,
#[arg(long)]
note: Option<String>,
},
Budget {
#[arg(long)]
project: Option<String>,
},
Gc,
}
#[derive(Subcommand)]
enum BridgeAction {
Open {
#[arg(long)]
from: String,
#[arg(long)]
to: String,
#[arg(long)]
topic: String,
#[arg(long, default_value_t = 120)]
ttl: u64,
},
Close { id: i64 },
List,
Log { id: i64 },
}
fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_env("TEAMCTL_LOG")
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")),
)
.init();
let cli = Cli::parse();
let root = cli
.root
.canonicalize()
.with_context(|| format!("canonicalize --root {}", cli.root.display()))?;
match cli.command {
Command::Validate => cmd::validate::run(&root),
Command::Up => cmd::up::run(&root),
Command::Down => cmd::down::run(&root),
Command::Reload => cmd::reload::run(&root),
Command::Status => cmd::status::run(&root),
Command::Logs { target } => cmd::logs::run(&root, &target),
Command::Send { target, text } => cmd::send::run(&root, &target, &text),
Command::Budget { project } => cmd::budget::run(&root, project.as_deref()),
Command::Gc => cmd::gc::run(&root),
Command::Pending => cmd::approval::pending(&root),
Command::Approve { id, note } => cmd::approval::decide(&root, id, true, note.as_deref()),
Command::Deny { id, note } => cmd::approval::decide(&root, id, false, note.as_deref()),
Command::Bridge { action } => match action {
BridgeAction::Open {
from,
to,
topic,
ttl,
} => cmd::bridge::open(&root, &from, &to, &topic, ttl),
BridgeAction::Close { id } => cmd::bridge::close(&root, id),
BridgeAction::List => cmd::bridge::list(&root),
BridgeAction::Log { id } => cmd::bridge::log(&root, id),
},
}
}