use std::path::PathBuf;
use clap::{Args as ClapArgs, Parser, Subcommand, ValueEnum};
#[derive(Debug, Clone)]
pub struct GlobalArgs {
pub json: bool,
pub ledger_path: Option<PathBuf>,
pub no_color: bool,
}
#[derive(Debug, Parser)]
#[command(
name = "burn",
bin_name = "burn",
about = "token usage & cost attribution for agent CLIs",
long_about = None,
version,
propagate_version = true,
// The TS CLI emits its own help block; clap's auto-generated one is
// close enough for the scaffold and is what every Wave 2 PR will
// extend with per-command flag docs.
disable_help_subcommand = false,
)]
pub struct Args {
#[arg(long, global = true)]
pub json: bool,
#[arg(long, global = true, value_name = "PATH")]
pub ledger_path: Option<PathBuf>,
#[arg(long, global = true)]
pub no_color: bool,
#[command(subcommand)]
pub command: Command,
}
impl Args {
pub fn globals(&self) -> GlobalArgs {
GlobalArgs {
json: self.json,
ledger_path: self.ledger_path.clone(),
no_color: self.no_color,
}
}
}
#[derive(Debug, Subcommand)]
pub enum Command {
Summary(crate::commands::summary::SummaryArgs),
Hotspots(crate::commands::hotspots::HotspotsArgs),
Overhead(OverheadArgs),
Compare(CompareArgs),
State(StateArgs),
Sessions(SessionsArgs),
Stamps(StampsArgs),
Ingest(IngestArgs),
#[command(name = "mcp-server")]
McpServer(McpServerArgs),
}
#[derive(Debug, Clone, ClapArgs)]
pub struct IngestArgs {
#[arg(long)]
pub watch: bool,
#[arg(long, value_name = "MS")]
pub interval: Option<u64>,
#[arg(long, value_name = "HARNESS")]
pub hook: Option<String>,
#[arg(long, requires = "hook")]
pub quiet: bool,
#[arg(long, requires = "watch")]
pub no_fsevents: bool,
}
#[derive(Debug, Clone, ClapArgs)]
pub struct McpServerArgs {
#[arg(long = "session-id", value_name = "ID")]
pub session_id: Option<String>,
#[arg(long)]
pub debug: bool,
}
#[derive(Debug, Clone, ClapArgs)]
pub struct CompareArgs {
#[arg(value_name = "MODELS")]
pub models: Option<String>,
#[arg(long, value_name = "LIST")]
pub provider: Option<String>,
#[arg(long, value_name = "WHEN")]
pub since: Option<String>,
#[arg(long, value_name = "PATH")]
pub project: Option<String>,
#[arg(long, value_name = "ID")]
pub session: Option<String>,
#[arg(long, value_name = "ID")]
pub workflow: Option<String>,
#[arg(long, value_name = "ID")]
pub agent: Option<String>,
#[arg(long = "min-sample", value_name = "N")]
pub min_sample: Option<u64>,
#[arg(long, value_name = "CLASS")]
pub fidelity: Option<String>,
#[arg(long = "include-partial")]
pub include_partial: bool,
#[arg(long)]
pub csv: bool,
#[arg(long = "no-archive")]
pub no_archive: bool,
}
#[derive(Debug, ClapArgs)]
pub struct OverheadArgs {
#[arg(long, value_name = "PATH", global = true)]
pub project: Option<PathBuf>,
#[arg(long, value_name = "RANGE", global = true)]
pub since: Option<String>,
#[arg(long, value_enum, value_name = "KIND", global = true)]
pub kind: Option<OverheadKind>,
#[command(subcommand)]
pub action: Option<OverheadAction>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum OverheadKind {
#[value(name = "claude-md")]
ClaudeMd,
#[value(name = "agents-md")]
AgentsMd,
}
impl From<OverheadKind> for relayburn_sdk::OverheadFileKind {
fn from(k: OverheadKind) -> Self {
match k {
OverheadKind::ClaudeMd => relayburn_sdk::OverheadFileKind::ClaudeMd,
OverheadKind::AgentsMd => relayburn_sdk::OverheadFileKind::AgentsMd,
}
}
}
#[derive(Debug, Subcommand)]
pub enum OverheadAction {
Trim(OverheadTrimArgs),
}
#[derive(Debug, ClapArgs)]
pub struct OverheadTrimArgs {
#[arg(long, value_name = "N")]
pub top: Option<u64>,
}
#[derive(Debug, Clone, ClapArgs)]
pub struct StateArgs {
#[command(subcommand)]
pub command: Option<StateSubcommand>,
}
#[derive(Debug, Clone, Subcommand)]
pub enum StateSubcommand {
Status(StateStatusArgs),
Rebuild(StateRebuildArgs),
Prune(StatePruneArgs),
Reset(StateResetArgs),
}
#[derive(Debug, Clone, ClapArgs, Default)]
pub struct StateStatusArgs {}
#[derive(Debug, Clone, ClapArgs)]
pub struct StateRebuildArgs {
#[command(subcommand)]
pub target: StateRebuildTarget,
}
#[derive(Debug, Clone, Subcommand)]
pub enum StateRebuildTarget {
Index,
Classify,
Content,
Archive,
All,
}
#[derive(Debug, Clone, ClapArgs, Default)]
pub struct StatePruneArgs {
#[arg(long)]
pub days: Option<String>,
}
#[derive(Debug, Clone, ClapArgs, Default)]
pub struct StateResetArgs {
#[arg(long)]
pub force: bool,
#[arg(long, requires = "force")]
pub reingest: bool,
}
#[derive(Debug, Clone, ClapArgs)]
pub struct SessionsArgs {
#[command(subcommand)]
pub command: SessionsSubcommand,
}
#[derive(Debug, Clone, Subcommand)]
pub enum SessionsSubcommand {
List(SessionsListArgs),
}
#[derive(Debug, Clone, ClapArgs)]
pub struct SessionsListArgs {
#[arg(long, value_name = "WHEN")]
pub since: Option<String>,
#[arg(long, value_name = "PROJECT")]
pub project: Option<String>,
#[arg(long, value_name = "PATTERN")]
pub grep: Option<String>,
#[arg(long, value_name = "N")]
pub limit: Option<u64>,
}
#[derive(Debug, Clone, ClapArgs)]
pub struct StampsArgs {
#[command(subcommand)]
pub command: StampsSubcommand,
}
#[derive(Debug, Clone, Subcommand)]
pub enum StampsSubcommand {
Export(StampsExportArgs),
}
#[derive(Debug, Clone, ClapArgs)]
pub struct StampsExportArgs {
#[arg(short, long, value_name = "PATH")]
pub out: Option<String>,
}