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 /// Trim oversized sessions by keeping only the most recent requests
1364 #[command(visible_alias = "t")]
1365 Trim {
1366 /// Project path (default: current directory)
1367 #[arg(long)]
1368 path: Option<String>,
1369
1370 /// Number of recent requests to keep (default: 20)
1371 #[arg(long, short, default_value = "20")]
1372 keep: usize,
1373
1374 /// Session ID to trim (default: largest session)
1375 #[arg(long, short)]
1376 session: Option<String>,
1377
1378 /// Trim all sessions over the size threshold
1379 #[arg(long, short)]
1380 all: bool,
1381
1382 /// Only trim sessions larger than this size in MB (default: 10)
1383 #[arg(long, default_value = "10")]
1384 threshold_mb: u64,
1385
1386 /// Force even if VS Code is running
1387 #[arg(long, short)]
1388 force: bool,
1389 },
1390}
1391
1392// ============================================================================
1393// Harvest Subcommands
1394// ============================================================================
1395
1396#[derive(Subcommand)]
1397pub enum HarvestCommands {
1398 /// Initialize a harvest database
1399 Init {
1400 /// Path to the database file (default: ./chat_sessions.db)
1401 #[arg(long)]
1402 path: Option<String>,
1403
1404 /// Initialize git tracking for the database
1405 #[arg(long)]
1406 git: bool,
1407 },
1408
1409 /// Scan for available providers and sessions
1410 Scan {
1411 /// Show individual sessions
1412 #[arg(long)]
1413 sessions: bool,
1414
1415 /// Scan for web-based LLM providers (ChatGPT, Claude, etc.)
1416 #[arg(long)]
1417 web: bool,
1418
1419 /// Timeout in seconds for web provider checks (default: 5)
1420 #[arg(long, default_value = "5")]
1421 timeout: u64,
1422
1423 /// Show verbose debug output for browser scanning
1424 #[arg(long, short)]
1425 verbose: bool,
1426 },
1427
1428 /// Run the harvest to collect sessions from all providers
1429 Run {
1430 /// Path to the harvest database
1431 #[arg(long)]
1432 path: Option<String>,
1433
1434 /// Only include specific providers (comma-separated: copilot,cursor,ollama)
1435 #[arg(long, value_delimiter = ',')]
1436 providers: Option<Vec<String>>,
1437
1438 /// Exclude specific providers (comma-separated)
1439 #[arg(long, value_delimiter = ',')]
1440 exclude: Option<Vec<String>>,
1441
1442 /// Only harvest sessions changed since last run
1443 #[arg(long)]
1444 incremental: bool,
1445
1446 /// Auto-commit changes to git after harvest
1447 #[arg(long)]
1448 commit: bool,
1449
1450 /// Commit message (requires --commit)
1451 #[arg(short, long)]
1452 message: Option<String>,
1453 },
1454
1455 /// Show harvest database status
1456 Status {
1457 /// Path to the harvest database
1458 #[arg(long)]
1459 path: Option<String>,
1460 },
1461
1462 /// List sessions in the harvest database
1463 List {
1464 /// Path to the harvest database
1465 #[arg(long)]
1466 path: Option<String>,
1467
1468 /// Filter by provider name
1469 #[arg(long)]
1470 provider: Option<String>,
1471
1472 /// Maximum number of sessions to show
1473 #[arg(long, default_value = "20")]
1474 limit: usize,
1475
1476 /// Search sessions by title or ID
1477 #[arg(long)]
1478 search: Option<String>,
1479 },
1480
1481 /// Export sessions from the harvest database
1482 Export {
1483 /// Output file path
1484 output: String,
1485
1486 /// Path to the harvest database
1487 #[arg(long)]
1488 path: Option<String>,
1489
1490 /// Export format: json, jsonl, md (markdown)
1491 #[arg(long, default_value = "json")]
1492 format: String,
1493
1494 /// Filter by provider name
1495 #[arg(long)]
1496 provider: Option<String>,
1497
1498 /// Export specific sessions by ID (comma-separated)
1499 #[arg(long, value_delimiter = ',')]
1500 sessions: Option<Vec<String>>,
1501 },
1502
1503 /// Import a shared chat session from a URL
1504 Share {
1505 /// Share link URL (ChatGPT, Claude, etc.)
1506 url: String,
1507
1508 /// Path to the harvest database
1509 #[arg(long)]
1510 path: Option<String>,
1511
1512 /// Custom name for the imported session
1513 #[arg(long)]
1514 name: Option<String>,
1515
1516 /// Associate with a workspace path
1517 #[arg(long)]
1518 workspace: Option<String>,
1519 },
1520
1521 /// List pending or imported share links
1522 Shares {
1523 /// Path to the harvest database
1524 #[arg(long)]
1525 path: Option<String>,
1526
1527 /// Filter by status: pending, imported, failed, expired
1528 #[arg(long)]
1529 status: Option<String>,
1530
1531 /// Maximum number of links to show
1532 #[arg(long, default_value = "20")]
1533 limit: usize,
1534 },
1535
1536 /// Create a checkpoint (version snapshot) of a session
1537 Checkpoint {
1538 /// Session ID to checkpoint
1539 session: String,
1540
1541 /// Path to the harvest database
1542 #[arg(long)]
1543 path: Option<String>,
1544
1545 /// Checkpoint description message
1546 #[arg(short, long)]
1547 message: Option<String>,
1548 },
1549
1550 /// List checkpoints for a session
1551 Checkpoints {
1552 /// Session ID to list checkpoints for
1553 session: String,
1554
1555 /// Path to the harvest database
1556 #[arg(long)]
1557 path: Option<String>,
1558 },
1559
1560 /// Revert a session to a previous checkpoint
1561 Revert {
1562 /// Session ID to revert
1563 session: String,
1564
1565 /// Checkpoint number to revert to
1566 checkpoint: i64,
1567
1568 /// Path to the harvest database
1569 #[arg(long)]
1570 path: Option<String>,
1571 },
1572
1573 /// Sync sessions between the harvest database and provider workspaces
1574 Sync {
1575 /// Path to the harvest database
1576 #[arg(long)]
1577 path: Option<String>,
1578
1579 /// Push sessions from database to provider workspaces (restore)
1580 #[arg(long)]
1581 push: bool,
1582
1583 /// Pull sessions from provider workspaces into database (backup)
1584 #[arg(long)]
1585 pull: bool,
1586
1587 /// Filter by provider name
1588 #[arg(long)]
1589 provider: Option<String>,
1590
1591 /// Filter by workspace/project path
1592 #[arg(long)]
1593 workspace: Option<String>,
1594
1595 /// Session IDs to sync (space-separated)
1596 #[arg(long, num_args = 1..)]
1597 sessions: Option<Vec<String>>,
1598
1599 /// Target format for push: auto (detect from provider), jsonl, json
1600 #[arg(long, default_value = "auto")]
1601 format: String,
1602
1603 /// Overwrite existing files without prompting
1604 #[arg(long)]
1605 force: bool,
1606
1607 /// Dry run - show what would be synced without making changes
1608 #[arg(long)]
1609 dry_run: bool,
1610 },
1611
1612 /// Rebuild the full-text search index
1613 Rebuild {
1614 /// Path to the harvest database
1615 #[arg(long)]
1616 path: Option<String>,
1617 },
1618
1619 /// Search messages across all sessions (full-text search)
1620 Search {
1621 /// Search query
1622 query: String,
1623
1624 /// Path to the harvest database
1625 #[arg(long)]
1626 path: Option<String>,
1627
1628 /// Filter by provider
1629 #[arg(long)]
1630 provider: Option<String>,
1631
1632 /// Maximum results to show
1633 #[arg(long, default_value = "20")]
1634 limit: usize,
1635 },
1636
1637 /// Git operations for the harvest database
1638 Git {
1639 #[command(subcommand)]
1640 command: HarvestGitCommands,
1641 },
1642}
1643
1644#[derive(Subcommand)]
1645pub enum HarvestGitCommands {
1646 /// Initialize git tracking for the harvest database
1647 Init {
1648 /// Path to the harvest database
1649 #[arg(long)]
1650 path: Option<String>,
1651 },
1652
1653 /// Commit changes to the harvest database
1654 Commit {
1655 /// Path to the harvest database
1656 #[arg(long)]
1657 path: Option<String>,
1658
1659 /// Commit message
1660 #[arg(short, long)]
1661 message: Option<String>,
1662 },
1663
1664 /// Show git log for the harvest database
1665 Log {
1666 /// Path to the harvest database
1667 #[arg(long)]
1668 path: Option<String>,
1669
1670 /// Number of commits to show
1671 #[arg(short = 'n', long, default_value = "10")]
1672 count: usize,
1673 },
1674
1675 /// Show changes to the harvest database
1676 Diff {
1677 /// Path to the harvest database
1678 #[arg(long)]
1679 path: Option<String>,
1680
1681 /// Compare against specific commit
1682 #[arg(long)]
1683 commit: Option<String>,
1684 },
1685
1686 /// Restore harvest database from a commit
1687 Restore {
1688 /// Commit hash to restore from
1689 commit: String,
1690
1691 /// Path to the harvest database
1692 #[arg(long)]
1693 path: Option<String>,
1694 },
1695}
1696
1697// ============================================================================
1698// Recover Subcommands
1699// ============================================================================
1700
1701#[derive(Subcommand)]
1702pub enum RecoverCommands {
1703 /// Scan for recoverable sessions from various sources
1704 Scan {
1705 /// Provider to scan: vscode, cursor, all (default: all)
1706 #[arg(long, default_value = "all")]
1707 provider: String,
1708
1709 /// Show detailed information about each session
1710 #[arg(short, long)]
1711 verbose: bool,
1712
1713 /// Include sessions older than normal retention period
1714 #[arg(long)]
1715 include_old: bool,
1716 },
1717
1718 /// Recover sessions from the recording API server
1719 Recording {
1720 /// Server URL (default: http://localhost:8787)
1721 #[arg(long, default_value = "http://localhost:8787")]
1722 server: String,
1723
1724 /// Only recover specific session ID
1725 #[arg(long)]
1726 session: Option<String>,
1727
1728 /// Output directory for recovered sessions
1729 #[arg(short, long)]
1730 output: Option<String>,
1731 },
1732
1733 /// Recover sessions from SQLite database backups
1734 Database {
1735 /// Path to the database backup file
1736 backup: String,
1737
1738 /// Extract specific session by ID
1739 #[arg(long)]
1740 session: Option<String>,
1741
1742 /// Output directory for recovered sessions
1743 #[arg(short, long)]
1744 output: Option<String>,
1745
1746 /// Output format: json, jsonl, md (default: json)
1747 #[arg(long, default_value = "json")]
1748 format: String,
1749 },
1750
1751 /// Recover sessions from incomplete/corrupted JSONL files
1752 Jsonl {
1753 /// Path to the JSONL file to repair
1754 file: String,
1755
1756 /// Output file for recovered sessions (default: same name with .recovered suffix)
1757 #[arg(short, long)]
1758 output: Option<String>,
1759
1760 /// Attempt aggressive recovery (may produce incomplete sessions)
1761 #[arg(long)]
1762 aggressive: bool,
1763 },
1764
1765 /// List sessions from VS Code's workspaceStorage that may be orphaned
1766 Orphans {
1767 /// Provider to check: vscode, cursor, all (default: all)
1768 #[arg(long, default_value = "all")]
1769 provider: String,
1770
1771 /// Show sessions not in the SQLite state database
1772 #[arg(long)]
1773 unindexed: bool,
1774
1775 /// Check if files actually exist on disk
1776 #[arg(long)]
1777 verify: bool,
1778 },
1779
1780 /// Repair corrupted session files in place
1781 Repair {
1782 /// Path to the session directory or file
1783 path: String,
1784
1785 /// Create backup before repair
1786 #[arg(long, default_value = "true")]
1787 backup: bool,
1788
1789 /// Dry run - show what would be repaired without making changes
1790 #[arg(long)]
1791 dry_run: bool,
1792 },
1793
1794 /// Show recovery status and recommendations
1795 Status {
1796 /// Provider to check: vscode, cursor, all (default: all)
1797 #[arg(long, default_value = "all")]
1798 provider: String,
1799
1800 /// Check disk space and file system health
1801 #[arg(long)]
1802 system: bool,
1803 },
1804
1805 /// Convert session files between JSON and JSONL formats
1806 Convert {
1807 /// Input file to convert (.json or .jsonl)
1808 input: String,
1809
1810 /// Output file (auto-detects format from extension, or uses --format)
1811 #[arg(short, long)]
1812 output: Option<String>,
1813
1814 /// Output format: json, jsonl (default: opposite of input)
1815 #[arg(long)]
1816 format: Option<String>,
1817
1818 /// VS Code version compatibility: legacy (< 1.109), modern (>= 1.109), both
1819 #[arg(long, default_value = "both")]
1820 compat: String,
1821 },
1822
1823 /// Extract sessions from a VS Code workspace by project path
1824 Extract {
1825 /// Project directory path (will find corresponding workspace hash)
1826 path: String,
1827
1828 /// Output directory for extracted sessions
1829 #[arg(short, long)]
1830 output: Option<String>,
1831
1832 /// Include both JSON and JSONL formats if available
1833 #[arg(long)]
1834 all_formats: bool,
1835
1836 /// Include editing session fragments (agent mode work)
1837 #[arg(long)]
1838 include_edits: bool,
1839 },
1840
1841 /// Detect and display session format and version information
1842 Detect {
1843 /// Session file to analyze (.json or .jsonl)
1844 file: String,
1845
1846 /// Show raw format detection details
1847 #[arg(long)]
1848 verbose: bool,
1849
1850 /// Output detection result as JSON
1851 #[arg(long)]
1852 json: bool,
1853 },
1854
1855 /// Upgrade session files to the current provider format (JSON to JSONL for VS Code 1.109+)
1856 Upgrade {
1857 /// Project paths to upgrade (space-separated)
1858 #[arg(required = true, num_args = 1..)]
1859 project_paths: Vec<String>,
1860
1861 /// Provider to use: vscode, cursor, auto (default: auto-detect)
1862 #[arg(long, default_value = "auto")]
1863 provider: String,
1864
1865 /// Target format: jsonl (VS Code 1.109+), json (legacy). Default: jsonl
1866 #[arg(long, default_value = "jsonl")]
1867 target_format: String,
1868
1869 /// Skip creating backup of original files
1870 #[arg(long)]
1871 no_backup: bool,
1872
1873 /// Dry run - show what would be upgraded without making changes
1874 #[arg(long)]
1875 dry_run: bool,
1876 },
1877}
1878
1879// ============================================================================
1880// API Server Subcommands
1881// ============================================================================
1882
1883#[derive(Subcommand)]
1884pub enum ApiCommands {
1885 /// Start the API server
1886 Serve {
1887 /// Host to bind to (default: 0.0.0.0 for all interfaces)
1888 #[arg(long, default_value = "0.0.0.0")]
1889 host: String,
1890
1891 /// Port to listen on (default: 8787)
1892 #[arg(short, long, default_value = "8787")]
1893 port: u16,
1894
1895 /// Path to the database file
1896 #[arg(long)]
1897 database: Option<String>,
1898 },
1899}
1900
1901// ============================================================================
1902// Agency (Agent Development Kit) Subcommands
1903// ============================================================================
1904
1905#[derive(Subcommand)]
1906pub enum AgencyCommands {
1907 /// List available agents and their roles
1908 List {
1909 /// Show detailed information
1910 #[arg(short, long)]
1911 verbose: bool,
1912 },
1913
1914 /// Show agent information
1915 Info {
1916 /// Agent name or ID
1917 name: String,
1918 },
1919
1920 /// List supported orchestration modes
1921 Modes,
1922
1923 /// Run an agent with a prompt
1924 Run {
1925 /// Agent name to run
1926 #[arg(short, long, default_value = "assistant")]
1927 agent: String,
1928
1929 /// Prompt or task for the agent
1930 prompt: String,
1931
1932 /// Model to use (e.g., gemini-2.0-flash, gpt-4o)
1933 #[arg(short, long)]
1934 model: Option<String>,
1935
1936 /// Orchestration mode (single, sequential, parallel, swarm)
1937 #[arg(long, default_value = "single")]
1938 orchestration: String,
1939
1940 /// Enable verbose output
1941 #[arg(short, long)]
1942 verbose: bool,
1943 },
1944
1945 /// Create a new agent configuration
1946 Create {
1947 /// Agent name
1948 name: String,
1949
1950 /// Agent role (coordinator, researcher, coder, reviewer, executor, writer, tester, custom)
1951 #[arg(short, long, default_value = "custom")]
1952 role: String,
1953
1954 /// System instruction for the agent
1955 #[arg(short, long)]
1956 instruction: Option<String>,
1957
1958 /// Model to use
1959 #[arg(short, long)]
1960 model: Option<String>,
1961 },
1962
1963 /// List available tools
1964 Tools,
1965
1966 /// Show swarm templates
1967 Templates,
1968}
1969
1970// ============================================================================
1971// Telemetry Subcommands
1972// ============================================================================
1973
1974#[derive(Subcommand)]
1975pub enum TelemetryCommands {
1976 /// Show telemetry status and what data is collected
1977 #[command(visible_alias = "status")]
1978 Info,
1979
1980 /// Enable anonymous usage data collection (this is the default)
1981 #[command(visible_alias = "enable")]
1982 OptIn,
1983
1984 /// Disable anonymous usage data collection
1985 #[command(visible_alias = "disable")]
1986 OptOut,
1987
1988 /// Reset telemetry ID (generates new anonymous identifier)
1989 Reset,
1990
1991 /// Record structured data for later AI analysis
1992 #[command(visible_alias = "log")]
1993 Record {
1994 /// Event category (e.g., 'workflow', 'error', 'performance', 'usage')
1995 #[arg(short, long, default_value = "custom")]
1996 category: String,
1997
1998 /// Event name or type
1999 #[arg(short, long)]
2000 event: String,
2001
2002 /// JSON data payload (or use --kv for key=value pairs)
2003 #[arg(short, long)]
2004 data: Option<String>,
2005
2006 /// Key-value pairs (can be repeated: -k foo=bar -k baz=123)
2007 #[arg(short = 'k', long = "kv", value_parser = parse_key_value)]
2008 kv: Vec<(String, String)>,
2009
2010 /// Add tags for filtering (can be repeated: -t important -t session-123)
2011 #[arg(short, long)]
2012 tags: Vec<String>,
2013
2014 /// Optional session or context ID to associate with
2015 #[arg(long)]
2016 context: Option<String>,
2017
2018 /// Print recorded event details
2019 #[arg(short, long)]
2020 verbose: bool,
2021 },
2022
2023 /// Show recorded telemetry data
2024 #[command(visible_alias = "logs")]
2025 Show {
2026 /// Filter by category
2027 #[arg(short, long)]
2028 category: Option<String>,
2029
2030 /// Filter by event name
2031 #[arg(short, long)]
2032 event: Option<String>,
2033
2034 /// Filter by tag
2035 #[arg(short, long)]
2036 tag: Option<String>,
2037
2038 /// Maximum number of records to show
2039 #[arg(short = 'n', long, default_value = "20")]
2040 limit: usize,
2041
2042 /// Output format: table, json, jsonl
2043 #[arg(short, long, default_value = "table")]
2044 format: String,
2045
2046 /// Show records after this date (YYYY-MM-DD)
2047 #[arg(long)]
2048 after: Option<String>,
2049
2050 /// Show records before this date (YYYY-MM-DD)
2051 #[arg(long)]
2052 before: Option<String>,
2053 },
2054
2055 /// Export recorded data for AI analysis
2056 Export {
2057 /// Output file path
2058 output: String,
2059
2060 /// Export format: json, jsonl, csv
2061 #[arg(short, long, default_value = "jsonl")]
2062 format: String,
2063
2064 /// Filter by category
2065 #[arg(short, long)]
2066 category: Option<String>,
2067
2068 /// Include installation metadata in export
2069 #[arg(long)]
2070 with_metadata: bool,
2071 },
2072
2073 /// Clear recorded telemetry data
2074 Clear {
2075 /// Skip confirmation prompt
2076 #[arg(short, long)]
2077 force: bool,
2078
2079 /// Only clear records older than N days
2080 #[arg(long)]
2081 older_than: Option<u32>,
2082 },
2083
2084 /// Configure remote telemetry endpoint
2085 Config {
2086 /// Set the remote endpoint URL
2087 #[arg(long)]
2088 endpoint: Option<String>,
2089
2090 /// Set the API key for authentication
2091 #[arg(long)]
2092 api_key: Option<String>,
2093
2094 /// Enable remote telemetry sending
2095 #[arg(long)]
2096 enable_remote: bool,
2097
2098 /// Disable remote telemetry sending
2099 #[arg(long)]
2100 disable_remote: bool,
2101 },
2102
2103 /// Sync telemetry records to remote server
2104 Sync {
2105 /// Maximum number of records to sync
2106 #[arg(short = 'n', long)]
2107 limit: Option<usize>,
2108
2109 /// Clear local records after successful sync
2110 #[arg(long)]
2111 clear_after: bool,
2112 },
2113
2114 /// Test connection to remote telemetry server
2115 Test,
2116}
2117
2118/// Parse key=value pairs for telemetry record command
2119fn parse_key_value(s: &str) -> std::result::Result<(String, String), String> {
2120 let pos = s
2121 .find('=')
2122 .ok_or_else(|| format!("invalid key=value pair: no '=' found in '{s}'"))?;
2123 Ok((s[..pos].to_string(), s[pos + 1..].to_string()))
2124}
2125
2126// ============================================================================
2127// Shell Completion Enum
2128// ============================================================================
2129
2130/// Supported shells for completion generation
2131#[derive(Clone, Debug, clap::ValueEnum)]
2132pub enum CompletionShell {
2133 /// Bash shell
2134 Bash,
2135 /// Zsh shell
2136 Zsh,
2137 /// Fish shell
2138 Fish,
2139 /// PowerShell
2140 Powershell,
2141 /// Elvish shell
2142 Elvish,
2143}