1use clap::{Parser, Subcommand};
2use std::path::PathBuf;
3
4#[derive(Parser)]
5#[command(name = "sparrow", about = "one cli · grows with you", version)]
6pub struct Cli {
7 #[command(subcommand)]
8 pub command: Option<Commands>,
9
10 #[arg(long)]
12 pub tui: bool,
13
14 #[arg(long)]
16 pub web: bool,
17
18 #[arg(long)]
20 pub json: bool,
21
22 #[arg(long)]
24 pub autonomy: Option<String>,
25
26 #[arg(long)]
28 pub model: Option<String>,
29
30 #[arg(long, global = true)]
32 pub local: bool,
33
34 #[arg(long, global = true)]
36 pub budget: Option<f64>,
37
38 #[arg(long, global = true)]
41 pub max_cost_usd: Option<f64>,
42
43 #[arg(long, global = true)]
45 pub max_wall_secs: Option<u64>,
46
47 #[arg(long, global = true)]
49 pub max_tokens: Option<u64>,
50
51 #[arg(long, global = true)]
54 pub bind: Option<String>,
55
56 #[arg(long, global = true)]
58 pub sandbox: Option<String>,
59
60 #[arg(long, global = true)]
62 pub profile: Option<String>,
63
64 #[arg(long, global = true)]
66 pub no_checkpoint: bool,
67
68 #[arg(long)]
70 pub agent: Option<String>,
71
72 #[arg(long = "continue", global = true)]
75 pub continue_last: bool,
76
77 #[arg(long, global = true)]
79 pub fresh: bool,
80
81 #[arg(long, global = true)]
83 pub yes: bool,
84}
85
86#[derive(Subcommand)]
87pub enum Commands {
88 Run {
90 task: String,
92
93 #[arg(long)]
96 json: bool,
97 },
98
99 Plan {
101 task: String,
103
104 #[arg(long)]
106 json: bool,
107 },
108
109 Chat,
111
112 Tui,
114
115 Launch {
117 #[arg(long, default_value = "9339")]
119 port: u16,
120
121 #[arg(long)]
123 tui: bool,
124 },
125
126 Console {
128 #[arg(long, default_value = "9339")]
130 port: u16,
131 },
132
133 Daemon,
135
136 Agent {
138 #[command(subcommand)]
139 action: AgentAction,
140 },
141
142 Swarm {
144 task: String,
146 },
147
148 Schedule {
150 task: String,
152
153 #[arg(long)]
155 cron: String,
156
157 #[arg(long)]
159 autonomy: Option<String>,
160
161 #[arg(long)]
163 report: Vec<String>,
164 },
165
166 Model {
168 #[arg(long)]
170 set: Option<String>,
171
172 #[arg(long)]
174 list: bool,
175 },
176
177 Route {
179 #[command(subcommand)]
180 action: RouteAction,
181 },
182
183 Auth {
185 #[command(subcommand)]
186 action: AuthAction,
187 },
188
189 Skills {
191 #[command(subcommand)]
192 action: SkillsAction,
193 },
194
195 Plugins {
197 #[command(subcommand)]
198 action: PluginsAction,
199 },
200
201 Tools {
203 #[command(subcommand)]
204 action: ToolsAction,
205 },
206
207 Security {
209 #[command(subcommand)]
210 action: SecurityAction,
211 },
212
213 Github {
215 #[command(subcommand)]
216 action: GithubAction,
217 },
218
219 Compact {
221 #[arg(long)]
223 task: Option<String>,
224 #[arg(long)]
226 out: Option<PathBuf>,
227 #[arg(long)]
229 json: bool,
230 },
231
232 Mcp {
234 #[command(subcommand)]
235 action: McpAction,
236 },
237
238 Checkpoint {
240 #[command(subcommand)]
241 action: CheckpointAction,
242 },
243
244 Rewind {
246 id: String,
248 },
249
250 Replay {
252 run_id: String,
254 #[arg(long)]
256 scrub: bool,
257 },
258
259 Gateway {
261 #[command(subcommand)]
262 action: GatewayAction,
263 },
264
265 Sessions {
267 #[command(subcommand)]
268 action: SessionAction,
269 },
270
271 Learn,
273
274 Init,
276
277 Status,
279
280 Memory {
282 #[command(subcommand)]
283 action: MemoryAction,
284 },
285
286 Permissions {
288 #[command(subcommand)]
289 action: PermissionAction,
290 },
291
292 Profile {
294 #[command(subcommand)]
295 action: ProfileAction,
296 },
297
298 Import {
300 #[command(subcommand)]
301 source: ImportSource,
302 },
303
304 Config {
306 #[arg(short)]
308 edit: bool,
309 },
310
311 Update,
313
314 Doctor,
316
317 Setup,
319
320 Demo,
322
323 Share,
325
326 Hook {
328 #[command(subcommand)]
329 action: HookAction,
330 },
331
332 Voice {
334 #[command(subcommand)]
335 action: VoiceAction,
336 },
337
338 Browser {
340 #[arg(default_value = "https://example.com")]
342 url: String,
343 },
344}
345
346#[derive(Subcommand)]
347pub enum AgentAction {
348 Create { name: String },
349 List,
350 Edit { name: String },
351 Rm { name: String },
352 Run { name: String, task: String },
353 Mention { name: String, message: String },
354}
355
356#[derive(Subcommand)]
357pub enum AuthAction {
358 Add {
359 provider: String,
360 },
361 List,
362 Rm {
363 provider: String,
364 },
365 Login {
367 provider: String,
368 #[arg(long)]
370 client_id: Option<String>,
371 },
372}
373
374#[derive(Subcommand)]
375pub enum SkillsAction {
376 List,
377 View {
378 name: String,
379 },
380 Create {
381 name: String,
382 },
383 Install {
386 source: String,
387 },
388 Update {
389 name: String,
390 },
391 Prune,
392 Rm {
394 name: String,
395 },
396}
397
398#[derive(Subcommand)]
399pub enum PluginsAction {
400 List,
401 Install {
402 source: String,
403 #[arg(long)]
404 allow: bool,
405 },
406 Rm {
407 name: String,
408 },
409}
410
411#[derive(Subcommand)]
412pub enum GithubAction {
413 Review {
415 pr: u64,
417 #[arg(long)]
419 dry_run: bool,
420 #[arg(long)]
422 model: Option<String>,
423 #[arg(long)]
425 allowed_tools: Option<String>,
426 },
427 Status,
429 Logs { run_id: String },
431}
432
433#[derive(Subcommand)]
434pub enum SecurityAction {
435 Audit {
437 #[arg(long)]
439 json: bool,
440 },
441}
442
443#[derive(Subcommand)]
444pub enum ToolsAction {
445 List {
446 #[arg(long)]
447 surface: Option<String>,
448 },
449 Enable {
450 tool: String,
451 },
452 Disable {
453 tool: String,
454 },
455}
456
457#[derive(Subcommand)]
458pub enum McpAction {
459 Add {
460 server: String,
461
462 #[arg(long)]
464 command: Option<String>,
465
466 #[arg(long, value_delimiter = ' ', allow_hyphen_values = true)]
468 args: Vec<String>,
469
470 #[arg(long)]
472 transport: Option<String>,
473 },
474 List,
475 Rm {
476 server: String,
477 },
478}
479
480#[derive(Subcommand)]
481pub enum CheckpointAction {
482 List,
484 Diff {
486 id: String,
488 },
489 Prune {
491 #[arg(long, default_value = "30")]
493 older_than_days: u64,
494 },
495}
496
497#[derive(Subcommand)]
498pub enum GatewayAction {
499 Start,
500 Status,
501 Health,
502 Abort { run: String },
503 Stop,
504}
505
506#[derive(Subcommand)]
507pub enum SessionAction {
508 List,
509 Export {
510 id: String,
511 path: Option<PathBuf>,
512 },
513 Cleanup {
514 #[arg(long, default_value_t = 30)]
515 older_than_days: u64,
516 },
517 Search {
519 query: String,
520 #[arg(long, default_value_t = 10)]
521 limit: usize,
522 },
523}
524
525#[derive(Subcommand)]
526pub enum ProfileAction {
527 Create { name: String },
528 List,
529 Use { name: String },
530}
531
532#[derive(Subcommand)]
533pub enum ImportSource {
534 ClaudeCode {
536 path: Option<PathBuf>,
538 },
539 Codex {
541 path: Option<PathBuf>,
543 },
544 #[command(name = "opencode")]
546 OpenCode {
547 path: Option<PathBuf>,
549 },
550 Openclaw {
552 path: Option<PathBuf>,
554 },
555 Auto,
557}
558
559#[derive(Subcommand)]
560pub enum MemoryAction {
561 List,
562 Forget {
563 id: String,
564 },
565 Add {
566 key: String,
567 value: String,
568 },
569 Replace {
570 id: String,
571 key: String,
572 value: String,
573 },
574 Recall {
575 query: String,
576 #[arg(long, default_value_t = 10)]
577 limit: usize,
578 },
579 Consolidate,
580 Docs,
581 Search {
582 query: String,
583 #[arg(long, default_value_t = 10)]
584 limit: usize,
585 },
586 Scroll {
587 session: String,
588 #[arg(long, default_value_t = 0)]
589 around: usize,
590 #[arg(long, default_value_t = 3)]
591 before: usize,
592 #[arg(long, default_value_t = 3)]
593 after: usize,
594 },
595 Graph {
596 #[command(subcommand)]
597 action: GraphAction,
598 },
599}
600
601#[derive(Subcommand)]
602pub enum GraphAction {
603 UpsertNode {
604 id: String,
605 label: String,
606 #[arg(long, default_value = "entity")]
607 kind: String,
608 #[arg(long, default_value = "{}")]
609 properties: String,
610 },
611 UpsertEdge {
612 from_id: String,
613 relation: String,
614 to_id: String,
615 #[arg(long)]
616 id: Option<String>,
617 #[arg(long, default_value_t = 1.0)]
618 weight: f64,
619 #[arg(long, default_value = "{}")]
620 properties: String,
621 },
622 Get {
623 id: String,
624 },
625 Neighbors {
626 id: String,
627 #[arg(long, default_value = "both")]
628 direction: String,
629 #[arg(long, default_value_t = 20)]
630 limit: usize,
631 },
632 Search {
633 query: String,
634 #[arg(long, default_value_t = 20)]
635 limit: usize,
636 },
637 Export,
638 DeleteNode {
639 id: String,
640 },
641 DeleteEdge {
642 id: String,
643 },
644 SyncNeo4j,
645}
646
647#[derive(Subcommand)]
648pub enum PermissionAction {
649 List,
651 Set { mode: String },
653 AllowTool { tool: String },
655 AskTool { tool: String },
657 DenyTool { tool: String },
659 AllowPath { path: PathBuf },
661 DenyPath { path: PathBuf },
663}
664
665#[derive(Subcommand)]
666pub enum RouteAction {
667 Set {
670 provider: String,
672 },
673 Clear,
675 Show,
677}
678
679#[derive(Subcommand)]
680pub enum HookAction {
681 Install,
683 Scan {
685 #[arg(long)]
687 all: bool,
688 },
689}
690
691#[derive(Subcommand)]
692pub enum VoiceAction {
693 Speak { text: String },
695 Transcribe { file: String },
697 Providers,
699}