1use crate::activity::ActivityStateValue;
2
3use clap::{Args, Command, CommandFactory, Parser, Subcommand};
4
5#[derive(Debug, Parser)]
6#[command(
7 name = "agent-id",
8 version,
9 about = "Portable identity registry for coding-agent sessions",
10 long_about = "agent-id assigns permanent human-readable names to stable agent-harness session IDs."
11)]
12pub struct Cli {
13 #[command(subcommand)]
14 pub command: Commands,
15}
16
17#[derive(Debug, Subcommand)]
18pub enum Commands {
19 Register(RegisterArgs),
21 Lookup(LookupArgs),
23 Current(CurrentArgs),
25 Annotate(AnnotateArgs),
27 Discover(DiscoverArgs),
29 Prune(PruneArgs),
31 Prime(PrimeArgs),
33}
34
35#[derive(Debug, Args)]
36pub struct CurrentArgs {
37 #[arg(long)]
39 pub json: bool,
40}
41
42#[derive(Debug, Args)]
43pub struct RegisterArgs {
44 #[arg(value_name = "SESSION_ID", conflicts_with = "session_id")]
46 pub session: Option<String>,
47
48 #[arg(long = "session-id", value_name = "ID")]
50 pub session_id: Option<String>,
51
52 #[arg(long, value_name = "NAME")]
54 pub family: Option<String>,
55
56 #[arg(long, value_name = "NAME")]
58 pub realm: Option<String>,
59
60 #[arg(long)]
62 pub json: bool,
63}
64
65impl RegisterArgs {
66 pub fn explicit_session(&self) -> Option<&str> {
67 self.session.as_deref().or(self.session_id.as_deref())
68 }
69}
70
71#[derive(Debug, Args)]
72pub struct LookupArgs {
73 #[arg(value_name = "IDENTIFIER", conflicts_with = "session_id")]
75 pub input: Option<String>,
76
77 #[arg(long = "session-id", value_name = "ID")]
79 pub session_id: Option<String>,
80
81 #[arg(long)]
83 pub json: bool,
84}
85
86impl LookupArgs {
87 pub fn explicit_input(&self) -> Option<&str> {
88 self.input.as_deref().or(self.session_id.as_deref())
89 }
90}
91
92#[derive(Debug, Args)]
93pub struct AnnotateArgs {
94 #[arg(value_name = "SESSION_ID", conflicts_with = "session_id")]
96 pub session: Option<String>,
97
98 #[arg(long = "session-id", value_name = "ID")]
100 pub session_id: Option<String>,
101
102 #[arg(long, value_name = "TEXT", conflicts_with = "clear_summary")]
104 pub summary: Option<String>,
105
106 #[arg(long, conflicts_with = "summary")]
108 pub clear_summary: bool,
109
110 #[arg(long, value_name = "VALUE", conflicts_with = "clear_state")]
112 pub state: Option<ActivityStateValue>,
113
114 #[arg(long, conflicts_with = "state")]
116 pub clear_state: bool,
117
118 #[arg(long, value_name = "PATH", conflicts_with = "clear_cwd")]
120 pub cwd: Option<String>,
121
122 #[arg(long, conflicts_with = "cwd")]
124 pub clear_cwd: bool,
125
126 #[arg(long = "extension", value_name = "OWNER=JSON")]
128 pub extensions: Vec<String>,
129
130 #[arg(long = "clear-extension", value_name = "OWNER")]
132 pub clear_extensions: Vec<String>,
133
134 #[arg(long)]
136 pub json: bool,
137}
138
139impl AnnotateArgs {
140 pub fn explicit_session(&self) -> Option<&str> {
141 self.session.as_deref().or(self.session_id.as_deref())
142 }
143}
144
145#[derive(Debug, Args)]
146pub struct DiscoverArgs {
147 #[arg(long, default_value_t = 20)]
149 pub limit: usize,
150
151 #[arg(long, value_name = "HOURS")]
153 pub recent: Option<i64>,
154
155 #[arg(long, value_name = "NAME")]
157 pub realm: Option<String>,
158
159 #[arg(long)]
161 pub all: bool,
162
163 #[arg(long)]
165 pub json: bool,
166}
167
168#[derive(Debug, Args)]
169pub struct PruneArgs {
170 #[arg(long, value_name = "TIMESTAMP", required = true)]
172 pub before: String,
173
174 #[arg(long)]
176 pub dry_run: bool,
177
178 #[arg(long)]
180 pub json: bool,
181}
182
183#[derive(Debug, Args)]
184#[command(about = "Output the agent-facing identity workflow manual")]
185pub struct PrimeArgs {
186 #[arg(long)]
188 pub prelude: bool,
189
190 #[arg(long)]
192 pub json: bool,
193}
194
195pub fn build_cli() -> Command {
196 Cli::command()
197}