mod commands;
mod content_trust;
mod db;
mod display_safe;
mod extensions;
mod handoff;
mod host_adapter;
mod logging;
mod mcp;
mod memory;
mod output;
mod paths;
mod profile;
mod recovery;
mod repo;
mod runtime_api;
mod runtime_events;
mod session_boundary;
mod shipped_skills;
mod state;
mod telemetry;
mod timestamps;
use std::path::PathBuf;
use std::process::ExitCode;
use anyhow::Result;
use clap::{Args, CommandFactory, FromArgMatches, Parser, Subcommand, ValueEnum};
use output::OutputFormat;
#[derive(Parser)]
#[command(
name = "ccd",
version,
about = "Runtime-neutral continuity and governance kernel for AI coding"
)]
struct Cli {
#[arg(long, global = true, value_enum, default_value_t = OutputFormat::Text)]
output: OutputFormat,
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand)]
enum Command {
Describe,
Attach(AttachArgs),
Init(InitArgs),
Scaffold(ScaffoldArgs),
Host {
#[command(subcommand)]
command: HostCommand,
},
Repo {
#[command(subcommand)]
command: RepoCommand,
},
Link(LinkArgs),
Check(CheckArgs),
Preflight(PreflightArgs),
Start(StartArgs),
Status(StatusArgs),
ContextCheck(ContextCheckArgs),
PolicyCheck(PolicyCheckArgs),
Gc(GcArgs),
Unlink(UnlinkArgs),
Sync(SyncArgs),
Doctor(DoctorArgs),
Consistency(ConsistencyArgs),
Drift(DriftArgs),
Handoff {
#[command(subcommand)]
command: HandoffCommand,
},
Remember(RememberArgs),
Memory {
#[command(subcommand)]
command: MemoryCommand,
},
#[command(name = "host-hook")]
HostHook(HostHookRunArgs),
Telemetry {
#[command(subcommand)]
command: TelemetryCommand,
},
RuntimeState {
#[command(subcommand)]
command: RuntimeStateCommand,
},
EscalationState {
#[command(subcommand)]
command: EscalationStateCommand,
},
RadarState(RadarStateArgs),
Checkpoint(CheckpointArgs),
Recovery {
#[command(subcommand)]
command: RecoveryCommand,
},
Session {
#[command(subcommand)]
command: SessionCommand,
},
SessionState {
#[command(subcommand)]
command: SessionStateCommand,
},
Hooks {
#[command(subcommand)]
command: HooksCommand,
},
Skills {
#[command(subcommand)]
command: SkillsCommand,
},
#[command(hide = true)]
Pod {
#[command(subcommand)]
command: PodCommand,
},
Machine {
#[command(subcommand)]
command: MachineCommand,
},
Migrate {
#[command(subcommand)]
command: MigrateCommand,
},
#[command(hide = true)]
McpServe,
#[cfg(feature = "daemon")]
Daemon(DaemonArgs),
}
impl Command {
fn name(&self) -> &'static str {
match self {
Self::Describe => "Describe",
Self::Attach(_) => "Attach",
Self::Init(_) => "Init",
Self::Scaffold(_) => "Scaffold",
Self::Host { .. } => "Host",
Self::Repo { .. } => "Repo",
Self::Link(_) => "Link",
Self::Check(_) => "Check",
Self::Preflight(_) => "Preflight",
Self::Start(_) => "Start",
Self::Status(_) => "Status",
Self::ContextCheck(_) => "ContextCheck",
Self::PolicyCheck(_) => "PolicyCheck",
Self::Gc(_) => "Gc",
Self::Unlink(_) => "Unlink",
Self::Sync(_) => "Sync",
Self::Doctor(_) => "Doctor",
Self::Consistency(_) => "Consistency",
Self::Drift(_) => "Drift",
Self::Handoff { .. } => "Handoff",
Self::Remember(_) => "Remember",
Self::Memory { .. } => "Memory",
Self::HostHook(_) => "HostHook",
Self::Telemetry { .. } => "Telemetry",
Self::RuntimeState { .. } => "RuntimeState",
Self::EscalationState { .. } => "EscalationState",
Self::RadarState(_) => "RadarState",
Self::Checkpoint(_) => "Checkpoint",
Self::Recovery { .. } => "Recovery",
Self::Session { .. } => "Session",
Self::SessionState { .. } => "SessionState",
Self::Hooks { .. } => "Hooks",
Self::Skills { .. } => "Skills",
Self::Pod { .. } => "Pod",
Self::Machine { .. } => "Machine",
Self::Migrate { .. } => "Migrate",
Self::McpServe => "McpServe",
#[cfg(feature = "daemon")]
Self::Daemon(_) => "Daemon",
}
}
}
#[derive(Subcommand)]
enum HooksCommand {
Install(HooksInstallArgs),
Check(HooksCheckArgs),
}
#[derive(Subcommand)]
enum HostCommand {
Install(HostInstallArgs),
}
#[derive(Subcommand)]
enum RepoCommand {
Status(RepoStatusArgs),
List(RepoListArgs),
Relink(RepoRelinkArgs),
Merge(RepoMergeArgs),
Split(RepoSplitArgs),
}
#[derive(Subcommand)]
enum HandoffCommand {
Refresh(HandoffRefreshArgs),
Export(HandoffExportArgs),
Write(HandoffWriteArgs),
}
#[derive(Subcommand)]
enum MemoryCommand {
Search(MemorySearchArgs),
Describe(MemoryDescribeArgs),
Expand(MemoryExpandArgs),
SyncStatus(MemorySyncStatusArgs),
SourceMap(MemorySourceMapArgs),
Evidence {
#[command(subcommand)]
command: MemoryEvidenceCommand,
},
Candidate {
#[command(subcommand)]
command: MemoryCandidateCommand,
},
Compact(MemoryCompactArgs),
Promote(MemoryPromoteArgs),
}
#[derive(Subcommand)]
enum MemoryEvidenceCommand {
Submit(MemoryEvidenceSubmitArgs),
}
#[derive(Subcommand)]
enum MemoryCandidateCommand {
Admit(MemoryCandidateAdmitArgs),
Extract(MemoryCandidateExtractArgs),
}
#[derive(Subcommand)]
enum SkillsCommand {
Install(SkillsInstallArgs),
}
#[derive(Subcommand)]
enum PodCommand {
Init(PodInitArgs),
List,
Status(PodStatusArgs),
MigrateDefaults(PodMigrateDefaultsArgs),
}
#[derive(Subcommand)]
enum MachineCommand {
List,
}
#[derive(Subcommand)]
enum MigrateCommand {
FromPodLayout(MigrateFromPodLayoutArgs),
}
#[derive(Args)]
struct MigrateFromPodLayoutArgs {
#[arg(long)]
path: Option<PathBuf>,
#[arg(long)]
dry_run: bool,
}
#[cfg(feature = "daemon")]
#[derive(Args)]
struct DaemonArgs {
#[arg(long, default_value = "127.0.0.1")]
host: String,
#[arg(long, default_value_t = 8820)]
port: u16,
#[arg(long)]
profile: Option<String>,
#[arg(long)]
cors: bool,
}
#[derive(Args)]
struct PodInitArgs {
name: String,
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long)]
force: bool,
}
#[derive(Args)]
struct PodStatusArgs {
name: Option<String>,
#[arg(long)]
path: Option<PathBuf>,
#[arg(long)]
profile: Option<String>,
}
#[derive(Args)]
struct PodMigrateDefaultsArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long = "memory-item")]
memory_items: Vec<String>,
#[arg(long = "policy-item")]
policy_items: Vec<String>,
#[arg(long)]
adopt_suggested: bool,
#[arg(long)]
write: bool,
}
#[derive(Subcommand)]
enum RuntimeStateCommand {
Export(RuntimeStateExportArgs),
ChildBootstrap(RuntimeStateChildBootstrapArgs),
}
#[derive(Subcommand)]
enum TelemetryCommand {
Report(TelemetryReportArgs),
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)]
enum PolicyActionFamilyArg {
#[value(name = "read_only")]
ReadOnly,
#[value(name = "local_execution")]
LocalExecution,
#[value(name = "local_isolation")]
LocalIsolation,
#[value(name = "local_finalize")]
LocalFinalize,
#[value(name = "publish_external")]
PublishExternal,
#[value(name = "shared_queue_mutation")]
SharedQueueMutation,
#[value(name = "durable_memory_mutation")]
DurableMemoryMutation,
#[value(name = "repair_destructive")]
RepairDestructive,
#[value(name = "protected_surface_mutation")]
ProtectedSurfaceMutation,
}
impl PolicyActionFamilyArg {
fn into_policy_action_family(self) -> state::policy_projection::PolicyActionFamily {
match self {
Self::ReadOnly => state::policy_projection::PolicyActionFamily::ReadOnly,
Self::LocalExecution => state::policy_projection::PolicyActionFamily::LocalExecution,
Self::LocalIsolation => state::policy_projection::PolicyActionFamily::LocalIsolation,
Self::LocalFinalize => state::policy_projection::PolicyActionFamily::LocalFinalize,
Self::PublishExternal => state::policy_projection::PolicyActionFamily::PublishExternal,
Self::SharedQueueMutation => {
state::policy_projection::PolicyActionFamily::SharedQueueMutation
}
Self::DurableMemoryMutation => {
state::policy_projection::PolicyActionFamily::DurableMemoryMutation
}
Self::RepairDestructive => {
state::policy_projection::PolicyActionFamily::RepairDestructive
}
Self::ProtectedSurfaceMutation => {
state::policy_projection::PolicyActionFamily::ProtectedSurfaceMutation
}
}
}
}
#[derive(Subcommand)]
enum RecoveryCommand {
Write(RecoveryWriteArgs),
}
#[derive(Subcommand)]
enum EscalationStateCommand {
Set(EscalationStateSetArgs),
Clear(EscalationStateClearArgs),
List(EscalationStateListArgs),
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)]
enum ProjectionTargetArg {
Default,
Planning,
Session,
}
impl ProjectionTargetArg {
fn into_projection_target(self) -> state::compiled::ProjectionTarget {
match self {
Self::Default => state::compiled::ProjectionTarget::Default,
Self::Planning => state::compiled::ProjectionTarget::Planning,
Self::Session => state::compiled::ProjectionTarget::Session,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)]
enum ProjectionFormatArg {
Narrative,
Symbolic,
Bundle,
}
impl ProjectionFormatArg {
fn into_projection_format(self) -> state::compiled::ProjectionFormat {
match self {
Self::Narrative => state::compiled::ProjectionFormat::Narrative,
Self::Symbolic => state::compiled::ProjectionFormat::Symbolic,
Self::Bundle => state::compiled::ProjectionFormat::Bundle,
}
}
}
#[derive(Subcommand)]
enum SessionStateCommand {
Start(SessionStateStartArgs),
Heartbeat(SessionStateHeartbeatArgs),
Clear(SessionStateClearArgs),
Takeover(SessionStateTakeoverArgs),
Gates {
#[command(subcommand)]
command: SessionGateCommand,
},
}
#[derive(Subcommand)]
enum SessionGateCommand {
List(SessionStateArgs),
Replace(SessionGateReplaceArgs),
Seed(SessionGateSeedArgs),
SetStatus(SessionGateSetStatusArgs),
Advance(SessionGateMutateArgs),
Clear(SessionGateMutateArgs),
}
#[derive(Subcommand)]
enum SessionCommand {
Open(SessionOpenArgs),
}
#[derive(Args)]
struct SessionStateArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
}
#[derive(Args, Clone, Default)]
struct ProtectedWriteArgs {
#[arg(long = "actor-id")]
actor_id: Option<String>,
#[arg(long = "session-id")]
session_id: Option<String>,
#[arg(long = "expected-revision")]
expected_revision: Option<u64>,
}
impl ProtectedWriteArgs {
fn into_state_options(self) -> state::protected_write::ExclusiveWriteOptions {
state::protected_write::ExclusiveWriteOptions {
actor_id: self.actor_id,
session_id: self.session_id,
expected_revision: self.expected_revision,
}
}
}
#[derive(Args)]
struct SessionStateStartArgs {
#[command(flatten)]
base: SessionStateArgs,
#[arg(long, value_enum)]
mode: Option<SessionModeArg>,
#[arg(long, value_enum, default_value_t = SessionLifecycleArg::Interactive)]
lifecycle: SessionLifecycleArg,
#[arg(long = "owner-kind", value_enum)]
owner_kind: Option<AutonomousOwnerKindArg>,
#[arg(long = "actor-id")]
actor_id: Option<String>,
#[arg(long = "supervisor-id")]
supervisor_id: Option<String>,
#[arg(long = "lease-seconds")]
lease_seconds: Option<u64>,
}
#[derive(Args)]
struct SessionStateHeartbeatArgs {
#[command(flatten)]
base: SessionStateArgs,
#[arg(long = "actor-id")]
actor_id: String,
#[arg(long)]
activity: Option<String>,
}
#[derive(Args)]
struct SessionStateClearArgs {
#[command(flatten)]
base: SessionStateArgs,
#[arg(long = "actor-id")]
actor_id: Option<String>,
#[arg(long)]
reason: Option<String>,
}
#[derive(Args)]
struct SessionStateTakeoverArgs {
#[command(flatten)]
base: SessionStateArgs,
#[arg(long = "actor-id")]
actor_id: String,
#[arg(long = "supervisor-id")]
supervisor_id: Option<String>,
#[arg(long)]
reason: String,
}
#[derive(Args)]
struct SessionGateReplaceArgs {
#[command(flatten)]
base: SessionStateArgs,
#[command(flatten)]
protected_write: ProtectedWriteArgs,
#[arg(long = "gate", required = true)]
gates: Vec<String>,
}
#[derive(Args)]
struct SessionGateSeedArgs {
#[command(flatten)]
base: SessionStateArgs,
#[command(flatten)]
protected_write: ProtectedWriteArgs,
#[arg(long, value_enum)]
from: GateSeedSourceArg,
}
#[derive(Args)]
struct SessionGateSetStatusArgs {
#[command(flatten)]
base: SessionStateArgs,
#[command(flatten)]
protected_write: ProtectedWriteArgs,
#[arg(long)]
index: usize,
#[arg(long, value_enum)]
status: GateStatusArg,
}
#[derive(Args)]
struct SessionGateMutateArgs {
#[command(flatten)]
base: SessionStateArgs,
#[command(flatten)]
protected_write: ProtectedWriteArgs,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)]
enum GateSeedSourceArg {
ImmediateActions,
DefinitionOfDone,
}
impl GateSeedSourceArg {
fn into_state_source(self) -> state::session_gates::GateSeedSource {
match self {
Self::ImmediateActions => state::session_gates::GateSeedSource::ImmediateActions,
Self::DefinitionOfDone => state::session_gates::GateSeedSource::DefinitionOfDone,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)]
enum GateStatusArg {
Open,
Done,
Blocked,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)]
enum SessionModeArg {
General,
Research,
Implement,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)]
enum SessionLifecycleArg {
Interactive,
Autonomous,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)]
enum AttemptOutcomeArg {
Progress,
NoProgress,
Neutral,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)]
enum AutonomousOwnerKindArg {
RuntimeWorker,
RuntimeSupervisor,
}
impl SessionModeArg {
fn into_state_mode(self) -> state::session::SessionMode {
match self {
Self::General => state::session::SessionMode::General,
Self::Research => state::session::SessionMode::Research,
Self::Implement => state::session::SessionMode::Implement,
}
}
}
impl SessionLifecycleArg {
fn into_state_lifecycle(self) -> state::session::SessionLifecycle {
match self {
Self::Interactive => state::session::SessionLifecycle::Interactive,
Self::Autonomous => state::session::SessionLifecycle::Autonomous,
}
}
}
impl AttemptOutcomeArg {
fn into_state_outcome(self) -> state::work_stream_decay::AttemptOutcome {
match self {
Self::Progress => state::work_stream_decay::AttemptOutcome::Progress,
Self::NoProgress => state::work_stream_decay::AttemptOutcome::NoProgress,
Self::Neutral => state::work_stream_decay::AttemptOutcome::Neutral,
}
}
}
impl AutonomousOwnerKindArg {
fn into_state_owner_kind(self) -> state::session::SessionOwnerKind {
match self {
Self::RuntimeWorker => state::session::SessionOwnerKind::RuntimeWorker,
Self::RuntimeSupervisor => state::session::SessionOwnerKind::RuntimeSupervisor,
}
}
}
impl GateStatusArg {
fn into_status(self) -> state::session_gates::ExecutionGateStatus {
match self {
Self::Open => state::session_gates::ExecutionGateStatus::Open,
Self::Done => state::session_gates::ExecutionGateStatus::Done,
Self::Blocked => state::session_gates::ExecutionGateStatus::Blocked,
}
}
}
#[derive(Args)]
struct SessionOpenArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long)]
worktree: Option<PathBuf>,
#[arg(long)]
branch: Option<String>,
#[arg(long = "from")]
from_ref: Option<String>,
#[arg(long, hide = true)]
pod: Option<String>,
}
#[derive(Args)]
struct SkillsInstallArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long, default_value_t = true)]
global: bool,
#[arg(long)]
local: bool,
}
#[derive(Args)]
struct RuntimeStateExportArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long, value_enum)]
projection_target: Option<ProjectionTargetArg>,
#[arg(long, value_enum)]
projection_format: Option<ProjectionFormatArg>,
}
#[derive(Args)]
struct RuntimeStateChildBootstrapArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
}
#[derive(Args)]
struct TelemetryReportArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long, default_value_t = 20)]
limit: usize,
}
#[derive(Args, Clone)]
struct EscalationStateArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
}
#[derive(Args)]
struct EscalationStateSetArgs {
#[command(flatten)]
base: EscalationStateArgs,
#[command(flatten)]
protected_write: ProtectedWriteArgs,
#[arg(long, value_enum, default_value_t = EscalationKindArg::Blocking)]
kind: EscalationKindArg,
#[arg(long)]
id: Option<String>,
#[arg(long)]
reason: String,
}
#[derive(Args)]
struct EscalationStateClearArgs {
#[command(flatten)]
base: EscalationStateArgs,
#[command(flatten)]
protected_write: ProtectedWriteArgs,
#[arg(long)]
id: Option<String>,
}
#[derive(Args)]
struct EscalationStateListArgs {
#[command(flatten)]
base: EscalationStateArgs,
}
#[derive(Args)]
struct HooksInstallArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
force: bool,
}
#[derive(Args)]
struct HooksCheckArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
}
#[derive(Args)]
struct HandoffRefreshArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long)]
write: bool,
}
#[derive(Args)]
struct HandoffExportArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
}
#[derive(Args)]
struct HandoffWriteArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[command(flatten)]
protected_write: ProtectedWriteArgs,
#[arg(long = "allow-missing-refs")]
allow_missing_refs: bool,
}
#[derive(Args)]
struct RecoveryWriteArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[command(flatten)]
protected_write: ProtectedWriteArgs,
}
#[derive(Args)]
struct RememberArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long, value_enum)]
scope: Option<RememberScopeArg>,
#[arg(long = "type", value_enum, default_value_t = RememberTypeArg::Observation)]
entry_type: RememberTypeArg,
#[arg(long, value_enum, default_value_t = RememberOriginArg::Manual)]
origin: RememberOriginArg,
#[arg(long)]
source_ref: Option<String>,
#[arg(long)]
dry_run: bool,
content: String,
}
#[derive(Args)]
struct AttachArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long = "project-id")]
project_id: Option<String>,
#[arg(long)]
display_name: Option<String>,
}
#[derive(Args)]
struct InitArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long = "project-id")]
project_id: Option<String>,
#[arg(long)]
display_name: Option<String>,
#[arg(long = "host", value_enum, value_delimiter = ',')]
host: Vec<RepoHostArg>,
#[arg(long)]
force: bool,
}
#[derive(Args)]
struct ScaffoldArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
force: bool,
}
#[derive(Args)]
struct LinkArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long = "project-id")]
project_id: Option<String>,
#[arg(long)]
display_name: Option<String>,
}
#[derive(Args)]
struct HostInstallArgs {
host: RepoHostArg,
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long)]
force: bool,
#[arg(long = "with-launcher")]
with_launcher: bool,
}
#[derive(Args)]
struct RepoStatusArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
}
#[derive(Args)]
struct RepoListArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
}
#[derive(Args)]
struct RepoRelinkArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
locality_id: String,
}
#[derive(Args)]
struct RepoMergeArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
target_locality_id: String,
source_locality_id: String,
#[arg(long)]
force: bool,
}
#[derive(Args)]
struct RepoSplitArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
source_locality_id: String,
}
#[derive(Args)]
struct CheckArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
}
#[derive(Args)]
struct PreflightArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
}
#[derive(Args)]
struct StartArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long)]
refresh: bool,
#[arg(long)]
check: bool,
#[arg(long, value_delimiter = ',')]
fields: Option<Vec<String>>,
#[arg(long, value_enum)]
memory_depth: Option<output::MemoryDepth>,
#[arg(long)]
activate: bool,
#[arg(long, value_enum)]
mode: Option<SessionModeArg>,
}
#[derive(Args)]
struct StatusArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long, value_delimiter = ',')]
fields: Option<Vec<String>>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)]
enum ContextCheckTriggerArg {
Interval,
Manual,
#[value(name = "pre-compaction")]
PreCompaction,
#[value(name = "idle-reset")]
IdleReset,
Resume,
#[value(name = "supervisor-poll")]
SupervisorPoll,
}
impl ContextCheckTriggerArg {
fn into_trigger(self) -> state::radar::ContextCheckTrigger {
match self {
Self::Interval => state::radar::ContextCheckTrigger::Interval,
Self::Manual => state::radar::ContextCheckTrigger::Manual,
Self::PreCompaction => state::radar::ContextCheckTrigger::PreCompaction,
Self::IdleReset => state::radar::ContextCheckTrigger::IdleReset,
Self::Resume => state::radar::ContextCheckTrigger::Resume,
Self::SupervisorPoll => state::radar::ContextCheckTrigger::SupervisorPoll,
}
}
}
#[derive(Args)]
struct ContextCheckArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long, value_enum, default_value = "interval")]
trigger: ContextCheckTriggerArg,
#[arg(long, value_delimiter = ',')]
fields: Option<Vec<String>>,
#[arg(long, value_enum)]
memory_depth: Option<output::MemoryDepth>,
}
#[derive(Args)]
struct PolicyCheckArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long, value_enum)]
action_family: PolicyActionFamilyArg,
}
#[derive(Args)]
struct GcArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
}
#[derive(Args)]
struct UnlinkArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
}
#[derive(Args)]
struct SyncArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long)]
check: bool,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)]
enum DoctorSeverityFilter {
Pass,
Warn,
Fail,
}
#[derive(Args)]
struct DoctorArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long, hide = true)]
skip_repo_native_checks: bool,
#[arg(long, value_enum)]
severity: Option<DoctorSeverityFilter>,
#[arg(long, value_delimiter = ',')]
fields: Option<Vec<String>>,
}
#[derive(Args)]
struct ConsistencyArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
}
#[derive(Args)]
struct DriftArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
}
#[derive(Args)]
struct MemoryPromoteArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[command(flatten)]
protected_write: ProtectedWriteArgs,
#[arg(long)]
entry: String,
#[arg(long, value_enum)]
source_outcome: Option<MemoryPromoteSourceOutcomeArg>,
#[arg(long, value_enum, default_value = "profile-memory")]
destination: MemoryPromoteDestinationArg,
#[arg(long)]
target_file: Option<PathBuf>,
#[arg(long)]
write: bool,
}
#[derive(Args)]
struct MemoryCandidateAdmitArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[command(flatten)]
protected_write: ProtectedWriteArgs,
#[arg(long)]
entry: String,
#[arg(long, value_enum)]
source_scope: MemoryCandidateSourceScopeArg,
#[arg(long, value_enum)]
destination: MemoryCandidateDestinationArg,
#[arg(long)]
write: bool,
}
#[derive(Args)]
struct MemoryEvidenceSubmitArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[command(flatten)]
protected_write: ProtectedWriteArgs,
#[arg(long, value_enum)]
scope: MemoryEvidenceScopeArg,
#[arg(long = "type", value_enum)]
entry_type: RememberTypeArg,
#[arg(long = "source-kind", value_enum, default_value_t = MemoryEvidenceSourceKindArg::HookOutput)]
source_kind: MemoryEvidenceSourceKindArg,
#[arg(long)]
source_ref: Option<String>,
#[arg(long = "host-hook", value_enum)]
host_hook: Option<HostHookArg>,
#[arg(long)]
host: Option<String>,
#[arg(long)]
provider: Option<String>,
#[arg(long = "provider-ref")]
provider_ref: Option<String>,
#[arg(long)]
summary: String,
}
#[derive(Args)]
struct HostHookRunArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long)]
host: Option<String>,
#[arg(long, value_enum)]
mode: Option<SessionModeArg>,
#[arg(long, value_enum, default_value_t = SessionLifecycleArg::Interactive)]
lifecycle: SessionLifecycleArg,
#[arg(long = "owner-kind", value_enum)]
owner_kind: Option<AutonomousOwnerKindArg>,
#[arg(long = "supervisor-id")]
supervisor_id: Option<String>,
#[arg(long = "lease-seconds")]
lease_seconds: Option<u64>,
#[arg(long = "host-session-id")]
host_session_id: Option<String>,
#[arg(long = "host-run-id")]
host_run_id: Option<String>,
#[arg(long = "host-task-id")]
host_task_id: Option<String>,
#[arg(long)]
diagnostics: bool,
#[arg(long = "host-total-context-chars")]
host_total_context_chars: Option<u64>,
#[arg(long, value_enum)]
hook: HostHookArg,
#[command(flatten)]
protected_write: ProtectedWriteArgs,
#[arg(long = "capture-scope", value_enum)]
capture_scope: Option<MemoryEvidenceScopeArg>,
#[arg(long = "capture-type", value_enum)]
capture_type: Option<RememberTypeArg>,
#[arg(long = "capture-source-kind", value_enum)]
capture_source_kind: Option<MemoryEvidenceSourceKindArg>,
#[arg(long = "capture-summary")]
capture_summary: Option<String>,
#[arg(long = "capture-source-ref")]
capture_source_ref: Option<String>,
#[arg(long = "capture-provider")]
capture_provider: Option<String>,
#[arg(long = "capture-provider-ref", requires = "capture_provider")]
capture_provider_ref: Option<String>,
#[arg(long = "attempt-outcome", value_enum)]
attempt_outcome: Option<AttemptOutcomeArg>,
}
#[derive(Args)]
struct MemoryCandidateExtractArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[command(flatten)]
protected_write: ProtectedWriteArgs,
#[arg(long = "evidence-id")]
evidence_id: Option<String>,
#[arg(long, default_value_t = 8, value_parser = parse_positive_usize)]
limit: usize,
#[arg(long)]
write: bool,
}
#[derive(Args)]
struct MemoryCompactArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[command(flatten)]
protected_write: ProtectedWriteArgs,
#[arg(long, value_enum)]
scope: MemoryCompactScopeArg,
#[arg(long)]
entry: Option<String>,
#[arg(long)]
keep: Option<String>,
#[arg(long, value_enum)]
decay_class: Option<MemoryDecayClassArg>,
#[arg(long, value_enum)]
review: Option<MemoryCompactReviewArg>,
#[arg(long)]
remove: bool,
#[arg(long)]
write: bool,
}
#[derive(Args)]
struct MemorySearchArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long)]
query: String,
#[arg(long, default_value_t = 5, value_parser = parse_positive_usize)]
limit: usize,
}
#[derive(Args)]
struct MemoryDescribeArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long = "native-id")]
native_id: String,
}
#[derive(Args)]
struct MemoryExpandArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long = "native-id")]
native_id: String,
#[arg(long, default_value_t = 3, value_parser = parse_positive_usize)]
limit: usize,
}
#[derive(Args)]
struct MemorySyncStatusArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
}
#[derive(Args)]
struct MemorySourceMapArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
}
fn parse_positive_usize(raw: &str) -> Result<usize, String> {
let value = raw
.parse::<usize>()
.map_err(|_| format!("invalid value `{raw}`: expected a positive integer"))?;
if value == 0 {
return Err("expected a positive integer greater than zero".to_owned());
}
Ok(value)
}
#[derive(Args)]
struct RadarStateArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long, value_delimiter = ',')]
fields: Option<Vec<String>>,
#[arg(long, value_enum)]
memory_depth: Option<output::MemoryDepth>,
#[arg(long)]
commit: bool,
#[arg(long)]
since_session: Option<String>,
}
#[derive(Args)]
struct CheckpointArgs {
#[arg(long, default_value = ".")]
path: PathBuf,
#[arg(long)]
profile: Option<String>,
#[arg(long, value_delimiter = ',')]
fields: Option<Vec<String>>,
#[arg(long, value_enum)]
memory_depth: Option<output::MemoryDepth>,
#[arg(long)]
commit: bool,
#[arg(long)]
since_session: Option<String>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
enum MemoryPromoteSourceOutcomeArg {
Active,
Superseded,
LinkOnly,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
enum MemoryPromoteDestinationArg {
#[value(
name = "work-stream-memory",
alias = "branch-memory",
alias = "work_stream-memory",
alias = "work_stream_memory"
)]
BranchMemory,
#[value(name = "project-memory", alias = "repo-memory")]
RepoMemory,
#[value(name = "profile-memory")]
ProfileMemory,
#[value(name = "project-truth")]
ProjectTruth,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
enum MemoryCandidateSourceScopeArg {
#[value(name = "workspace-memory", alias = "clone-memory")]
Clone,
#[value(
name = "work-stream-memory",
alias = "branch-memory",
alias = "work-stream-memory",
alias = "work_stream-memory",
alias = "work_stream_memory"
)]
Branch,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
enum MemoryCandidateDestinationArg {
#[value(
name = "work-stream-memory",
alias = "branch-memory",
alias = "work-stream-memory",
alias = "work_stream-memory",
alias = "work_stream_memory"
)]
Branch,
#[value(name = "project-memory", alias = "repo-memory")]
Repo,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
enum MemoryEvidenceScopeArg {
#[value(name = "workspace", alias = "clone")]
Workspace,
#[value(name = "work-stream", alias = "work_stream", alias = "branch")]
WorkStream,
#[value(name = "project", alias = "repo")]
Project,
Profile,
#[value(name = "project-truth", alias = "project_truth")]
ProjectTruth,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
enum MemoryEvidenceSourceKindArg {
Transcript,
Session,
#[value(name = "event-stream", alias = "event_stream")]
EventStream,
#[value(name = "hook-output", alias = "hook_output")]
HookOutput,
Log,
Document,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
enum HostHookArg {
#[value(name = "on-session-start")]
OnSessionStart,
#[value(name = "before-prompt-build")]
BeforePromptBuild,
#[value(name = "on-compaction-notice")]
OnCompactionNotice,
#[value(name = "on-agent-end")]
OnAgentEnd,
#[value(name = "on-session-end")]
OnSessionEnd,
#[value(name = "supervisor-tick")]
SupervisorTick,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
enum RepoHostArg {
#[value(name = "claude", alias = "claude-code")]
Claude,
Codex,
Hermes,
#[value(name = "openclaw")]
OpenClaw,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
enum MemoryCompactScopeArg {
Profile,
#[value(name = "project", alias = "repo")]
Repo,
#[value(name = "work-stream", alias = "branch", alias = "work_stream")]
Branch,
#[value(name = "workspace", alias = "clone")]
Clone,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
enum MemoryCompactReviewArg {
Expired,
Superseded,
PromotionCandidate,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
enum MemoryDecayClassArg {
Permanent,
Stable,
Active,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)]
enum EscalationKindArg {
Blocking,
#[value(alias = "non_blocking")]
NonBlocking,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
enum RememberScopeArg {
Profile,
#[value(name = "project", alias = "repo")]
Repo,
#[value(name = "work-stream", alias = "branch", alias = "work_stream")]
Branch,
#[value(name = "workspace", alias = "clone")]
Clone,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
enum RememberTypeArg {
Rule,
Constraint,
Heuristic,
Observation,
Attempt,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, clap::ValueEnum)]
enum RememberOriginArg {
Manual,
Agent,
Radar,
}
impl MemoryCompactScopeArg {
fn into_scope(self) -> memory::compact::CompactScope {
match self {
Self::Profile => memory::compact::CompactScope::Profile,
Self::Repo => memory::compact::CompactScope::Repo,
Self::Branch => memory::compact::CompactScope::Branch,
Self::Clone => memory::compact::CompactScope::Clone,
}
}
}
impl MemoryCompactReviewArg {
fn into_review_kind(self) -> memory::compact::CompactReviewKind {
match self {
Self::Expired => memory::compact::CompactReviewKind::Expired,
Self::Superseded => memory::compact::CompactReviewKind::Superseded,
Self::PromotionCandidate => memory::compact::CompactReviewKind::PromotionCandidate,
}
}
}
impl MemoryDecayClassArg {
fn into_decay_class(self) -> memory::compact::DecayClass {
match self {
Self::Permanent => memory::compact::DecayClass::Permanent,
Self::Stable => memory::compact::DecayClass::Stable,
Self::Active => memory::compact::DecayClass::Active,
}
}
}
impl EscalationKindArg {
fn into_kind(self) -> state::escalation::EscalationKind {
match self {
Self::Blocking => state::escalation::EscalationKind::Blocking,
Self::NonBlocking => state::escalation::EscalationKind::NonBlocking,
}
}
}
impl RememberScopeArg {
fn into_scope(self) -> memory::remember::RememberScope {
match self {
Self::Profile => memory::remember::RememberScope::Profile,
Self::Repo => memory::remember::RememberScope::Repo,
Self::Branch => memory::remember::RememberScope::Branch,
Self::Clone => memory::remember::RememberScope::Clone,
}
}
}
impl RememberTypeArg {
fn as_str(self) -> &'static str {
match self {
Self::Rule => "rule",
Self::Constraint => "constraint",
Self::Heuristic => "heuristic",
Self::Observation => "observation",
Self::Attempt => "attempt",
}
}
}
impl RememberOriginArg {
fn as_str(self) -> &'static str {
match self {
Self::Manual => "manual",
Self::Agent => "agent",
Self::Radar => "radar",
}
}
}
impl MemoryEvidenceScopeArg {
fn as_str(self) -> &'static str {
match self {
Self::Workspace => "workspace",
Self::WorkStream => "work_stream",
Self::Project => "project",
Self::Profile => "profile",
Self::ProjectTruth => "project_truth",
}
}
}
impl MemoryEvidenceSourceKindArg {
fn as_str(self) -> &'static str {
match self {
Self::Transcript => "transcript",
Self::Session => "session",
Self::EventStream => "event_stream",
Self::HookOutput => "hook_output",
Self::Log => "log",
Self::Document => "document",
}
}
}
impl HostHookArg {
fn as_str(self) -> &'static str {
match self {
Self::OnSessionStart => "on_session_start",
Self::BeforePromptBuild => "before_prompt_build",
Self::OnCompactionNotice => "on_compaction_notice",
Self::OnAgentEnd => "on_agent_end",
Self::OnSessionEnd => "on_session_end",
Self::SupervisorTick => "supervisor_tick",
}
}
}
impl RepoHostArg {
fn into_host(self) -> commands::host::ManagedHost {
match self {
Self::Claude => commands::host::ManagedHost::Claude,
Self::Codex => commands::host::ManagedHost::Codex,
Self::Hermes => commands::host::ManagedHost::Hermes,
Self::OpenClaw => commands::host::ManagedHost::OpenClaw,
}
}
}
fn resolve_host_adapter_name(explicit: Option<String>) -> Result<String> {
explicit
.and_then(|value| {
let trimmed = value.trim();
if trimmed.is_empty() {
None
} else {
Some(trimmed.to_owned())
}
})
.or_else(|| telemetry::host::env_string(&["CCD_HOST_ADAPTER"]))
.ok_or_else(|| anyhow::anyhow!("missing host adapter: pass --host or set CCD_HOST_ADAPTER"))
}
fn build_host_hook_capture(
args: &HostHookRunArgs,
host: &str,
runtime_hints: &memory::evidence::SubmitRuntimeHints,
) -> Result<Option<memory::evidence::MemoryEvidenceEnvelope>> {
let hook = args.hook.as_str();
let capture_requested = args.capture_scope.is_some()
|| args.capture_type.is_some()
|| args.capture_source_kind.is_some()
|| args.capture_summary.is_some()
|| args.capture_source_ref.is_some()
|| args.capture_provider.is_some()
|| args.capture_provider_ref.is_some();
if !capture_requested {
return Ok(None);
}
if hook != "on_compaction_notice" {
anyhow::bail!("capture arguments are only supported for --hook on-compaction-notice");
}
let scope = args
.capture_scope
.ok_or_else(|| anyhow::anyhow!("missing required argument: --capture-scope"))?
.as_str()
.to_owned();
let entry_type = args
.capture_type
.ok_or_else(|| anyhow::anyhow!("missing required argument: --capture-type"))?
.as_str()
.to_owned();
let source_kind = args
.capture_source_kind
.unwrap_or(MemoryEvidenceSourceKindArg::HookOutput)
.as_str()
.to_owned();
let summary = args
.capture_summary
.clone()
.ok_or_else(|| anyhow::anyhow!("missing required argument: --capture-summary"))?;
Ok(Some(memory::evidence::MemoryEvidenceEnvelope {
scope,
entry_type,
source_kind,
summary,
source_ref: args.capture_source_ref.clone(),
host_reference: Some(memory::evidence::MemoryEvidenceHostReference {
host: host.to_owned(),
hook: Some(hook.to_owned()),
session_id: runtime_hints.host_session_id.clone(),
run_id: runtime_hints.host_run_id.clone(),
task_id: runtime_hints.host_task_id.clone(),
}),
provider_reference: args.capture_provider.clone().map(|provider| {
memory::evidence::MemoryEvidenceProviderReference {
provider,
native_id: args.capture_provider_ref.clone(),
}
}),
}))
}
fn host_hook_runtime_hints(args: &HostHookRunArgs) -> memory::evidence::SubmitRuntimeHints {
memory::evidence::SubmitRuntimeHints {
host_session_id: args.host_session_id.clone(),
host_run_id: args.host_run_id.clone(),
host_task_id: args.host_task_id.clone(),
}
}
fn host_hook_session_start_options(
args: &HostHookRunArgs,
) -> host_adapter::HostSessionStartOptions {
host_adapter::HostSessionStartOptions {
mode: args.mode.map(SessionModeArg::into_state_mode),
lifecycle: args.lifecycle.into_state_lifecycle(),
owner_kind: args
.owner_kind
.map(AutonomousOwnerKindArg::into_state_owner_kind),
actor_id: args.protected_write.actor_id.clone(),
supervisor_id: args.supervisor_id.clone(),
lease_ttl_secs: args.lease_seconds,
host_session_id: args.host_session_id.clone(),
host_run_id: args.host_run_id.clone(),
host_task_id: args.host_task_id.clone(),
}
}
impl MemoryPromoteSourceOutcomeArg {
fn into_source_outcome(self) -> memory::promote::SourceOutcome {
match self {
Self::Active => memory::promote::SourceOutcome::Active,
Self::Superseded => memory::promote::SourceOutcome::Superseded,
Self::LinkOnly => memory::promote::SourceOutcome::LinkOnly,
}
}
}
impl MemoryCandidateSourceScopeArg {
fn into_source_scope(self) -> memory::candidate::CandidateSourceScope {
match self {
Self::Clone => memory::candidate::CandidateSourceScope::Clone,
Self::Branch => memory::candidate::CandidateSourceScope::Branch,
}
}
}
impl MemoryCandidateDestinationArg {
fn into_destination(self) -> memory::candidate::CandidateDestination {
match self {
Self::Branch => memory::candidate::CandidateDestination::Branch,
Self::Repo => memory::candidate::CandidateDestination::Repo,
}
}
}
fn apply_since_session_delta(
mut value: serde_json::Value,
repo_path: &std::path::Path,
explicit_profile: Option<&str>,
since: &str,
current_digests: &state::compiled::ProjectionDigests,
) -> anyhow::Result<serde_json::Value> {
let session_layout =
paths::state::StateLayout::resolve(repo_path, profile::resolve(explicit_profile)?)?;
let mut delta_status = "filtered";
let mut delta_warning = None;
let mut skip_stats = state::compiled::ProjectionDeltaStats::default();
let target_session_id = if since == "current" {
match state::session::load_session_id(&session_layout)? {
Some(session_id) => Some(session_id),
None => {
delta_status = "no_active_session";
delta_warning = Some(
"--since-session current: no active session found; emitting full output"
.to_owned(),
);
None
}
}
} else {
Some(since.to_owned())
};
if let Some(target_session_id) = target_session_id.as_deref() {
match state::projection_metadata::load_baseline_for_session(
&session_layout,
target_session_id,
)? {
Some(obs) if obs.projection_digests.is_some() => {
let baseline = obs.projection_digests.unwrap();
skip_stats =
state::compiled::compute_projection_delta_stats(&baseline, current_digests);
value = state::radar::apply_delta_filter(value, &baseline, current_digests);
}
_ => {
delta_status = "baseline_missing";
delta_warning =
Some("no baseline found for session; emitting full output".to_owned());
}
}
}
if let Some(obj) = value.as_object_mut() {
if let Some(warning) = delta_warning.as_deref() {
obj.insert("delta_warning".to_owned(), serde_json::json!(warning));
}
obj.insert(
"session_delta".to_owned(),
serde_json::json!({
"requested": since,
"status": delta_status,
"resolved_session_id": target_session_id,
"skip_stats": skip_stats,
"warning": delta_warning,
}),
);
}
Ok(value)
}
fn main() -> ExitCode {
logging::init();
let matches = cli_command().get_matches();
let output = matches
.get_one::<OutputFormat>("output")
.copied()
.unwrap_or(OutputFormat::Text);
match run_matches(&matches) {
Ok(code) => code,
Err(error) => {
output::render_error(output, &error);
ExitCode::from(1)
}
}
}
pub(crate) fn cli_command() -> clap::Command {
extensions::augment_clap(Cli::command())
}
fn run_matches(matches: &clap::ArgMatches) -> Result<ExitCode> {
let output = matches
.get_one::<OutputFormat>("output")
.copied()
.unwrap_or(OutputFormat::Text);
if let Some((subcommand_name, submatches)) = matches.subcommand() {
if let Some(result) = extensions::dispatch_cli(subcommand_name, submatches, output) {
return result;
}
}
let cli = Cli::from_arg_matches(matches)?;
run(cli)
}
fn run(cli: Cli) -> Result<ExitCode> {
let command_name = cli.command.name();
let _span = tracing::info_span!("command", name = command_name).entered();
tracing::info!(command = command_name, "dispatching command");
match cli.command {
Command::Describe => commands::dispatch::maintenance::describe(cli.output),
Command::Attach(args) => commands::dispatch::bootstrap::attach(args, cli.output),
Command::Init(args) => commands::dispatch::bootstrap::init(args, cli.output),
Command::Scaffold(args) => commands::dispatch::bootstrap::scaffold(args, cli.output),
Command::Host { command } => commands::dispatch::host::host(command, cli.output),
Command::Repo { command } => commands::dispatch::repo::dispatch(command, cli.output),
Command::Link(args) => commands::dispatch::bootstrap::link(args, cli.output),
Command::Check(args) => commands::dispatch::maintenance::check(args, cli.output),
Command::Preflight(args) => commands::dispatch::session::preflight(args, cli.output),
Command::Start(args) => commands::dispatch::session::start(args, cli.output),
Command::Status(args) => commands::dispatch::session::status(args, cli.output),
Command::ContextCheck(args) => commands::dispatch::state::context_check(args, cli.output),
Command::PolicyCheck(args) => commands::dispatch::state::policy_check(args, cli.output),
Command::Gc(args) => commands::dispatch::maintenance::gc(args, cli.output),
Command::Unlink(args) => commands::dispatch::bootstrap::unlink(args, cli.output),
Command::Sync(args) => commands::dispatch::maintenance::sync(args, cli.output),
Command::Doctor(args) => commands::dispatch::maintenance::doctor(args, cli.output),
Command::Consistency(args) => {
commands::dispatch::maintenance::consistency(args, cli.output)
}
Command::Drift(args) => commands::dispatch::maintenance::drift(args, cli.output),
Command::Handoff { command } => {
commands::dispatch::continuity::handoff(command, cli.output)
}
Command::Remember(args) => commands::dispatch::memory::remember(args, cli.output),
Command::Memory { command } => commands::dispatch::memory::dispatch(command, cli.output),
Command::HostHook(args) => commands::dispatch::host::host_hook(args, cli.output),
Command::Telemetry { command } => commands::dispatch::host::telemetry(command, cli.output),
Command::RuntimeState { command } => {
commands::dispatch::state::runtime_state(command, cli.output)
}
Command::EscalationState { command } => {
commands::dispatch::state::escalation_state(command, cli.output)
}
Command::RadarState(args) => commands::dispatch::state::radar_state(args, cli.output),
Command::Checkpoint(args) => commands::dispatch::state::checkpoint(args, cli.output),
Command::Recovery { command } => {
commands::dispatch::continuity::recovery(command, cli.output)
}
Command::Session { command } => commands::dispatch::session::session(command, cli.output),
Command::SessionState { command } => {
commands::dispatch::session::session_state(command, cli.output)
}
Command::Hooks { command } => commands::dispatch::maintenance::hooks(command, cli.output),
Command::Skills { command } => commands::dispatch::maintenance::skills(command, cli.output),
Command::Pod { command } => commands::dispatch::pod::dispatch(command, cli.output),
Command::Machine { command } => commands::dispatch::machine::dispatch(command, cli.output),
Command::Migrate { command } => commands::dispatch::migrate::dispatch(command, cli.output),
Command::McpServe => commands::dispatch::host::mcp_serve(),
#[cfg(feature = "daemon")]
Command::Daemon(args) => commands::dispatch::host::daemon(args),
}
}