use clap::{Parser, Subcommand, ValueEnum};
#[derive(Parser)]
#[command(
name = "ritalin",
version,
about = "Executive function for AI coding agents",
long_about = "ritalin is executive function for AI coding agents.\n\
Like Ritalin for ADHD — agents are smart, they just need help focusing their\n\
intelligence on the right things and avoiding avoidable mistakes.\n\n\
It ensures agents research before implementing, ground claims in evidence, reference\n\
real code instead of hallucinating patterns, and actually finish what they start.\n\n\
Workflow:\n \
1. ritalin init --outcome \"...\"\n \
2. ritalin add \"claim\" --proof \"shell command\" (repeat per obligation)\n \
3. Hook ritalin gate --hook-mode into Claude Code's Stop event\n \
4. Agent works, runs ritalin prove <id> as it discharges obligations\n \
5. Stop is blocked until every critical obligation has evidence"
)]
pub struct Cli {
#[arg(long, global = true)]
pub json: bool,
#[arg(long, global = true)]
pub quiet: bool,
#[command(subcommand)]
pub command: Commands,
}
#[derive(Clone, Copy, Debug, ValueEnum, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
#[clap(rename_all = "snake_case")]
pub enum ObligationKind {
UserPath,
Integration,
Persistence,
FailurePath,
Performance,
Security,
ResearchGrounded,
CodeReferenced,
ModelCurrent,
Other,
}
impl std::fmt::Display for ObligationKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UserPath => write!(f, "user_path"),
Self::Integration => write!(f, "integration"),
Self::Persistence => write!(f, "persistence"),
Self::FailurePath => write!(f, "failure_path"),
Self::Performance => write!(f, "performance"),
Self::Security => write!(f, "security"),
Self::ResearchGrounded => write!(f, "research_grounded"),
Self::CodeReferenced => write!(f, "code_referenced"),
Self::ModelCurrent => write!(f, "model_current"),
Self::Other => write!(f, "other"),
}
}
}
#[derive(Subcommand)]
pub enum Commands {
Init {
#[arg(long, short)]
outcome: Option<String>,
#[arg(long)]
force: bool,
},
Add {
claim: String,
#[arg(long)]
proof: String,
#[arg(long, value_enum, default_value = "other")]
kind: ObligationKind,
#[arg(long, default_value_t = true, action = clap::ArgAction::Set)]
critical: bool,
},
Prove {
id: String,
#[arg(long)]
cmd: Option<String>,
},
Gate {
#[arg(long)]
hook_mode: bool,
},
Seed {
manifest: String,
#[arg(long)]
force: bool,
},
Status,
#[command(visible_alias = "info")]
AgentInfo,
Skill {
#[command(subcommand)]
action: SkillAction,
},
Update {
#[arg(long)]
check: bool,
},
}
#[derive(Subcommand)]
pub enum SkillAction {
Install,
Status,
}