chasm/cli.rs
1// Copyright (c) 2024-2026 Nervosys LLC
2// SPDX-License-Identifier: AGPL-3.0-only
3//! CLI argument definitions using clap derive macros
4
5use clap::{Parser, Subcommand};
6
7/// CHAt System Manager (chasm) - Manage and merge chat sessions across workspaces
8#[derive(Parser)]
9#[command(name = "chasm")]
10#[command(author = "Nervosys")]
11#[command(version)]
12#[command(about = "Manage and merge chat sessions across workspaces", long_about = None)]
13pub struct Cli {
14 #[command(subcommand)]
15 pub command: Commands,
16}
17
18#[derive(Subcommand)]
19pub enum Commands {
20 // ============================================================================
21 // List Commands
22 // ============================================================================
23 /// List workspaces, sessions, or paths
24 #[command(visible_alias = "ls")]
25 List {
26 #[command(subcommand)]
27 command: Option<ListCommands>,
28 },
29
30 // ============================================================================
31 // Find Commands
32 // ============================================================================
33 /// Search workspaces or sessions by text pattern (title, content, ID)
34 Find {
35 #[command(subcommand)]
36 command: Option<FindCommands>,
37 },
38
39 // ============================================================================
40 // Show Commands
41 // ============================================================================
42 /// Show workspaces, sessions, or paths
43 #[command(visible_alias = "info")]
44 Show {
45 #[command(subcommand)]
46 command: Option<ShowCommands>,
47 },
48
49 // ============================================================================
50 // Fetch Commands
51 // ============================================================================
52 /// Fetch chat sessions from workspaces, sessions, or paths
53 Fetch {
54 #[command(subcommand)]
55 command: Option<FetchCommands>,
56 },
57
58 // ============================================================================
59 // Merge Commands
60 // ============================================================================
61 /// Merge chat sessions from workspaces, sessions, or paths
62 Merge {
63 #[command(subcommand)]
64 command: Option<MergeCommands>,
65 },
66
67 // ============================================================================
68 // Export Commands
69 // ============================================================================
70 /// Export chat sessions from workspaces, sessions, or paths
71 Export {
72 #[command(subcommand)]
73 command: Option<ExportCommands>,
74 },
75
76 // ============================================================================
77 // Import Commands
78 // ============================================================================
79 /// Import session files from external directories into a workspace
80 Import {
81 #[command(subcommand)]
82 command: Option<ImportCommands>,
83 },
84
85 // ============================================================================
86 // Move Commands
87 // ============================================================================
88 /// Move chat sessions between workspaces
89 #[command(visible_alias = "mv")]
90 Move {
91 #[command(subcommand)]
92 command: Option<MoveCommands>,
93 },
94
95 // ============================================================================
96 // Git Integration Commands
97 // ============================================================================
98 /// Git integration for chat session versioning
99 Git {
100 #[command(subcommand)]
101 command: GitCommands,
102 },
103
104 // ============================================================================
105 // Migration Commands
106 // ============================================================================
107 /// Migration commands for moving chat sessions between machines
108 Migration {
109 #[command(subcommand)]
110 command: MigrationCommands,
111 },
112
113 // ============================================================================
114 // Run Commands (Agent Launcher + TUI)
115 // ============================================================================
116 /// Launch an AI coding agent with auto-save, or run interactive tools
117 ///
118 /// Supported agents: claude, open, claw, cursor, codex, droid, gemini
119 Run {
120 #[command(subcommand)]
121 command: RunCommands,
122 },
123
124 // ============================================================================
125 // Watch Command (File-System Monitor)
126 // ============================================================================
127 /// Watch agent session directories for changes and auto-harvest
128 ///
129 /// Monitors session storage paths for new or modified files.
130 /// Default: watches all known agent directories.
131 #[command(visible_alias = "w")]
132 Watch {
133 /// Watch a specific agent's session directory (e.g., claude, gemini)
134 #[arg(short, long)]
135 agent: Option<String>,
136
137 /// Watch a custom path instead of agent directories
138 #[arg(short, long)]
139 path: Option<String>,
140
141 /// Debounce interval in seconds before harvesting (default: 3)
142 #[arg(short, long, default_value = "3")]
143 debounce: u64,
144
145 /// Detect changes without harvesting (dry-run)
146 #[arg(long)]
147 no_harvest: bool,
148
149 /// Show detailed file change events
150 #[arg(short, long)]
151 verbose: bool,
152 },
153
154 // ============================================================================
155 // Provider Commands
156 // ============================================================================
157 /// Manage LLM providers (Ollama, vLLM, Foundry, Cursor, etc.)
158 Provider {
159 #[command(subcommand)]
160 command: ProviderCommands,
161 },
162
163 // ============================================================================
164 // Detect Commands
165 // ============================================================================
166 /// Auto-detect workspace and provider information
167 Detect {
168 #[command(subcommand)]
169 command: Option<DetectCommands>,
170 },
171
172 // ============================================================================
173 // Register Commands
174 // ============================================================================
175 /// Add on-disk sessions to VS Code's database index (makes orphaned sessions visible)
176 Register {
177 #[command(subcommand)]
178 command: RegisterCommands,
179 },
180
181 // ============================================================================
182 // Sync Commands (shortcut to harvest sync)
183 // ============================================================================
184 /// Sync sessions between the harvest database and provider workspaces
185 Sync {
186 /// Path to the harvest database
187 #[arg(long)]
188 path: Option<String>,
189
190 /// Push sessions from database to provider workspaces (restore)
191 #[arg(long)]
192 push: bool,
193
194 /// Pull sessions from provider workspaces into database (backup)
195 #[arg(long)]
196 pull: bool,
197
198 /// Filter by provider name
199 #[arg(long)]
200 provider: Option<String>,
201
202 /// Filter by workspace/project path
203 #[arg(long)]
204 workspace: Option<String>,
205
206 /// Session IDs to sync (space-separated)
207 #[arg(long, num_args = 1..)]
208 sessions: Option<Vec<String>>,
209
210 /// Target format for push: auto (detect from provider), jsonl, json
211 #[arg(long, default_value = "auto")]
212 format: String,
213
214 /// Overwrite existing files without prompting
215 #[arg(long)]
216 force: bool,
217
218 /// Dry run - show what would be synced without making changes
219 #[arg(long)]
220 dry_run: bool,
221 },
222
223 // ============================================================================
224 // Harvest Commands
225 // ============================================================================
226 /// Harvest chat sessions from all providers into a unified database
227 Harvest {
228 #[command(subcommand)]
229 command: HarvestCommands,
230 },
231
232 // ============================================================================
233 // Recover Commands
234 // ============================================================================
235 /// Recover lost chat sessions from backups, recording state, or corrupted files
236 #[command(visible_alias = "restore")]
237 Recover {
238 #[command(subcommand)]
239 command: RecoverCommands,
240 },
241
242 // ============================================================================
243 // API Server Commands
244 // ============================================================================
245 /// Start the HTTP API server for the web frontend
246 #[command(visible_alias = "serve")]
247 Api {
248 #[command(subcommand)]
249 command: ApiCommands,
250 },
251
252 // ============================================================================
253 // Agency Commands
254 // ============================================================================
255 /// Agent Development Kit - manage agents and orchestration
256 Agency {
257 #[command(subcommand)]
258 command: AgencyCommands,
259 },
260
261 // ============================================================================
262 // Telemetry Commands
263 // ============================================================================
264 /// Manage anonymous usage data collection (opt-in by default)
265 Telemetry {
266 #[command(subcommand)]
267 command: Option<TelemetryCommands>,
268 },
269
270 // ============================================================================
271 // Completions Command
272 // ============================================================================
273 /// Generate shell completions for bash, zsh, fish, or PowerShell
274 Completions {
275 /// Shell to generate completions for
276 #[arg(value_enum)]
277 shell: CompletionShell,
278 },
279
280 // ============================================================================
281 // Doctor Command
282 // ============================================================================
283 /// Check system environment, providers, and configuration health
284 #[command(visible_alias = "check")]
285 Doctor {
286 /// Run all checks including network connectivity
287 #[arg(long)]
288 full: bool,
289
290 /// Output format: text, json
291 #[arg(long, default_value = "text")]
292 format: String,
293
294 /// Attempt to fix detected issues automatically
295 #[arg(long)]
296 fix: bool,
297 },
298
299 // ============================================================================
300 // Easter Egg
301 // ============================================================================
302 /// Show banner
303 #[command(hide = true)]
304 Banner,
305}
306
307// ============================================================================
308// List Subcommands
309// ============================================================================
310
311#[derive(Subcommand)]
312pub enum ListCommands {
313 /// List all VS Code workspaces
314 #[command(visible_alias = "ws")]
315 Workspaces,
316
317 /// List all chat sessions
318 #[command(visible_alias = "s")]
319 Sessions {
320 /// Filter by project path
321 #[arg(long)]
322 project_path: Option<String>,
323
324 /// Show file sizes
325 #[arg(long, short = 's')]
326 size: bool,
327
328 /// Filter by provider (vscode, cursor, claudecode, opencode, openclaw, antigravity)
329 #[arg(long, short = 'p')]
330 provider: Option<String>,
331
332 /// Include all providers
333 #[arg(long)]
334 all_providers: bool,
335 },
336
337 /// List available AI coding agents and their installation status
338 #[command(visible_alias = "a")]
339 Agents,
340
341 /// List agent mode sessions (Copilot Edits / chatEditingSessions)
342 #[command(visible_alias = "e")]
343 Edits {
344 /// Filter by project path
345 #[arg(long)]
346 project_path: Option<String>,
347
348 /// Show file sizes
349 #[arg(long, short = 's')]
350 size: bool,
351
352 /// Filter by provider (vscode, cursor, claudecode, opencode, openclaw, antigravity)
353 #[arg(long, short = 'p')]
354 provider: Option<String>,
355 },
356
357 /// List sessions for a specific project path
358 Path {
359 /// Project path (default: current directory)
360 project_path: Option<String>,
361 },
362
363 /// List unregistered sessions (exist on disk but invisible to VS Code)
364 Orphaned {
365 /// Project path (default: current directory)
366 #[arg(long)]
367 path: Option<String>,
368 },
369}
370
371// ============================================================================
372// Find Subcommands
373// ============================================================================
374
375#[derive(Subcommand)]
376pub enum FindCommands {
377 /// Search workspaces by name pattern (defaults to current directory name)
378 #[command(visible_alias = "ws")]
379 Workspace {
380 /// Text pattern to match (case-insensitive, defaults to current directory name)
381 pattern: Option<String>,
382 },
383
384 /// Search sessions by title, content, or ID pattern
385 #[command(visible_alias = "s")]
386 Session {
387 /// Text pattern to match (case-insensitive, defaults to current directory name)
388 pattern: Option<String>,
389
390 /// Filter by project path or workspace name
391 #[arg(long, short = 'w')]
392 workspace: Option<String>,
393
394 /// Only search in session titles (faster, skip content search)
395 #[arg(long, short = 't')]
396 title_only: bool,
397
398 /// Include message content in search (slower)
399 #[arg(long, short = 'c')]
400 content: bool,
401
402 /// Filter sessions modified after this date (YYYY-MM-DD)
403 #[arg(long)]
404 after: Option<String>,
405
406 /// Filter sessions modified before this date (YYYY-MM-DD)
407 #[arg(long)]
408 before: Option<String>,
409
410 /// Filter by internal message timestamp date (YYYY-MM-DD)
411 #[arg(long)]
412 date: Option<String>,
413
414 /// Search across all workspaces (not just current project)
415 #[arg(long, short = 'a')]
416 all: bool,
417
418 /// Filter by provider (vscode, cursor, claudecode, opencode, openclaw, antigravity)
419 #[arg(long, short = 'p')]
420 provider: Option<String>,
421
422 /// Search across all providers
423 #[arg(long)]
424 all_providers: bool,
425
426 /// Limit number of results
427 #[arg(long, short = 'n', default_value = "50")]
428 limit: usize,
429 },
430
431 /// Search sessions within a specific project path
432 Path {
433 /// Search pattern (case-insensitive, defaults to current directory name)
434 pattern: Option<String>,
435
436 /// Project path (default: current directory)
437 #[arg(long)]
438 project_path: Option<String>,
439 },
440}
441
442// ============================================================================
443// Show Subcommands
444// ============================================================================
445
446#[derive(Subcommand)]
447pub enum ShowCommands {
448 /// Show workspace details
449 #[command(visible_alias = "ws")]
450 Workspace {
451 /// Workspace name or hash
452 workspace: String,
453 },
454
455 /// Show session details
456 #[command(visible_alias = "s")]
457 Session {
458 /// Session ID or filename
459 session_id: String,
460
461 /// Project path to search in
462 #[arg(long)]
463 project_path: Option<String>,
464 },
465
466 /// Show agent mode session details (Copilot Edits)
467 #[command(visible_alias = "a")]
468 Agent {
469 /// Agent session ID
470 session_id: String,
471
472 /// Project path to search in
473 #[arg(long)]
474 project_path: Option<String>,
475 },
476
477 /// Show the VS Code session index (state.vscdb) for a workspace
478 #[command(visible_alias = "idx")]
479 Index {
480 /// Project path (default: current directory)
481 #[arg(long)]
482 path: Option<String>,
483
484 /// Show indexes for all workspaces that have chat sessions
485 #[arg(long, short)]
486 all: bool,
487 },
488
489 /// Show chat history timeline for a project path
490 Path {
491 /// Path to the project (default: current directory)
492 project_path: Option<String>,
493 },
494
495 /// Show timeline of session activity with gaps visualization
496 Timeline {
497 /// Path to the project (default: current directory)
498 project_path: Option<String>,
499
500 /// Include agent mode sessions
501 #[arg(long, short = 'a')]
502 agents: bool,
503
504 /// Filter by provider (vscode, cursor, claudecode, opencode, openclaw, antigravity)
505 #[arg(long, short = 'p')]
506 provider: Option<String>,
507
508 /// Include all providers (aggregate timeline)
509 #[arg(long)]
510 all_providers: bool,
511 },
512}
513
514// ============================================================================
515// Fetch Subcommands
516// ============================================================================
517
518#[derive(Subcommand)]
519pub enum FetchCommands {
520 /// Fetch sessions from workspaces matching a pattern
521 #[command(visible_alias = "ws")]
522 Workspace {
523 /// Workspace name pattern (case-insensitive)
524 workspace_name: String,
525
526 /// Target project path (default: current directory)
527 #[arg(long)]
528 target_path: Option<String>,
529
530 /// Overwrite existing sessions
531 #[arg(long)]
532 force: bool,
533
534 /// Don't register sessions in VS Code index
535 #[arg(long)]
536 no_register: bool,
537 },
538
539 /// Fetch specific sessions by ID
540 #[command(visible_alias = "s")]
541 Session {
542 /// Session IDs to fetch (space-separated)
543 #[arg(required = true, num_args = 1..)]
544 session_ids: Vec<String>,
545
546 /// Target project path (default: current directory)
547 #[arg(long)]
548 target_path: Option<String>,
549
550 /// Overwrite existing sessions
551 #[arg(long)]
552 force: bool,
553
554 /// Don't register sessions in VS Code index
555 #[arg(long)]
556 no_register: bool,
557 },
558
559 /// Fetch chat sessions from other workspaces by project path
560 Path {
561 /// Path to the project (default: current directory)
562 project_path: Option<String>,
563
564 /// Overwrite existing sessions and skip VS Code running check
565 #[arg(long)]
566 force: bool,
567
568 /// Don't register sessions in VS Code index
569 #[arg(long)]
570 no_register: bool,
571 },
572}
573
574// ============================================================================
575// Merge Subcommands
576// ============================================================================
577
578#[derive(Subcommand)]
579pub enum MergeCommands {
580 /// Merge sessions from workspaces matching a name pattern
581 #[command(visible_alias = "ws")]
582 Workspace {
583 /// Workspace name pattern to search for (case-insensitive)
584 workspace_name: String,
585
586 /// Title for the merged session
587 #[arg(short, long)]
588 title: Option<String>,
589
590 /// Target project path to save the merged session (default: current directory)
591 #[arg(long)]
592 target_path: Option<String>,
593
594 /// Skip VS Code running check
595 #[arg(long)]
596 force: bool,
597
598 /// Don't create backup of current sessions
599 #[arg(long)]
600 no_backup: bool,
601 },
602
603 /// Merge sessions from multiple workspace name patterns
604 #[command(visible_alias = "wss")]
605 Workspaces {
606 /// Workspace name patterns to search for (space-separated, case-insensitive)
607 #[arg(required = true, num_args = 1..)]
608 workspace_names: Vec<String>,
609
610 /// Title for the merged session
611 #[arg(short, long)]
612 title: Option<String>,
613
614 /// Target project path to save the merged session (default: current directory)
615 #[arg(long)]
616 target_path: Option<String>,
617
618 /// Skip VS Code running check
619 #[arg(long)]
620 force: bool,
621
622 /// Don't create backup of current sessions
623 #[arg(long)]
624 no_backup: bool,
625 },
626
627 /// Merge specific sessions by their IDs or filenames
628 #[command(visible_alias = "s")]
629 Sessions {
630 /// Session IDs or filenames (comma-separated or space-separated)
631 #[arg(required = true, num_args = 1..)]
632 sessions: Vec<String>,
633
634 /// Title for the merged session
635 #[arg(short, long)]
636 title: Option<String>,
637
638 /// Target project path to save the merged session (default: current directory)
639 #[arg(long)]
640 target_path: Option<String>,
641
642 /// Skip VS Code running check
643 #[arg(long)]
644 force: bool,
645
646 /// Don't create backup of current sessions
647 #[arg(long)]
648 no_backup: bool,
649 },
650
651 /// Merge all sessions for a project path into one unified chat
652 Path {
653 /// Path to the project (default: current directory)
654 project_path: Option<String>,
655
656 /// Title for the merged session
657 #[arg(short, long)]
658 title: Option<String>,
659
660 /// Skip VS Code running check
661 #[arg(long)]
662 force: bool,
663
664 /// Don't create backup of current sessions
665 #[arg(long)]
666 no_backup: bool,
667 },
668
669 /// Merge sessions from an LLM provider (Ollama, Cursor, etc.)
670 Provider {
671 /// Provider name (copilot, cursor, ollama, vllm, foundry, etc.)
672 provider_name: String,
673
674 /// Title for the merged session
675 #[arg(short, long)]
676 title: Option<String>,
677
678 /// Target project path to save the merged session (default: current directory)
679 #[arg(long)]
680 target_path: Option<String>,
681
682 /// Session IDs from the provider to include (omit for all)
683 #[arg(long)]
684 sessions: Option<Vec<String>>,
685
686 /// Skip VS Code running check
687 #[arg(long)]
688 force: bool,
689
690 /// Don't create backup of current sessions
691 #[arg(long)]
692 no_backup: bool,
693 },
694
695 /// Merge sessions from multiple providers
696 #[command(name = "providers")]
697 Providers {
698 /// Provider names (space-separated: copilot cursor ollama)
699 #[arg(required = true, num_args = 1..)]
700 providers: Vec<String>,
701
702 /// Title for the merged session
703 #[arg(short, long)]
704 title: Option<String>,
705
706 /// Target project path to save the merged session (default: current directory)
707 #[arg(long)]
708 target_path: Option<String>,
709
710 /// Filter by workspace name pattern (applies to providers that support workspaces)
711 #[arg(long)]
712 workspace: Option<String>,
713
714 /// Skip VS Code running check
715 #[arg(long)]
716 force: bool,
717
718 /// Don't create backup of current sessions
719 #[arg(long)]
720 no_backup: bool,
721 },
722
723 /// Merge all sessions across all available providers
724 All {
725 /// Title for the merged session
726 #[arg(short, long)]
727 title: Option<String>,
728
729 /// Target project path to save the merged session (default: current directory)
730 #[arg(long)]
731 target_path: Option<String>,
732
733 /// Filter by workspace name pattern (applies to providers that support workspaces)
734 #[arg(long)]
735 workspace: Option<String>,
736
737 /// Skip VS Code running check
738 #[arg(long)]
739 force: bool,
740
741 /// Don't create backup of current sessions
742 #[arg(long)]
743 no_backup: bool,
744 },
745}
746
747// ============================================================================
748// Export Subcommands
749// ============================================================================
750
751#[derive(Subcommand)]
752pub enum ExportCommands {
753 /// Export sessions from a workspace by hash
754 #[command(visible_alias = "ws")]
755 Workspace {
756 /// Destination directory for exported sessions
757 destination: String,
758
759 /// Source workspace hash
760 hash: String,
761 },
762
763 /// Export specific sessions by ID
764 #[command(visible_alias = "s")]
765 Sessions {
766 /// Destination directory for exported sessions
767 destination: String,
768
769 /// Session IDs to export (space-separated)
770 #[arg(required = true, num_args = 1..)]
771 session_ids: Vec<String>,
772
773 /// Source project path
774 #[arg(long)]
775 project_path: Option<String>,
776 },
777
778 /// Export chat sessions from a project path
779 Path {
780 /// Destination directory for exported sessions
781 destination: String,
782
783 /// Source project path (default: current directory)
784 project_path: Option<String>,
785 },
786
787 /// Export chat sessions from multiple project paths (batch operation)
788 Batch {
789 /// Base destination directory (subdirectories created per project)
790 destination: String,
791
792 /// Project paths to export (space-separated)
793 #[arg(required = true, num_args = 1..)]
794 project_paths: Vec<String>,
795 },
796}
797
798// ============================================================================
799// Import Subcommands
800// ============================================================================
801
802#[derive(Subcommand)]
803pub enum ImportCommands {
804 /// Copy session files from external directory into a workspace
805 #[command(visible_alias = "ws")]
806 Workspace {
807 /// Source directory containing session JSON files to import
808 source: String,
809
810 /// Target workspace hash
811 hash: String,
812
813 /// Overwrite existing sessions
814 #[arg(long)]
815 force: bool,
816 },
817
818 /// Copy specific session files into a workspace
819 #[command(visible_alias = "s")]
820 Sessions {
821 /// Session files to import (space-separated paths)
822 #[arg(required = true, num_args = 1..)]
823 session_files: Vec<String>,
824
825 /// Target project path (default: current directory)
826 #[arg(long)]
827 target_path: Option<String>,
828
829 /// Overwrite existing sessions
830 #[arg(long)]
831 force: bool,
832 },
833
834 /// Copy session files from external directory into a project workspace
835 Path {
836 /// Source directory containing session JSON files to import
837 source: String,
838
839 /// Target project path (default: current directory)
840 target_path: Option<String>,
841
842 /// Overwrite existing sessions
843 #[arg(long)]
844 force: bool,
845 },
846}
847
848// ============================================================================
849// Move Subcommands
850// ============================================================================
851
852#[derive(Subcommand)]
853pub enum MoveCommands {
854 /// Move all sessions from one workspace to another
855 #[command(visible_alias = "ws")]
856 Workspace {
857 /// Source workspace hash
858 source_hash: String,
859
860 /// Target workspace hash or project path
861 target: String,
862 },
863
864 /// Move specific sessions by ID
865 #[command(visible_alias = "s")]
866 Sessions {
867 /// Session IDs to move (space-separated)
868 #[arg(required = true, num_args = 1..)]
869 session_ids: Vec<String>,
870
871 /// Target project path
872 target_path: String,
873 },
874
875 /// Move sessions from a source path to target path
876 Path {
877 /// Source project path
878 source_path: String,
879
880 /// Target project path
881 target_path: String,
882 },
883}
884
885// ============================================================================
886// Git Subcommands
887// ============================================================================
888
889#[derive(Subcommand)]
890pub enum GitCommands {
891 /// Configure git settings for chat sessions
892 Config {
893 /// Git user name
894 #[arg(long)]
895 name: Option<String>,
896
897 /// Git user email
898 #[arg(long)]
899 email: Option<String>,
900
901 /// Project path
902 #[arg(long)]
903 path: Option<String>,
904 },
905
906 /// Initialize git versioning for chat sessions
907 Init {
908 /// Project path
909 path: String,
910 },
911
912 /// Add chat sessions to git (stage and optionally commit)
913 Add {
914 /// Project path
915 path: String,
916
917 /// Also commit the changes
918 #[arg(long)]
919 commit: bool,
920
921 /// Commit message (requires --commit)
922 #[arg(short, long)]
923 message: Option<String>,
924 },
925
926 /// Show git status of chat sessions
927 Status {
928 /// Project path
929 path: String,
930 },
931
932 /// Create a git tag snapshot of chat sessions
933 Snapshot {
934 /// Project path
935 path: String,
936
937 /// Tag name (auto-generated if not provided)
938 #[arg(long)]
939 tag: Option<String>,
940
941 /// Snapshot message
942 #[arg(short, long)]
943 message: Option<String>,
944 },
945
946 /// Track chat sessions together with associated file changes
947 Track {
948 /// Project path
949 path: String,
950
951 /// Commit message describing the changes
952 #[arg(short, long)]
953 message: Option<String>,
954
955 /// Include all staged and unstaged file changes
956 #[arg(long)]
957 all: bool,
958
959 /// Include specific files in addition to chat sessions
960 #[arg(long)]
961 files: Option<Vec<String>>,
962
963 /// Create a tag for this tracked state
964 #[arg(long)]
965 tag: Option<String>,
966 },
967
968 /// Show history of chat session commits with associated file changes
969 Log {
970 /// Project path
971 path: String,
972
973 /// Number of commits to show
974 #[arg(short = 'n', long, default_value = "10")]
975 count: usize,
976
977 /// Show only commits that include chat session changes
978 #[arg(long)]
979 sessions_only: bool,
980 },
981
982 /// Diff chat sessions between commits or current state
983 Diff {
984 /// Project path
985 path: String,
986
987 /// First commit (default: HEAD)
988 #[arg(long)]
989 from: Option<String>,
990
991 /// Second commit (default: working directory)
992 #[arg(long)]
993 to: Option<String>,
994
995 /// Show associated file changes alongside chat diffs
996 #[arg(long)]
997 with_files: bool,
998 },
999
1000 /// Restore chat sessions from a specific commit
1001 Restore {
1002 /// Project path
1003 path: String,
1004
1005 /// Commit hash, tag, or reference to restore from
1006 commit: String,
1007
1008 /// Also restore associated files from the same commit
1009 #[arg(long)]
1010 with_files: bool,
1011
1012 /// Create a backup before restoring
1013 #[arg(long)]
1014 backup: bool,
1015 },
1016}
1017
1018// ============================================================================
1019// Migration Subcommands
1020// ============================================================================
1021
1022#[derive(Subcommand)]
1023pub enum MigrationCommands {
1024 /// Create a migration package for moving to a new machine
1025 Create {
1026 /// Output directory for migration package
1027 output: String,
1028
1029 /// Comma-separated list of project paths to include
1030 #[arg(long)]
1031 projects: Option<String>,
1032
1033 /// Include all workspaces with chat sessions
1034 #[arg(long)]
1035 all: bool,
1036 },
1037
1038 /// Restore a migration package on a new machine
1039 Restore {
1040 /// Path to migration package directory
1041 package: String,
1042
1043 /// Project path mapping: 'old1:new1;old2:new2'
1044 #[arg(long)]
1045 mapping: Option<String>,
1046
1047 /// Show what would be done without doing it
1048 #[arg(long)]
1049 dry_run: bool,
1050 },
1051}
1052
1053// ============================================================================
1054// Run Subcommands
1055// ============================================================================
1056
1057#[derive(Subcommand)]
1058pub enum RunCommands {
1059 /// Launch interactive TUI (Text User Interface)
1060 Tui,
1061
1062 /// Launch Claude Code with auto-save
1063 #[command(visible_aliases = ["claude-code", "claudecode"])]
1064 Claude {
1065 /// Extra arguments to pass to the agent
1066 #[arg(last = true)]
1067 args: Vec<String>,
1068 /// Disable auto-save
1069 #[arg(long)]
1070 no_save: bool,
1071 /// Verbose output
1072 #[arg(short, long)]
1073 verbose: bool,
1074 },
1075
1076 /// Launch OpenCode with auto-save
1077 #[command(visible_aliases = ["opencode", "open-code"])]
1078 Open {
1079 #[arg(last = true)]
1080 args: Vec<String>,
1081 #[arg(long)]
1082 no_save: bool,
1083 #[arg(short, long)]
1084 verbose: bool,
1085 },
1086
1087 /// Launch OpenClaw (ClawdBot) with auto-save
1088 #[command(visible_aliases = ["openclaw", "clawdbot"])]
1089 Claw {
1090 #[arg(last = true)]
1091 args: Vec<String>,
1092 #[arg(long)]
1093 no_save: bool,
1094 #[arg(short, long)]
1095 verbose: bool,
1096 },
1097
1098 /// Launch Cursor CLI with auto-save
1099 Cursor {
1100 #[arg(last = true)]
1101 args: Vec<String>,
1102 #[arg(long)]
1103 no_save: bool,
1104 #[arg(short, long)]
1105 verbose: bool,
1106 },
1107
1108 /// Launch Codex CLI (OpenAI) with auto-save
1109 #[command(visible_aliases = ["codex-cli", "codexcli"])]
1110 Codex {
1111 #[arg(last = true)]
1112 args: Vec<String>,
1113 #[arg(long)]
1114 no_save: bool,
1115 #[arg(short, long)]
1116 verbose: bool,
1117 },
1118
1119 /// Launch Droid CLI (Factory) with auto-save
1120 #[command(visible_aliases = ["droid-cli", "droidcli", "factory"])]
1121 Droid {
1122 #[arg(last = true)]
1123 args: Vec<String>,
1124 #[arg(long)]
1125 no_save: bool,
1126 #[arg(short, long)]
1127 verbose: bool,
1128 },
1129
1130 /// Launch Gemini CLI (Google) with auto-save
1131 #[command(visible_aliases = ["gemini-cli", "geminicli"])]
1132 Gemini {
1133 #[arg(last = true)]
1134 args: Vec<String>,
1135 #[arg(long)]
1136 no_save: bool,
1137 #[arg(short, long)]
1138 verbose: bool,
1139 },
1140}
1141
1142// ============================================================================
1143// Provider Subcommands
1144// ============================================================================
1145
1146#[derive(Subcommand)]
1147pub enum ProviderCommands {
1148 /// List all discovered LLM providers
1149 List,
1150
1151 /// Show detailed info about a specific provider
1152 Info {
1153 /// Provider name (copilot, cursor, ollama, vllm, foundry, lm-studio, etc.)
1154 provider: String,
1155 },
1156
1157 /// Configure a provider
1158 Config {
1159 /// Provider name
1160 provider: String,
1161
1162 /// API endpoint URL
1163 #[arg(long)]
1164 endpoint: Option<String>,
1165
1166 /// API key
1167 #[arg(long)]
1168 api_key: Option<String>,
1169
1170 /// Default model
1171 #[arg(long)]
1172 model: Option<String>,
1173
1174 /// Enable or disable the provider
1175 #[arg(long)]
1176 enabled: Option<bool>,
1177 },
1178
1179 /// Import sessions from another provider
1180 Import {
1181 /// Source provider name
1182 #[arg(long)]
1183 from: String,
1184
1185 /// Target project path (or current directory)
1186 #[arg(long)]
1187 path: Option<String>,
1188
1189 /// Session ID to import (omit for all)
1190 #[arg(long)]
1191 session: Option<String>,
1192 },
1193
1194 /// Test connection to a provider
1195 Test {
1196 /// Provider name
1197 provider: String,
1198 },
1199}
1200
1201// ============================================================================
1202// Detect Subcommands
1203// ============================================================================
1204
1205#[derive(Subcommand)]
1206pub enum DetectCommands {
1207 /// Detect workspace for a path
1208 Workspace {
1209 /// Project path (default: current directory)
1210 path: Option<String>,
1211 },
1212
1213 /// Detect available providers
1214 Providers {
1215 /// Only show providers with sessions
1216 #[arg(long)]
1217 with_sessions: bool,
1218 },
1219
1220 /// Detect which provider a session belongs to
1221 Session {
1222 /// Session ID or filename
1223 session_id: String,
1224
1225 /// Project path to search in
1226 #[arg(long)]
1227 path: Option<String>,
1228 },
1229
1230 /// Detect everything (workspace, providers, sessions) for a path
1231 All {
1232 /// Project path (default: current directory)
1233 path: Option<String>,
1234
1235 /// Show detailed information
1236 #[arg(long)]
1237 verbose: bool,
1238 },
1239
1240 /// Find all workspace hashes for a project path (including orphaned workspaces with sessions)
1241 Orphaned {
1242 /// Project path (default: current directory)
1243 path: Option<String>,
1244
1245 /// Automatically recover orphaned sessions by copying to active workspace
1246 #[arg(long, short)]
1247 recover: bool,
1248 },
1249}
1250
1251// ============================================================================
1252// Register Subcommands
1253// ============================================================================
1254
1255#[derive(Subcommand)]
1256pub enum RegisterCommands {
1257 /// Register all on-disk sessions into VS Code's index (fixes orphaned sessions)
1258 All {
1259 /// Project path (default: current directory)
1260 #[arg(long)]
1261 path: Option<String>,
1262
1263 /// Merge all sessions into one before registering
1264 #[arg(long, short)]
1265 merge: bool,
1266
1267 /// Force registration even if VS Code is running
1268 #[arg(long, short)]
1269 force: bool,
1270
1271 /// Close VS Code before registering (ensures index is not overwritten by cache)
1272 #[arg(long)]
1273 close_vscode: bool,
1274
1275 /// Reopen VS Code after registering (implies --close-vscode)
1276 #[arg(long)]
1277 reopen: bool,
1278 },
1279
1280 /// Register specific sessions by ID or title into VS Code's index
1281 #[command(visible_alias = "s")]
1282 Session {
1283 /// Session IDs or filenames (without .json extension)
1284 #[arg(required_unless_present = "title")]
1285 ids: Vec<String>,
1286
1287 /// Match sessions by title instead of ID
1288 #[arg(long, short, num_args = 1.., value_delimiter = ' ')]
1289 title: Option<Vec<String>>,
1290
1291 /// Project path (default: current directory)
1292 #[arg(long)]
1293 path: Option<String>,
1294
1295 /// Force registration even if VS Code is running
1296 #[arg(long, short)]
1297 force: bool,
1298 },
1299
1300 /// Recursively walk directories to find and register orphaned sessions for all workspaces
1301 #[command(visible_alias = "r")]
1302 Recursive {
1303 /// Root path to start recursive search (default: current directory)
1304 path: Option<String>,
1305
1306 /// Maximum directory depth to recurse (default: unlimited)
1307 #[arg(long, short)]
1308 depth: Option<usize>,
1309
1310 /// Force registration even if VS Code is running
1311 #[arg(long, short)]
1312 force: bool,
1313
1314 /// Only show what would be registered without making changes
1315 #[arg(long)]
1316 dry_run: bool,
1317
1318 /// Skip directories matching these patterns (can be used multiple times)
1319 #[arg(long, short = 'x')]
1320 exclude: Vec<String>,
1321 },
1322
1323 /// Repair sessions: compact large JSONL files and rebuild the index with correct metadata
1324 #[command(visible_alias = "fix")]
1325 Repair {
1326 /// Project path (default: current directory)
1327 #[arg(long)]
1328 path: Option<String>,
1329
1330 /// Repair all workspaces that have chat sessions
1331 #[arg(long, short)]
1332 all: bool,
1333
1334 /// Recursively scan a directory tree for workspaces and repair all discovered sessions
1335 #[arg(long, short)]
1336 recursive: bool,
1337
1338 /// Maximum directory depth when using --recursive (default: unlimited)
1339 #[arg(long, short)]
1340 depth: Option<usize>,
1341
1342 /// Skip directories matching these patterns when using --recursive
1343 #[arg(long, short = 'x')]
1344 exclude: Vec<String>,
1345
1346 /// Only show what would be repaired without making changes
1347 #[arg(long)]
1348 dry_run: bool,
1349
1350 /// Force even if VS Code is running
1351 #[arg(long, short)]
1352 force: bool,
1353
1354 /// Close VS Code before repairing (ensures index is not overwritten)
1355 #[arg(long)]
1356 close_vscode: bool,
1357
1358 /// Reopen VS Code after repairing (implies --close-vscode)
1359 #[arg(long)]
1360 reopen: bool,
1361 },
1362}
1363
1364// ============================================================================
1365// Harvest Subcommands
1366// ============================================================================
1367
1368#[derive(Subcommand)]
1369pub enum HarvestCommands {
1370 /// Initialize a harvest database
1371 Init {
1372 /// Path to the database file (default: ./chat_sessions.db)
1373 #[arg(long)]
1374 path: Option<String>,
1375
1376 /// Initialize git tracking for the database
1377 #[arg(long)]
1378 git: bool,
1379 },
1380
1381 /// Scan for available providers and sessions
1382 Scan {
1383 /// Show individual sessions
1384 #[arg(long)]
1385 sessions: bool,
1386
1387 /// Scan for web-based LLM providers (ChatGPT, Claude, etc.)
1388 #[arg(long)]
1389 web: bool,
1390
1391 /// Timeout in seconds for web provider checks (default: 5)
1392 #[arg(long, default_value = "5")]
1393 timeout: u64,
1394
1395 /// Show verbose debug output for browser scanning
1396 #[arg(long, short)]
1397 verbose: bool,
1398 },
1399
1400 /// Run the harvest to collect sessions from all providers
1401 Run {
1402 /// Path to the harvest database
1403 #[arg(long)]
1404 path: Option<String>,
1405
1406 /// Only include specific providers (comma-separated: copilot,cursor,ollama)
1407 #[arg(long, value_delimiter = ',')]
1408 providers: Option<Vec<String>>,
1409
1410 /// Exclude specific providers (comma-separated)
1411 #[arg(long, value_delimiter = ',')]
1412 exclude: Option<Vec<String>>,
1413
1414 /// Only harvest sessions changed since last run
1415 #[arg(long)]
1416 incremental: bool,
1417
1418 /// Auto-commit changes to git after harvest
1419 #[arg(long)]
1420 commit: bool,
1421
1422 /// Commit message (requires --commit)
1423 #[arg(short, long)]
1424 message: Option<String>,
1425 },
1426
1427 /// Show harvest database status
1428 Status {
1429 /// Path to the harvest database
1430 #[arg(long)]
1431 path: Option<String>,
1432 },
1433
1434 /// List sessions in the harvest database
1435 List {
1436 /// Path to the harvest database
1437 #[arg(long)]
1438 path: Option<String>,
1439
1440 /// Filter by provider name
1441 #[arg(long)]
1442 provider: Option<String>,
1443
1444 /// Maximum number of sessions to show
1445 #[arg(long, default_value = "20")]
1446 limit: usize,
1447
1448 /// Search sessions by title or ID
1449 #[arg(long)]
1450 search: Option<String>,
1451 },
1452
1453 /// Export sessions from the harvest database
1454 Export {
1455 /// Output file path
1456 output: String,
1457
1458 /// Path to the harvest database
1459 #[arg(long)]
1460 path: Option<String>,
1461
1462 /// Export format: json, jsonl, md (markdown)
1463 #[arg(long, default_value = "json")]
1464 format: String,
1465
1466 /// Filter by provider name
1467 #[arg(long)]
1468 provider: Option<String>,
1469
1470 /// Export specific sessions by ID (comma-separated)
1471 #[arg(long, value_delimiter = ',')]
1472 sessions: Option<Vec<String>>,
1473 },
1474
1475 /// Import a shared chat session from a URL
1476 Share {
1477 /// Share link URL (ChatGPT, Claude, etc.)
1478 url: String,
1479
1480 /// Path to the harvest database
1481 #[arg(long)]
1482 path: Option<String>,
1483
1484 /// Custom name for the imported session
1485 #[arg(long)]
1486 name: Option<String>,
1487
1488 /// Associate with a workspace path
1489 #[arg(long)]
1490 workspace: Option<String>,
1491 },
1492
1493 /// List pending or imported share links
1494 Shares {
1495 /// Path to the harvest database
1496 #[arg(long)]
1497 path: Option<String>,
1498
1499 /// Filter by status: pending, imported, failed, expired
1500 #[arg(long)]
1501 status: Option<String>,
1502
1503 /// Maximum number of links to show
1504 #[arg(long, default_value = "20")]
1505 limit: usize,
1506 },
1507
1508 /// Create a checkpoint (version snapshot) of a session
1509 Checkpoint {
1510 /// Session ID to checkpoint
1511 session: String,
1512
1513 /// Path to the harvest database
1514 #[arg(long)]
1515 path: Option<String>,
1516
1517 /// Checkpoint description message
1518 #[arg(short, long)]
1519 message: Option<String>,
1520 },
1521
1522 /// List checkpoints for a session
1523 Checkpoints {
1524 /// Session ID to list checkpoints for
1525 session: String,
1526
1527 /// Path to the harvest database
1528 #[arg(long)]
1529 path: Option<String>,
1530 },
1531
1532 /// Revert a session to a previous checkpoint
1533 Revert {
1534 /// Session ID to revert
1535 session: String,
1536
1537 /// Checkpoint number to revert to
1538 checkpoint: i64,
1539
1540 /// Path to the harvest database
1541 #[arg(long)]
1542 path: Option<String>,
1543 },
1544
1545 /// Sync sessions between the harvest database and provider workspaces
1546 Sync {
1547 /// Path to the harvest database
1548 #[arg(long)]
1549 path: Option<String>,
1550
1551 /// Push sessions from database to provider workspaces (restore)
1552 #[arg(long)]
1553 push: bool,
1554
1555 /// Pull sessions from provider workspaces into database (backup)
1556 #[arg(long)]
1557 pull: bool,
1558
1559 /// Filter by provider name
1560 #[arg(long)]
1561 provider: Option<String>,
1562
1563 /// Filter by workspace/project path
1564 #[arg(long)]
1565 workspace: Option<String>,
1566
1567 /// Session IDs to sync (space-separated)
1568 #[arg(long, num_args = 1..)]
1569 sessions: Option<Vec<String>>,
1570
1571 /// Target format for push: auto (detect from provider), jsonl, json
1572 #[arg(long, default_value = "auto")]
1573 format: String,
1574
1575 /// Overwrite existing files without prompting
1576 #[arg(long)]
1577 force: bool,
1578
1579 /// Dry run - show what would be synced without making changes
1580 #[arg(long)]
1581 dry_run: bool,
1582 },
1583
1584 /// Rebuild the full-text search index
1585 Rebuild {
1586 /// Path to the harvest database
1587 #[arg(long)]
1588 path: Option<String>,
1589 },
1590
1591 /// Search messages across all sessions (full-text search)
1592 Search {
1593 /// Search query
1594 query: String,
1595
1596 /// Path to the harvest database
1597 #[arg(long)]
1598 path: Option<String>,
1599
1600 /// Filter by provider
1601 #[arg(long)]
1602 provider: Option<String>,
1603
1604 /// Maximum results to show
1605 #[arg(long, default_value = "20")]
1606 limit: usize,
1607 },
1608
1609 /// Git operations for the harvest database
1610 Git {
1611 #[command(subcommand)]
1612 command: HarvestGitCommands,
1613 },
1614}
1615
1616#[derive(Subcommand)]
1617pub enum HarvestGitCommands {
1618 /// Initialize git tracking for the harvest database
1619 Init {
1620 /// Path to the harvest database
1621 #[arg(long)]
1622 path: Option<String>,
1623 },
1624
1625 /// Commit changes to the harvest database
1626 Commit {
1627 /// Path to the harvest database
1628 #[arg(long)]
1629 path: Option<String>,
1630
1631 /// Commit message
1632 #[arg(short, long)]
1633 message: Option<String>,
1634 },
1635
1636 /// Show git log for the harvest database
1637 Log {
1638 /// Path to the harvest database
1639 #[arg(long)]
1640 path: Option<String>,
1641
1642 /// Number of commits to show
1643 #[arg(short = 'n', long, default_value = "10")]
1644 count: usize,
1645 },
1646
1647 /// Show changes to the harvest database
1648 Diff {
1649 /// Path to the harvest database
1650 #[arg(long)]
1651 path: Option<String>,
1652
1653 /// Compare against specific commit
1654 #[arg(long)]
1655 commit: Option<String>,
1656 },
1657
1658 /// Restore harvest database from a commit
1659 Restore {
1660 /// Commit hash to restore from
1661 commit: String,
1662
1663 /// Path to the harvest database
1664 #[arg(long)]
1665 path: Option<String>,
1666 },
1667}
1668
1669// ============================================================================
1670// Recover Subcommands
1671// ============================================================================
1672
1673#[derive(Subcommand)]
1674pub enum RecoverCommands {
1675 /// Scan for recoverable sessions from various sources
1676 Scan {
1677 /// Provider to scan: vscode, cursor, all (default: all)
1678 #[arg(long, default_value = "all")]
1679 provider: String,
1680
1681 /// Show detailed information about each session
1682 #[arg(short, long)]
1683 verbose: bool,
1684
1685 /// Include sessions older than normal retention period
1686 #[arg(long)]
1687 include_old: bool,
1688 },
1689
1690 /// Recover sessions from the recording API server
1691 Recording {
1692 /// Server URL (default: http://localhost:8787)
1693 #[arg(long, default_value = "http://localhost:8787")]
1694 server: String,
1695
1696 /// Only recover specific session ID
1697 #[arg(long)]
1698 session: Option<String>,
1699
1700 /// Output directory for recovered sessions
1701 #[arg(short, long)]
1702 output: Option<String>,
1703 },
1704
1705 /// Recover sessions from SQLite database backups
1706 Database {
1707 /// Path to the database backup file
1708 backup: String,
1709
1710 /// Extract specific session by ID
1711 #[arg(long)]
1712 session: Option<String>,
1713
1714 /// Output directory for recovered sessions
1715 #[arg(short, long)]
1716 output: Option<String>,
1717
1718 /// Output format: json, jsonl, md (default: json)
1719 #[arg(long, default_value = "json")]
1720 format: String,
1721 },
1722
1723 /// Recover sessions from incomplete/corrupted JSONL files
1724 Jsonl {
1725 /// Path to the JSONL file to repair
1726 file: String,
1727
1728 /// Output file for recovered sessions (default: same name with .recovered suffix)
1729 #[arg(short, long)]
1730 output: Option<String>,
1731
1732 /// Attempt aggressive recovery (may produce incomplete sessions)
1733 #[arg(long)]
1734 aggressive: bool,
1735 },
1736
1737 /// List sessions from VS Code's workspaceStorage that may be orphaned
1738 Orphans {
1739 /// Provider to check: vscode, cursor, all (default: all)
1740 #[arg(long, default_value = "all")]
1741 provider: String,
1742
1743 /// Show sessions not in the SQLite state database
1744 #[arg(long)]
1745 unindexed: bool,
1746
1747 /// Check if files actually exist on disk
1748 #[arg(long)]
1749 verify: bool,
1750 },
1751
1752 /// Repair corrupted session files in place
1753 Repair {
1754 /// Path to the session directory or file
1755 path: String,
1756
1757 /// Create backup before repair
1758 #[arg(long, default_value = "true")]
1759 backup: bool,
1760
1761 /// Dry run - show what would be repaired without making changes
1762 #[arg(long)]
1763 dry_run: bool,
1764 },
1765
1766 /// Show recovery status and recommendations
1767 Status {
1768 /// Provider to check: vscode, cursor, all (default: all)
1769 #[arg(long, default_value = "all")]
1770 provider: String,
1771
1772 /// Check disk space and file system health
1773 #[arg(long)]
1774 system: bool,
1775 },
1776
1777 /// Convert session files between JSON and JSONL formats
1778 Convert {
1779 /// Input file to convert (.json or .jsonl)
1780 input: String,
1781
1782 /// Output file (auto-detects format from extension, or uses --format)
1783 #[arg(short, long)]
1784 output: Option<String>,
1785
1786 /// Output format: json, jsonl (default: opposite of input)
1787 #[arg(long)]
1788 format: Option<String>,
1789
1790 /// VS Code version compatibility: legacy (< 1.109), modern (>= 1.109), both
1791 #[arg(long, default_value = "both")]
1792 compat: String,
1793 },
1794
1795 /// Extract sessions from a VS Code workspace by project path
1796 Extract {
1797 /// Project directory path (will find corresponding workspace hash)
1798 path: String,
1799
1800 /// Output directory for extracted sessions
1801 #[arg(short, long)]
1802 output: Option<String>,
1803
1804 /// Include both JSON and JSONL formats if available
1805 #[arg(long)]
1806 all_formats: bool,
1807
1808 /// Include editing session fragments (agent mode work)
1809 #[arg(long)]
1810 include_edits: bool,
1811 },
1812
1813 /// Detect and display session format and version information
1814 Detect {
1815 /// Session file to analyze (.json or .jsonl)
1816 file: String,
1817
1818 /// Show raw format detection details
1819 #[arg(long)]
1820 verbose: bool,
1821
1822 /// Output detection result as JSON
1823 #[arg(long)]
1824 json: bool,
1825 },
1826
1827 /// Upgrade session files to the current provider format (JSON to JSONL for VS Code 1.109+)
1828 Upgrade {
1829 /// Project paths to upgrade (space-separated)
1830 #[arg(required = true, num_args = 1..)]
1831 project_paths: Vec<String>,
1832
1833 /// Provider to use: vscode, cursor, auto (default: auto-detect)
1834 #[arg(long, default_value = "auto")]
1835 provider: String,
1836
1837 /// Target format: jsonl (VS Code 1.109+), json (legacy). Default: jsonl
1838 #[arg(long, default_value = "jsonl")]
1839 target_format: String,
1840
1841 /// Skip creating backup of original files
1842 #[arg(long)]
1843 no_backup: bool,
1844
1845 /// Dry run - show what would be upgraded without making changes
1846 #[arg(long)]
1847 dry_run: bool,
1848 },
1849}
1850
1851// ============================================================================
1852// API Server Subcommands
1853// ============================================================================
1854
1855#[derive(Subcommand)]
1856pub enum ApiCommands {
1857 /// Start the API server
1858 Serve {
1859 /// Host to bind to (default: 0.0.0.0 for all interfaces)
1860 #[arg(long, default_value = "0.0.0.0")]
1861 host: String,
1862
1863 /// Port to listen on (default: 8787)
1864 #[arg(short, long, default_value = "8787")]
1865 port: u16,
1866
1867 /// Path to the database file
1868 #[arg(long)]
1869 database: Option<String>,
1870 },
1871}
1872
1873// ============================================================================
1874// Agency (Agent Development Kit) Subcommands
1875// ============================================================================
1876
1877#[derive(Subcommand)]
1878pub enum AgencyCommands {
1879 /// List available agents and their roles
1880 List {
1881 /// Show detailed information
1882 #[arg(short, long)]
1883 verbose: bool,
1884 },
1885
1886 /// Show agent information
1887 Info {
1888 /// Agent name or ID
1889 name: String,
1890 },
1891
1892 /// List supported orchestration modes
1893 Modes,
1894
1895 /// Run an agent with a prompt
1896 Run {
1897 /// Agent name to run
1898 #[arg(short, long, default_value = "assistant")]
1899 agent: String,
1900
1901 /// Prompt or task for the agent
1902 prompt: String,
1903
1904 /// Model to use (e.g., gemini-2.0-flash, gpt-4o)
1905 #[arg(short, long)]
1906 model: Option<String>,
1907
1908 /// Orchestration mode (single, sequential, parallel, swarm)
1909 #[arg(long, default_value = "single")]
1910 orchestration: String,
1911
1912 /// Enable verbose output
1913 #[arg(short, long)]
1914 verbose: bool,
1915 },
1916
1917 /// Create a new agent configuration
1918 Create {
1919 /// Agent name
1920 name: String,
1921
1922 /// Agent role (coordinator, researcher, coder, reviewer, executor, writer, tester, custom)
1923 #[arg(short, long, default_value = "custom")]
1924 role: String,
1925
1926 /// System instruction for the agent
1927 #[arg(short, long)]
1928 instruction: Option<String>,
1929
1930 /// Model to use
1931 #[arg(short, long)]
1932 model: Option<String>,
1933 },
1934
1935 /// List available tools
1936 Tools,
1937
1938 /// Show swarm templates
1939 Templates,
1940}
1941
1942// ============================================================================
1943// Telemetry Subcommands
1944// ============================================================================
1945
1946#[derive(Subcommand)]
1947pub enum TelemetryCommands {
1948 /// Show telemetry status and what data is collected
1949 #[command(visible_alias = "status")]
1950 Info,
1951
1952 /// Enable anonymous usage data collection (this is the default)
1953 #[command(visible_alias = "enable")]
1954 OptIn,
1955
1956 /// Disable anonymous usage data collection
1957 #[command(visible_alias = "disable")]
1958 OptOut,
1959
1960 /// Reset telemetry ID (generates new anonymous identifier)
1961 Reset,
1962
1963 /// Record structured data for later AI analysis
1964 #[command(visible_alias = "log")]
1965 Record {
1966 /// Event category (e.g., 'workflow', 'error', 'performance', 'usage')
1967 #[arg(short, long, default_value = "custom")]
1968 category: String,
1969
1970 /// Event name or type
1971 #[arg(short, long)]
1972 event: String,
1973
1974 /// JSON data payload (or use --kv for key=value pairs)
1975 #[arg(short, long)]
1976 data: Option<String>,
1977
1978 /// Key-value pairs (can be repeated: -k foo=bar -k baz=123)
1979 #[arg(short = 'k', long = "kv", value_parser = parse_key_value)]
1980 kv: Vec<(String, String)>,
1981
1982 /// Add tags for filtering (can be repeated: -t important -t session-123)
1983 #[arg(short, long)]
1984 tags: Vec<String>,
1985
1986 /// Optional session or context ID to associate with
1987 #[arg(long)]
1988 context: Option<String>,
1989
1990 /// Print recorded event details
1991 #[arg(short, long)]
1992 verbose: bool,
1993 },
1994
1995 /// Show recorded telemetry data
1996 #[command(visible_alias = "logs")]
1997 Show {
1998 /// Filter by category
1999 #[arg(short, long)]
2000 category: Option<String>,
2001
2002 /// Filter by event name
2003 #[arg(short, long)]
2004 event: Option<String>,
2005
2006 /// Filter by tag
2007 #[arg(short, long)]
2008 tag: Option<String>,
2009
2010 /// Maximum number of records to show
2011 #[arg(short = 'n', long, default_value = "20")]
2012 limit: usize,
2013
2014 /// Output format: table, json, jsonl
2015 #[arg(short, long, default_value = "table")]
2016 format: String,
2017
2018 /// Show records after this date (YYYY-MM-DD)
2019 #[arg(long)]
2020 after: Option<String>,
2021
2022 /// Show records before this date (YYYY-MM-DD)
2023 #[arg(long)]
2024 before: Option<String>,
2025 },
2026
2027 /// Export recorded data for AI analysis
2028 Export {
2029 /// Output file path
2030 output: String,
2031
2032 /// Export format: json, jsonl, csv
2033 #[arg(short, long, default_value = "jsonl")]
2034 format: String,
2035
2036 /// Filter by category
2037 #[arg(short, long)]
2038 category: Option<String>,
2039
2040 /// Include installation metadata in export
2041 #[arg(long)]
2042 with_metadata: bool,
2043 },
2044
2045 /// Clear recorded telemetry data
2046 Clear {
2047 /// Skip confirmation prompt
2048 #[arg(short, long)]
2049 force: bool,
2050
2051 /// Only clear records older than N days
2052 #[arg(long)]
2053 older_than: Option<u32>,
2054 },
2055
2056 /// Configure remote telemetry endpoint
2057 Config {
2058 /// Set the remote endpoint URL
2059 #[arg(long)]
2060 endpoint: Option<String>,
2061
2062 /// Set the API key for authentication
2063 #[arg(long)]
2064 api_key: Option<String>,
2065
2066 /// Enable remote telemetry sending
2067 #[arg(long)]
2068 enable_remote: bool,
2069
2070 /// Disable remote telemetry sending
2071 #[arg(long)]
2072 disable_remote: bool,
2073 },
2074
2075 /// Sync telemetry records to remote server
2076 Sync {
2077 /// Maximum number of records to sync
2078 #[arg(short = 'n', long)]
2079 limit: Option<usize>,
2080
2081 /// Clear local records after successful sync
2082 #[arg(long)]
2083 clear_after: bool,
2084 },
2085
2086 /// Test connection to remote telemetry server
2087 Test,
2088}
2089
2090/// Parse key=value pairs for telemetry record command
2091fn parse_key_value(s: &str) -> std::result::Result<(String, String), String> {
2092 let pos = s
2093 .find('=')
2094 .ok_or_else(|| format!("invalid key=value pair: no '=' found in '{s}'"))?;
2095 Ok((s[..pos].to_string(), s[pos + 1..].to_string()))
2096}
2097
2098// ============================================================================
2099// Shell Completion Enum
2100// ============================================================================
2101
2102/// Supported shells for completion generation
2103#[derive(Clone, Debug, clap::ValueEnum)]
2104pub enum CompletionShell {
2105 /// Bash shell
2106 Bash,
2107 /// Zsh shell
2108 Zsh,
2109 /// Fish shell
2110 Fish,
2111 /// PowerShell
2112 Powershell,
2113 /// Elvish shell
2114 Elvish,
2115}