use crate::core::{docs_cli, flight_recorder, obligation, plan_governance, todo, workunit};
use crate::plugins::{
aptitude, container, cron, decide, doctor, eval, federation, health, internalize, lcm, map_ops,
policy, primitives, reflex, verify, workflow,
};
use clap::{Parser, Subcommand};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[clap(
name = "decapod",
version = env!("CARGO_PKG_VERSION"),
about = "Decapod is the daemonless, local-first control plane that agents call on demand to turn intent into context, then context into explicit specifications before inference, enforce boundaries, and produce proof-backed completion across concurrent multi-agent work. 🦀",
disable_version_flag = true
)]
pub(crate) struct Cli {
#[clap(subcommand)]
pub command: Command,
}
#[derive(clap::Args, Debug)]
pub(crate) struct ValidateCli {
#[clap(long, default_value = "repo")]
pub store: String,
#[clap(long, default_value = "text")]
pub format: String,
#[clap(long, short = 'v')]
pub verbose: bool,
}
#[derive(clap::Args, Debug)]
pub(crate) struct CapabilitiesCli {
#[clap(long, default_value = "text")]
pub format: String,
}
#[derive(clap::Args, Debug)]
pub(crate) struct WorkspaceCli {
#[clap(subcommand)]
pub command: WorkspaceCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum WorkspaceCommand {
Ensure {
#[clap(long)]
branch: Option<String>,
#[clap(long)]
container: bool,
},
Status,
Publish {
#[clap(long)]
title: Option<String>,
#[clap(long)]
description: Option<String>,
},
}
#[derive(clap::Args, Debug)]
pub(crate) struct RpcCli {
#[clap(long)]
pub op: Option<String>,
#[clap(long)]
pub params: Option<String>,
#[clap(long)]
pub stdin: bool,
}
#[derive(clap::Args, Debug)]
pub(crate) struct InitGroupCli {
#[clap(subcommand)]
pub command: Option<InitCommand>,
#[clap(short, long)]
pub dir: Option<PathBuf>,
#[clap(long)]
pub project_dir: Option<PathBuf>,
#[clap(long)]
pub force: bool,
#[clap(long)]
pub dry_run: bool,
#[clap(long = "no-specs", action = clap::ArgAction::SetFalse, default_value_t = true)]
pub specs: bool,
#[clap(long, value_enum, default_value_t = InitDiagramStyle::Ascii)]
pub diagram_style: InitDiagramStyle,
#[clap(long)]
pub all: bool,
#[clap(long)]
pub claude: bool,
#[clap(long)]
pub gemini: bool,
#[clap(long)]
pub cdx_ep: bool,
#[clap(long)]
pub agents: bool,
#[clap(long)]
pub product_name: Option<String>,
#[clap(long)]
pub product_summary: Option<String>,
#[clap(long)]
pub architecture_direction: Option<String>,
#[clap(long)]
pub product_type: Option<String>,
#[clap(long)]
pub done_criteria: Option<String>,
#[clap(long = "primary-language", value_delimiter = ',')]
pub primary_languages: Vec<String>,
#[clap(long = "surface", value_delimiter = ',')]
pub detected_surfaces: Vec<String>,
}
#[derive(Subcommand, Debug)]
pub(crate) enum InitCommand {
Clean {
#[clap(short, long)]
dir: Option<PathBuf>,
},
#[clap(alias = "wtih")]
With(Box<InitWithCli>),
}
#[derive(clap::Args, Debug, Clone)]
pub(crate) struct InitWithCli {
#[clap(short, long)]
pub dir: Option<PathBuf>,
#[clap(long)]
pub project_dir: Option<PathBuf>,
#[clap(long)]
pub force: bool,
#[clap(long)]
pub dry_run: bool,
#[clap(long)]
pub all: bool,
#[clap(long)]
pub claude: bool,
#[clap(long)]
pub gemini: bool,
#[clap(long)]
pub cdx_ep: bool,
#[clap(long)]
pub agents: bool,
#[clap(long = "no-specs", action = clap::ArgAction::SetFalse, default_value_t = true)]
pub specs: bool,
#[clap(long, value_enum, default_value_t = InitDiagramStyle::Ascii)]
pub diagram_style: InitDiagramStyle,
#[clap(long)]
pub product_name: Option<String>,
#[clap(long)]
pub product_summary: Option<String>,
#[clap(long)]
pub architecture_direction: Option<String>,
#[clap(long)]
pub product_type: Option<String>,
#[clap(long)]
pub done_criteria: Option<String>,
#[clap(long = "primary-language", value_delimiter = ',')]
pub primary_languages: Vec<String>,
#[clap(long = "surface", value_delimiter = ',')]
pub detected_surfaces: Vec<String>,
}
#[derive(clap::ValueEnum, Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub(crate) enum InitDiagramStyle {
Ascii,
Mermaid,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct DecapodProjectConfig {
pub schema_version: String,
pub init: InitConfigSection,
pub repo: RepoContext,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct InitConfigSection {
pub specs: bool,
pub diagram_style: InitDiagramStyle,
pub entrypoints: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub(crate) struct RepoContext {
#[serde(skip_serializing_if = "Option::is_none")]
pub product_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub product_summary: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "architecture_direction", alias = "architecture_intent")]
pub architecture_direction: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub product_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub done_criteria: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub primary_languages: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub detected_surfaces: Vec<String>,
#[serde(default)]
pub external_tracker: bool,
}
impl Default for DecapodProjectConfig {
fn default() -> Self {
Self {
schema_version: "1.0.0".to_string(),
init: InitConfigSection {
specs: true,
diagram_style: InitDiagramStyle::Ascii,
entrypoints: vec![
"AGENTS.md".to_string(),
"CLAUDE.md".to_string(),
"GEMINI.md".to_string(),
"CODEX.md".to_string(),
],
},
repo: RepoContext::default(),
}
}
}
#[derive(clap::Args, Debug)]
pub(crate) struct SessionCli {
#[clap(subcommand)]
pub command: SessionCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum SessionCommand {
Acquire,
Status,
Release,
Init {
#[clap(long, default_value = "governed-work-session")]
scope: String,
#[clap(long = "proof")]
proofs: Vec<String>,
#[clap(long)]
force: bool,
},
}
#[derive(clap::Args, Debug)]
pub(crate) struct SetupCli {
#[clap(subcommand)]
pub command: SetupCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum SetupCommand {
Hook {
#[clap(long)]
commit_msg: bool,
#[clap(long)]
pre_commit: bool,
#[clap(long)]
uninstall: bool,
},
}
#[derive(clap::Args, Debug)]
pub(crate) struct GovernCli {
#[clap(subcommand)]
pub command: GovernCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum GovernCommand {
Policy(policy::PolicyCli),
Health(health::HealthCli),
Proof(ProofCommandCli),
Watcher(WatcherCli),
Feedback(FeedbackCli),
Gatekeeper(GatekeeperCli),
Plan(PlanCli),
Workunit(WorkunitCli),
Capsule(CapsuleCli),
}
#[derive(clap::Args, Debug)]
pub(crate) struct PlanCli {
#[clap(subcommand)]
pub command: PlanCommand,
}
#[derive(clap::ValueEnum, Clone, Debug)]
pub(crate) enum PlanStateArg {
Draft,
Annotating,
Approved,
Executing,
Done,
}
impl From<PlanStateArg> for plan_governance::PlanState {
fn from(value: PlanStateArg) -> Self {
match value {
PlanStateArg::Draft => Self::Draft,
PlanStateArg::Annotating => Self::Annotating,
PlanStateArg::Approved => Self::Approved,
PlanStateArg::Executing => Self::Executing,
PlanStateArg::Done => Self::Done,
}
}
}
#[derive(Subcommand, Debug)]
pub(crate) enum PlanCommand {
Init {
#[clap(long)]
title: String,
#[clap(long)]
intent: String,
#[clap(long = "todo-id")]
todo_ids: Vec<String>,
#[clap(long = "proof-hook")]
proof_hooks: Vec<String>,
#[clap(long = "unknown")]
unknowns: Vec<String>,
#[clap(long = "question")]
human_questions: Vec<String>,
#[clap(long = "stop-condition")]
stop_conditions: Vec<String>,
#[clap(long = "contradiction")]
unresolved_contradictions: Vec<String>,
#[clap(long = "deferred-question")]
deferred_questions: Vec<String>,
#[clap(long = "forbidden-path")]
forbidden_paths: Vec<String>,
#[clap(long)]
file_touch_budget: Option<usize>,
},
Update {
#[clap(long)]
title: Option<String>,
#[clap(long)]
intent: Option<String>,
#[clap(long = "todo-id")]
todo_ids: Vec<String>,
#[clap(long = "proof-hook")]
proof_hooks: Vec<String>,
#[clap(long = "unknown")]
unknowns: Vec<String>,
#[clap(long = "question")]
human_questions: Vec<String>,
#[clap(long = "stop-condition")]
stop_conditions: Vec<String>,
#[clap(long = "contradiction")]
unresolved_contradictions: Vec<String>,
#[clap(long = "deferred-question")]
deferred_questions: Vec<String>,
#[clap(long, default_value_t = false)]
clear_unknowns: bool,
#[clap(long, default_value_t = false)]
clear_questions: bool,
#[clap(long, default_value_t = false)]
clear_stop_conditions: bool,
#[clap(long, default_value_t = false)]
clear_contradictions: bool,
#[clap(long, default_value_t = false)]
clear_deferred_questions: bool,
#[clap(long = "forbidden-path")]
forbidden_paths: Vec<String>,
#[clap(long)]
file_touch_budget: Option<usize>,
},
SetState {
#[clap(long, value_enum)]
state: PlanStateArg,
},
Approve,
Status,
CheckExecute {
#[clap(long)]
todo_id: Option<String>,
},
}
#[derive(clap::Args, Debug)]
pub(crate) struct WorkunitCli {
#[clap(subcommand)]
pub command: WorkunitCommand,
}
#[derive(clap::ValueEnum, Clone, Debug)]
pub(crate) enum WorkunitStatusArg {
Draft,
Executing,
Claimed,
Verified,
}
impl From<WorkunitStatusArg> for workunit::WorkUnitStatus {
fn from(value: WorkunitStatusArg) -> Self {
match value {
WorkunitStatusArg::Draft => Self::Draft,
WorkunitStatusArg::Executing => Self::Executing,
WorkunitStatusArg::Claimed => Self::Claimed,
WorkunitStatusArg::Verified => Self::Verified,
}
}
}
#[derive(Subcommand, Debug)]
pub(crate) enum WorkunitCommand {
Init {
#[clap(long)]
task_id: String,
#[clap(long)]
intent_ref: String,
},
Get {
#[clap(long)]
task_id: String,
},
Status {
#[clap(long)]
task_id: String,
},
AttachSpec {
#[clap(long)]
task_id: String,
#[clap(long = "ref")]
reference: String,
},
AttachState {
#[clap(long)]
task_id: String,
#[clap(long = "ref")]
reference: String,
},
SetProofPlan {
#[clap(long)]
task_id: String,
#[clap(long = "gate")]
gates: Vec<String>,
},
RecordProof {
#[clap(long)]
task_id: String,
#[clap(long)]
gate: String,
#[clap(long)]
status: String,
#[clap(long)]
artifact: Option<String>,
},
Transition {
#[clap(long)]
task_id: String,
#[clap(long, value_enum)]
to: WorkunitStatusArg,
},
}
#[derive(clap::Args, Debug)]
pub(crate) struct CapsuleCli {
#[clap(subcommand)]
pub command: CapsuleCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum CapsuleCommand {
Query {
#[clap(long)]
topic: String,
#[clap(long)]
scope: String,
#[clap(long)]
risk_tier: Option<String>,
#[clap(long)]
task_id: Option<String>,
#[clap(long)]
workunit_id: Option<String>,
#[clap(long, default_value_t = 6)]
limit: usize,
#[clap(long, default_value_t = false)]
write: bool,
},
}
#[derive(clap::Args, Debug)]
pub(crate) struct DataCli {
#[clap(subcommand)]
pub command: DataCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum DataCommand {
Archive(ArchiveCli),
Knowledge(KnowledgeCli),
Context(ContextCli),
Schema(SchemaCli),
Repo(RepoCli),
Broker(BrokerCli),
#[clap(aliases = ["memory"])]
Aptitude(aptitude::AptitudeCli),
Federation(federation::FederationCli),
Primitives(primitives::PrimitivesCli),
}
#[derive(clap::Args, Debug)]
pub(crate) struct AutoCli {
#[clap(subcommand)]
pub command: AutoCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum AutoCommand {
Cron(cron::CronCli),
Reflex(reflex::ReflexCli),
Workflow(workflow::WorkflowCli),
Container(container::ContainerCli),
}
#[derive(clap::Args, Debug)]
pub(crate) struct QaCli {
#[clap(subcommand)]
pub command: QaCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum QaCommand {
Verify(verify::VerifyCli),
Check {
#[clap(long)]
crate_description: bool,
#[clap(long)]
commands: bool,
#[clap(long)]
all: bool,
},
Gatling(crate::plugins::gatling::GatlingCli),
}
#[derive(clap::Args, Debug)]
pub(crate) struct HandshakeCli {
#[clap(long)]
pub scope: String,
#[clap(long = "proof")]
pub proofs: Vec<String>,
}
#[derive(clap::Args, Debug)]
pub(crate) struct ReleaseCli {
#[clap(subcommand)]
pub command: ReleaseCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum ReleaseCommand {
Check,
Inventory,
LineageSync,
}
#[derive(clap::Args, Debug)]
pub(crate) struct TraceCli {
#[clap(subcommand)]
pub command: TraceCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum TraceCommand {
Export {
#[clap(long, default_value = "10")]
last: usize,
},
}
#[derive(Subcommand, Debug)]
pub(crate) enum Command {
#[clap(name = "activate")]
Activate,
#[clap(name = "init", visible_alias = "i")]
Init(InitGroupCli),
#[clap(name = "setup")]
Setup(SetupCli),
#[clap(name = "session", visible_alias = "s")]
Session(SessionCli),
#[clap(name = "docs", visible_alias = "d")]
Docs(docs_cli::DocsCli),
#[clap(name = "todo", visible_alias = "t")]
Todo(todo::TodoCli),
#[clap(name = "obligation", visible_alias = "o")]
Obligation(obligation::ObligationCli),
#[clap(name = "validate", visible_alias = "v")]
Validate(ValidateCli),
#[clap(name = "version")]
Version,
#[clap(name = "govern", visible_alias = "g")]
Govern(GovernCli),
#[clap(name = "data")]
Data(DataCli),
#[clap(name = "auto", visible_alias = "a")]
Auto(AutoCli),
#[clap(name = "qa", visible_alias = "q")]
Qa(QaCli),
#[clap(name = "decide")]
Decide(decide::DecideCli),
#[clap(name = "workspace", visible_alias = "w")]
Workspace(WorkspaceCli),
#[clap(name = "rpc")]
Rpc(RpcCli),
#[clap(name = "handshake")]
Handshake(HandshakeCli),
#[clap(name = "release")]
Release(ReleaseCli),
#[clap(name = "capabilities")]
Capabilities(CapabilitiesCli),
#[clap(name = "internalize")]
Internalize(internalize::InternalizeCli),
#[clap(name = "preflight")]
Preflight(PreflightCli),
#[clap(name = "impact")]
Impact(ImpactCli),
#[clap(name = "infer")]
Infer(InferCli),
#[clap(name = "trace")]
Trace(TraceCli),
#[clap(name = "eval")]
Eval(eval::EvalCli),
#[clap(name = "flight-recorder")]
FlightRecorder(flight_recorder::FlightRecorderCli),
#[clap(name = "state-commit")]
StateCommit(StateCommitCli),
#[clap(name = "doctor")]
Doctor(doctor::DoctorCli),
#[clap(name = "lcm")]
Lcm(lcm::LcmCli),
#[clap(name = "map")]
Map(map_ops::MapCli),
#[clap(name = "demo")]
Demo(DemoCli),
}
#[derive(clap::Args, Debug)]
pub(crate) struct BrokerCli {
#[clap(subcommand)]
pub command: BrokerCommand,
}
#[derive(clap::Args, Debug)]
pub(crate) struct StateCommitCli {
#[clap(subcommand)]
pub command: StateCommitCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum StateCommitCommand {
Prove {
#[clap(long)]
base: String,
#[clap(long)]
head: Option<String>,
#[clap(long, default_value = "scope_record.cbor")]
output: PathBuf,
},
Verify {
#[clap(long)]
scope_record: PathBuf,
#[clap(long)]
expected_root: Option<String>,
},
Explain {
#[clap(long)]
scope_record: PathBuf,
},
}
#[derive(Subcommand, Debug)]
pub(crate) enum BrokerCommand {
Audit,
Verify,
}
#[derive(clap::Args, Debug)]
pub(crate) struct KnowledgeCli {
#[clap(subcommand)]
pub command: KnowledgeCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum KnowledgeCommand {
Add {
#[clap(long)]
id: String,
#[clap(long)]
title: String,
#[clap(long)]
text: String,
#[clap(long)]
provenance: String,
#[clap(long)]
claim_id: Option<String>,
},
Search {
#[clap(long)]
query: String,
},
Promote {
#[clap(long)]
source_entry_id: String,
#[clap(long = "evidence-ref")]
evidence_refs: Vec<String>,
#[clap(long)]
approved_by: String,
#[clap(long)]
reason: String,
},
}
#[derive(clap::Args, Debug)]
pub(crate) struct RepoCli {
#[clap(subcommand)]
pub command: RepoCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum RepoCommand {
Map,
Graph,
}
#[derive(clap::Args, Debug)]
pub(crate) struct WatcherCli {
#[clap(subcommand)]
pub command: WatcherCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum WatcherCommand {
Run,
}
#[derive(clap::Args, Debug)]
pub(crate) struct ArchiveCli {
#[clap(subcommand)]
pub command: ArchiveCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum ArchiveCommand {
List,
Verify,
}
#[derive(clap::Args, Debug)]
pub(crate) struct FeedbackCli {
#[clap(subcommand)]
pub command: FeedbackCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum FeedbackCommand {
Add {
#[clap(long)]
source: String,
#[clap(long)]
text: String,
#[clap(long)]
links: Option<String>,
},
Propose,
}
#[derive(clap::Args, Debug)]
pub(crate) struct GatekeeperCli {
#[clap(subcommand)]
pub command: GatekeeperCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum GatekeeperCommand {
Check {
#[clap(long)]
paths: Option<Vec<String>>,
#[clap(long)]
max_diff_bytes: Option<u64>,
#[clap(long)]
no_secrets: bool,
#[clap(long)]
no_dangerous: bool,
},
}
#[derive(clap::Args, Debug)]
pub struct ProofCommandCli {
#[clap(subcommand)]
pub command: ProofSubCommand,
}
#[derive(Subcommand, Debug)]
pub enum ProofSubCommand {
Run,
Test {
#[clap(long)]
name: String,
},
List,
}
#[derive(clap::Args, Debug)]
pub(crate) struct ContextCli {
#[clap(subcommand)]
pub command: ContextCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum ContextCommand {
Audit {
#[clap(long)]
profile: String,
#[clap(long)]
files: Vec<PathBuf>,
},
Pack {
#[clap(long)]
path: PathBuf,
#[clap(long)]
summary: String,
},
Restore {
#[clap(long)]
id: String,
#[clap(long, default_value = "main")]
profile: String,
#[clap(long)]
current_files: Vec<PathBuf>,
},
}
#[derive(clap::Args, Debug)]
pub(crate) struct SchemaCli {
#[clap(long, default_value = "json")]
pub format: String,
#[clap(long)]
pub subsystem: Option<String>,
#[clap(long)]
pub deterministic: bool,
}
#[derive(clap::Args, Debug)]
pub(crate) struct PreflightCli {
#[clap(long)]
pub op: Option<String>,
#[clap(long, default_value = "json")]
pub format: String,
#[clap(long)]
pub session: Option<String>,
}
#[derive(clap::Args, Debug)]
pub(crate) struct ImpactCli {
#[clap(long)]
pub changed_files: Option<String>,
#[clap(long, default_value = "json")]
pub format: String,
#[clap(long)]
pub predict: bool,
}
#[derive(clap::Args, Debug)]
pub(crate) struct InferCli {
#[clap(subcommand)]
pub command: InferCommand,
}
#[derive(Subcommand, Debug)]
pub(crate) enum InferCommand {
Init(InferInitCli),
Orientation(InferOrientationCli),
Validate(InferValidateCli),
Budget(InferBudgetCli),
}
#[derive(clap::Args, Debug)]
pub(crate) struct InferOrientationCli {
#[clap(long)]
pub intent: Option<String>,
#[clap(long)]
pub task_id: Option<String>,
#[clap(long, default_value = "json")]
pub format: String,
}
#[derive(clap::Args, Debug)]
pub(crate) struct InferInitCli {
#[clap(long)]
pub intent: String,
#[clap(long)]
pub context: Option<String>,
#[clap(long, default_value = "json")]
pub format: String,
}
#[derive(clap::Args, Debug)]
pub(crate) struct InferValidateCli {
#[clap(long)]
pub result: String,
#[clap(long)]
pub intent: String,
#[clap(long, default_value = "json")]
pub format: String,
}
#[derive(clap::Args, Debug)]
pub(crate) struct InferBudgetCli {
#[clap(long)]
pub intent: String,
#[clap(long)]
pub context: Option<String>,
#[clap(long, default_value = "json")]
pub format: String,
}
#[derive(clap::Args, Debug)]
pub(crate) struct DemoCli {
#[clap(long, default_value = "interlock")]
pub demo: String,
}