chasm_cli/
cli.rs

1// Copyright (c) 2024-2026 Nervosys LLC
2// SPDX-License-Identifier: Apache-2.0
3//! CLI argument definitions using clap derive macros
4
5use clap::{Parser, Subcommand};
6
7/// Chat System Manager (csm) - Manage and merge chat sessions across workspaces
8#[derive(Parser)]
9#[command(name = "csm")]
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 (TUI)
115    // ============================================================================
116    /// Run interactive tools
117    Run {
118        #[command(subcommand)]
119        command: RunCommands,
120    },
121
122    // ============================================================================
123    // Provider Commands
124    // ============================================================================
125    /// Manage LLM providers (Ollama, vLLM, Foundry, Cursor, etc.)
126    Provider {
127        #[command(subcommand)]
128        command: ProviderCommands,
129    },
130
131    // ============================================================================
132    // Detect Commands
133    // ============================================================================
134    /// Auto-detect workspace and provider information
135    Detect {
136        #[command(subcommand)]
137        command: Option<DetectCommands>,
138    },
139
140    // ============================================================================
141    // Register Commands
142    // ============================================================================
143    /// Add on-disk sessions to VS Code's database index (makes orphaned sessions visible)
144    #[command(visible_alias = "sync")]
145    Register {
146        #[command(subcommand)]
147        command: RegisterCommands,
148    },
149
150    // ============================================================================
151    // Harvest Commands
152    // ============================================================================
153    /// Harvest chat sessions from all providers into a unified database
154    Harvest {
155        #[command(subcommand)]
156        command: HarvestCommands,
157    },
158
159    // ============================================================================
160    // API Server Commands
161    // ============================================================================
162    /// Start the HTTP API server for the web frontend
163    #[command(visible_alias = "serve")]
164    Api {
165        #[command(subcommand)]
166        command: ApiCommands,
167    },
168
169    // ============================================================================
170    // Agency Commands
171    // ============================================================================
172    /// Agent Development Kit - manage agents and orchestration
173    Agency {
174        #[command(subcommand)]
175        command: AgencyCommands,
176    },
177
178    // ============================================================================
179    // Easter Egg
180    // ============================================================================
181    /// Show banner
182    #[command(hide = true)]
183    Banner,
184}
185
186// ============================================================================
187// List Subcommands
188// ============================================================================
189
190#[derive(Subcommand)]
191pub enum ListCommands {
192    /// List all VS Code workspaces
193    #[command(visible_alias = "ws")]
194    Workspaces,
195
196    /// List all chat sessions
197    #[command(visible_alias = "s")]
198    Sessions {
199        /// Filter by project path
200        #[arg(long)]
201        project_path: Option<String>,
202    },
203
204    /// List sessions for a specific project path
205    Path {
206        /// Project path (default: current directory)
207        project_path: Option<String>,
208    },
209
210    /// List unregistered sessions (exist on disk but invisible to VS Code)
211    Orphaned {
212        /// Project path (default: current directory)
213        #[arg(long)]
214        path: Option<String>,
215    },
216
217    /// List available LLM providers and their status
218    #[command(visible_alias = "p")]
219    Providers {
220        /// Show providers with sessions only
221        #[arg(long)]
222        with_sessions: bool,
223    },
224
225    /// List available models from LLM providers
226    #[command(visible_alias = "m")]
227    Models {
228        /// Filter by provider name (e.g., "ollama", "lmstudio")
229        #[arg(long, short)]
230        provider: Option<String>,
231    },
232}
233
234// ============================================================================
235// Find Subcommands
236// ============================================================================
237
238#[derive(Subcommand)]
239pub enum FindCommands {
240    /// Search workspaces by name pattern (defaults to current directory name)
241    #[command(visible_alias = "ws")]
242    Workspace {
243        /// Text pattern to match (case-insensitive, defaults to current directory name)
244        pattern: Option<String>,
245    },
246
247    /// Search sessions by title, content, or ID pattern
248    #[command(visible_alias = "s")]
249    Session {
250        /// Text pattern to match (case-insensitive, defaults to current directory name)
251        pattern: Option<String>,
252
253        /// Filter by project path or workspace name
254        #[arg(long, short = 'w')]
255        workspace: Option<String>,
256
257        /// Only search in session titles (faster, skip content search)
258        #[arg(long, short = 't')]
259        title_only: bool,
260
261        /// Include message content in search (slower)
262        #[arg(long, short = 'c')]
263        content: bool,
264
265        /// Filter sessions modified after this date (YYYY-MM-DD)
266        #[arg(long)]
267        after: Option<String>,
268
269        /// Filter sessions modified before this date (YYYY-MM-DD)
270        #[arg(long)]
271        before: Option<String>,
272
273        /// Limit number of results
274        #[arg(long, short = 'n', default_value = "50")]
275        limit: usize,
276    },
277
278    /// Search sessions within a specific project path
279    Path {
280        /// Search pattern (case-insensitive, defaults to current directory name)
281        pattern: Option<String>,
282
283        /// Project path (default: current directory)
284        #[arg(long)]
285        project_path: Option<String>,
286    },
287}
288
289// ============================================================================
290// Show Subcommands
291// ============================================================================
292
293#[derive(Subcommand)]
294pub enum ShowCommands {
295    /// Show workspace details
296    #[command(visible_alias = "ws")]
297    Workspace {
298        /// Workspace name or hash
299        workspace: String,
300    },
301
302    /// Show session details
303    #[command(visible_alias = "s")]
304    Session {
305        /// Session ID or filename
306        session_id: String,
307
308        /// Project path to search in
309        #[arg(long)]
310        project_path: Option<String>,
311    },
312
313    /// Show chat history timeline for a project path
314    Path {
315        /// Path to the project (default: current directory)
316        project_path: Option<String>,
317    },
318}
319
320// ============================================================================
321// Fetch Subcommands
322// ============================================================================
323
324#[derive(Subcommand)]
325pub enum FetchCommands {
326    /// Fetch sessions from workspaces matching a pattern
327    #[command(visible_alias = "ws")]
328    Workspace {
329        /// Workspace name pattern (case-insensitive)
330        workspace_name: String,
331
332        /// Target project path (default: current directory)
333        #[arg(long)]
334        target_path: Option<String>,
335
336        /// Overwrite existing sessions
337        #[arg(long)]
338        force: bool,
339
340        /// Don't register sessions in VS Code index
341        #[arg(long)]
342        no_register: bool,
343    },
344
345    /// Fetch specific sessions by ID
346    #[command(visible_alias = "s")]
347    Session {
348        /// Session IDs to fetch (space-separated)
349        #[arg(required = true, num_args = 1..)]
350        session_ids: Vec<String>,
351
352        /// Target project path (default: current directory)
353        #[arg(long)]
354        target_path: Option<String>,
355
356        /// Overwrite existing sessions
357        #[arg(long)]
358        force: bool,
359
360        /// Don't register sessions in VS Code index
361        #[arg(long)]
362        no_register: bool,
363    },
364
365    /// Fetch chat sessions from other workspaces by project path
366    Path {
367        /// Path to the project (default: current directory)
368        project_path: Option<String>,
369
370        /// Overwrite existing sessions and skip VS Code running check
371        #[arg(long)]
372        force: bool,
373
374        /// Don't register sessions in VS Code index
375        #[arg(long)]
376        no_register: bool,
377    },
378}
379
380// ============================================================================
381// Merge Subcommands
382// ============================================================================
383
384#[derive(Subcommand)]
385pub enum MergeCommands {
386    /// Merge sessions from workspaces matching a name pattern
387    #[command(visible_alias = "ws")]
388    Workspace {
389        /// Workspace name pattern to search for (case-insensitive)
390        workspace_name: String,
391
392        /// Title for the merged session
393        #[arg(short, long)]
394        title: Option<String>,
395
396        /// Target project path to save the merged session (default: current directory)
397        #[arg(long)]
398        target_path: Option<String>,
399
400        /// Skip VS Code running check
401        #[arg(long)]
402        force: bool,
403
404        /// Don't create backup of current sessions
405        #[arg(long)]
406        no_backup: bool,
407    },
408
409    /// Merge sessions from multiple workspace name patterns
410    #[command(visible_alias = "wss")]
411    Workspaces {
412        /// Workspace name patterns to search for (space-separated, case-insensitive)
413        #[arg(required = true, num_args = 1..)]
414        workspace_names: Vec<String>,
415
416        /// Title for the merged session
417        #[arg(short, long)]
418        title: Option<String>,
419
420        /// Target project path to save the merged session (default: current directory)
421        #[arg(long)]
422        target_path: Option<String>,
423
424        /// Skip VS Code running check
425        #[arg(long)]
426        force: bool,
427
428        /// Don't create backup of current sessions
429        #[arg(long)]
430        no_backup: bool,
431    },
432
433    /// Merge specific sessions by their IDs or filenames
434    #[command(visible_alias = "s")]
435    Sessions {
436        /// Session IDs or filenames (comma-separated or space-separated)
437        #[arg(required = true, num_args = 1..)]
438        sessions: Vec<String>,
439
440        /// Title for the merged session
441        #[arg(short, long)]
442        title: Option<String>,
443
444        /// Target project path to save the merged session (default: current directory)
445        #[arg(long)]
446        target_path: Option<String>,
447
448        /// Skip VS Code running check
449        #[arg(long)]
450        force: bool,
451
452        /// Don't create backup of current sessions
453        #[arg(long)]
454        no_backup: bool,
455    },
456
457    /// Merge all sessions for a project path into one unified chat
458    Path {
459        /// Path to the project (default: current directory)
460        project_path: Option<String>,
461
462        /// Title for the merged session
463        #[arg(short, long)]
464        title: Option<String>,
465
466        /// Skip VS Code running check
467        #[arg(long)]
468        force: bool,
469
470        /// Don't create backup of current sessions
471        #[arg(long)]
472        no_backup: bool,
473    },
474
475    /// Merge sessions from an LLM provider (Ollama, Cursor, etc.)
476    Provider {
477        /// Provider name (copilot, cursor, ollama, vllm, foundry, etc.)
478        provider_name: String,
479
480        /// Title for the merged session
481        #[arg(short, long)]
482        title: Option<String>,
483
484        /// Target project path to save the merged session (default: current directory)
485        #[arg(long)]
486        target_path: Option<String>,
487
488        /// Session IDs from the provider to include (omit for all)
489        #[arg(long)]
490        sessions: Option<Vec<String>>,
491
492        /// Skip VS Code running check
493        #[arg(long)]
494        force: bool,
495
496        /// Don't create backup of current sessions
497        #[arg(long)]
498        no_backup: bool,
499    },
500
501    /// Merge sessions from multiple providers
502    #[command(name = "providers")]
503    Providers {
504        /// Provider names (space-separated: copilot cursor ollama)
505        #[arg(required = true, num_args = 1..)]
506        providers: Vec<String>,
507
508        /// Title for the merged session
509        #[arg(short, long)]
510        title: Option<String>,
511
512        /// Target project path to save the merged session (default: current directory)
513        #[arg(long)]
514        target_path: Option<String>,
515
516        /// Filter by workspace name pattern (applies to providers that support workspaces)
517        #[arg(long)]
518        workspace: Option<String>,
519
520        /// Skip VS Code running check
521        #[arg(long)]
522        force: bool,
523
524        /// Don't create backup of current sessions
525        #[arg(long)]
526        no_backup: bool,
527    },
528
529    /// Merge all sessions across all available providers
530    All {
531        /// Title for the merged session
532        #[arg(short, long)]
533        title: Option<String>,
534
535        /// Target project path to save the merged session (default: current directory)
536        #[arg(long)]
537        target_path: Option<String>,
538
539        /// Filter by workspace name pattern (applies to providers that support workspaces)
540        #[arg(long)]
541        workspace: Option<String>,
542
543        /// Skip VS Code running check
544        #[arg(long)]
545        force: bool,
546
547        /// Don't create backup of current sessions
548        #[arg(long)]
549        no_backup: bool,
550    },
551}
552
553// ============================================================================
554// Export Subcommands
555// ============================================================================
556
557#[derive(Subcommand)]
558pub enum ExportCommands {
559    /// Export sessions from a workspace by hash
560    #[command(visible_alias = "ws")]
561    Workspace {
562        /// Destination directory for exported sessions
563        destination: String,
564
565        /// Source workspace hash
566        hash: String,
567    },
568
569    /// Export specific sessions by ID
570    #[command(visible_alias = "s")]
571    Sessions {
572        /// Destination directory for exported sessions
573        destination: String,
574
575        /// Session IDs to export (space-separated)
576        #[arg(required = true, num_args = 1..)]
577        session_ids: Vec<String>,
578
579        /// Source project path
580        #[arg(long)]
581        project_path: Option<String>,
582    },
583
584    /// Export chat sessions from a project path
585    Path {
586        /// Destination directory for exported sessions
587        destination: String,
588
589        /// Source project path (default: current directory)
590        project_path: Option<String>,
591    },
592}
593
594// ============================================================================
595// Import Subcommands
596// ============================================================================
597
598#[derive(Subcommand)]
599pub enum ImportCommands {
600    /// Copy session files from external directory into a workspace
601    #[command(visible_alias = "ws")]
602    Workspace {
603        /// Source directory containing session JSON files to import
604        source: String,
605
606        /// Target workspace hash
607        hash: String,
608
609        /// Overwrite existing sessions
610        #[arg(long)]
611        force: bool,
612    },
613
614    /// Copy specific session files into a workspace
615    #[command(visible_alias = "s")]
616    Sessions {
617        /// Session files to import (space-separated paths)
618        #[arg(required = true, num_args = 1..)]
619        session_files: Vec<String>,
620
621        /// Target project path (default: current directory)
622        #[arg(long)]
623        target_path: Option<String>,
624
625        /// Overwrite existing sessions
626        #[arg(long)]
627        force: bool,
628    },
629
630    /// Copy session files from external directory into a project workspace
631    Path {
632        /// Source directory containing session JSON files to import
633        source: String,
634
635        /// Target project path (default: current directory)
636        target_path: Option<String>,
637
638        /// Overwrite existing sessions
639        #[arg(long)]
640        force: bool,
641    },
642}
643
644// ============================================================================
645// Move Subcommands
646// ============================================================================
647
648#[derive(Subcommand)]
649pub enum MoveCommands {
650    /// Move all sessions from one workspace to another
651    #[command(visible_alias = "ws")]
652    Workspace {
653        /// Source workspace hash
654        source_hash: String,
655
656        /// Target workspace hash or project path
657        target: String,
658    },
659
660    /// Move specific sessions by ID
661    #[command(visible_alias = "s")]
662    Sessions {
663        /// Session IDs to move (space-separated)
664        #[arg(required = true, num_args = 1..)]
665        session_ids: Vec<String>,
666
667        /// Target project path
668        target_path: String,
669    },
670
671    /// Move sessions from a source path to target path
672    Path {
673        /// Source project path
674        source_path: String,
675
676        /// Target project path
677        target_path: String,
678    },
679}
680
681// ============================================================================
682// Git Subcommands
683// ============================================================================
684
685#[derive(Subcommand)]
686pub enum GitCommands {
687    /// Configure git settings for chat sessions
688    Config {
689        /// Git user name
690        #[arg(long)]
691        name: Option<String>,
692
693        /// Git user email
694        #[arg(long)]
695        email: Option<String>,
696
697        /// Project path
698        #[arg(long)]
699        path: Option<String>,
700    },
701
702    /// Initialize git versioning for chat sessions
703    Init {
704        /// Project path
705        path: String,
706    },
707
708    /// Add chat sessions to git (stage and optionally commit)
709    Add {
710        /// Project path
711        path: String,
712
713        /// Also commit the changes
714        #[arg(long)]
715        commit: bool,
716
717        /// Commit message (requires --commit)
718        #[arg(short, long)]
719        message: Option<String>,
720    },
721
722    /// Show git status of chat sessions
723    Status {
724        /// Project path
725        path: String,
726    },
727
728    /// Create a git tag snapshot of chat sessions
729    Snapshot {
730        /// Project path
731        path: String,
732
733        /// Tag name (auto-generated if not provided)
734        #[arg(long)]
735        tag: Option<String>,
736
737        /// Snapshot message
738        #[arg(short, long)]
739        message: Option<String>,
740    },
741
742    /// Track chat sessions together with associated file changes
743    Track {
744        /// Project path
745        path: String,
746
747        /// Commit message describing the changes
748        #[arg(short, long)]
749        message: Option<String>,
750
751        /// Include all staged and unstaged file changes
752        #[arg(long)]
753        all: bool,
754
755        /// Include specific files in addition to chat sessions
756        #[arg(long)]
757        files: Option<Vec<String>>,
758
759        /// Create a tag for this tracked state
760        #[arg(long)]
761        tag: Option<String>,
762    },
763
764    /// Show history of chat session commits with associated file changes
765    Log {
766        /// Project path
767        path: String,
768
769        /// Number of commits to show
770        #[arg(short = 'n', long, default_value = "10")]
771        count: usize,
772
773        /// Show only commits that include chat session changes
774        #[arg(long)]
775        sessions_only: bool,
776    },
777
778    /// Diff chat sessions between commits or current state
779    Diff {
780        /// Project path
781        path: String,
782
783        /// First commit (default: HEAD)
784        #[arg(long)]
785        from: Option<String>,
786
787        /// Second commit (default: working directory)
788        #[arg(long)]
789        to: Option<String>,
790
791        /// Show associated file changes alongside chat diffs
792        #[arg(long)]
793        with_files: bool,
794    },
795
796    /// Restore chat sessions from a specific commit
797    Restore {
798        /// Project path
799        path: String,
800
801        /// Commit hash, tag, or reference to restore from
802        commit: String,
803
804        /// Also restore associated files from the same commit
805        #[arg(long)]
806        with_files: bool,
807
808        /// Create a backup before restoring
809        #[arg(long)]
810        backup: bool,
811    },
812}
813
814// ============================================================================
815// Migration Subcommands
816// ============================================================================
817
818#[derive(Subcommand)]
819pub enum MigrationCommands {
820    /// Create a migration package for moving to a new machine
821    Create {
822        /// Output directory for migration package
823        output: String,
824
825        /// Comma-separated list of project paths to include
826        #[arg(long)]
827        projects: Option<String>,
828
829        /// Include all workspaces with chat sessions
830        #[arg(long)]
831        all: bool,
832    },
833
834    /// Restore a migration package on a new machine
835    Restore {
836        /// Path to migration package directory
837        package: String,
838
839        /// Project path mapping: 'old1:new1;old2:new2'
840        #[arg(long)]
841        mapping: Option<String>,
842
843        /// Show what would be done without doing it
844        #[arg(long)]
845        dry_run: bool,
846    },
847}
848
849// ============================================================================
850// Run Subcommands
851// ============================================================================
852
853#[derive(Subcommand)]
854pub enum RunCommands {
855    /// Launch interactive TUI (Text User Interface)
856    Tui,
857}
858
859// ============================================================================
860// Provider Subcommands
861// ============================================================================
862
863#[derive(Subcommand)]
864pub enum ProviderCommands {
865    /// List all discovered LLM providers
866    List,
867
868    /// Show detailed info about a specific provider
869    Info {
870        /// Provider name (copilot, cursor, ollama, vllm, foundry, lm-studio, etc.)
871        provider: String,
872    },
873
874    /// Configure a provider
875    Config {
876        /// Provider name
877        provider: String,
878
879        /// API endpoint URL
880        #[arg(long)]
881        endpoint: Option<String>,
882
883        /// API key
884        #[arg(long)]
885        api_key: Option<String>,
886
887        /// Default model
888        #[arg(long)]
889        model: Option<String>,
890
891        /// Enable or disable the provider
892        #[arg(long)]
893        enabled: Option<bool>,
894    },
895
896    /// Import sessions from another provider
897    Import {
898        /// Source provider name
899        #[arg(long)]
900        from: String,
901
902        /// Target project path (or current directory)
903        #[arg(long)]
904        path: Option<String>,
905
906        /// Session ID to import (omit for all)
907        #[arg(long)]
908        session: Option<String>,
909    },
910
911    /// Test connection to a provider
912    Test {
913        /// Provider name
914        provider: String,
915    },
916}
917
918// ============================================================================
919// Detect Subcommands
920// ============================================================================
921
922#[derive(Subcommand)]
923pub enum DetectCommands {
924    /// Detect workspace for a path
925    Workspace {
926        /// Project path (default: current directory)
927        path: Option<String>,
928    },
929
930    /// Detect available providers
931    Providers {
932        /// Only show providers with sessions
933        #[arg(long)]
934        with_sessions: bool,
935    },
936
937    /// Detect which provider a session belongs to
938    Session {
939        /// Session ID or filename
940        session_id: String,
941
942        /// Project path to search in
943        #[arg(long)]
944        path: Option<String>,
945    },
946
947    /// Detect everything (workspace, providers, sessions) for a path
948    All {
949        /// Project path (default: current directory)
950        path: Option<String>,
951
952        /// Show detailed information
953        #[arg(long)]
954        verbose: bool,
955    },
956}
957
958// ============================================================================
959// Register Subcommands
960// ============================================================================
961
962#[derive(Subcommand)]
963pub enum RegisterCommands {
964    /// Register all on-disk sessions into VS Code's index (fixes orphaned sessions)
965    All {
966        /// Project path (default: current directory)
967        #[arg(long)]
968        path: Option<String>,
969
970        /// Merge all sessions into one before registering
971        #[arg(long, short)]
972        merge: bool,
973
974        /// Force registration even if VS Code is running
975        #[arg(long, short)]
976        force: bool,
977    },
978
979    /// Register specific sessions by ID or title into VS Code's index
980    #[command(visible_alias = "s")]
981    Session {
982        /// Session IDs or filenames (without .json extension)
983        #[arg(required_unless_present = "title")]
984        ids: Vec<String>,
985
986        /// Match sessions by title instead of ID
987        #[arg(long, short, num_args = 1.., value_delimiter = ' ')]
988        title: Option<Vec<String>>,
989
990        /// Project path (default: current directory)
991        #[arg(long)]
992        path: Option<String>,
993
994        /// Force registration even if VS Code is running
995        #[arg(long, short)]
996        force: bool,
997    },
998}
999
1000// ============================================================================
1001// Harvest Subcommands
1002// ============================================================================
1003
1004#[derive(Subcommand)]
1005pub enum HarvestCommands {
1006    /// Initialize a harvest database
1007    Init {
1008        /// Path to the database file (default: ./chat_sessions.db)
1009        #[arg(long)]
1010        path: Option<String>,
1011
1012        /// Initialize git tracking for the database
1013        #[arg(long)]
1014        git: bool,
1015    },
1016
1017    /// Scan for available providers and sessions
1018    Scan {
1019        /// Show individual sessions
1020        #[arg(long)]
1021        sessions: bool,
1022
1023        /// Scan for web-based LLM providers (ChatGPT, Claude, etc.)
1024        #[arg(long)]
1025        web: bool,
1026
1027        /// Timeout in seconds for web provider checks (default: 5)
1028        #[arg(long, default_value = "5")]
1029        timeout: u64,
1030
1031        /// Show verbose debug output for browser scanning
1032        #[arg(long, short)]
1033        verbose: bool,
1034    },
1035
1036    /// Run the harvest to collect sessions from all providers
1037    Run {
1038        /// Path to the harvest database
1039        #[arg(long)]
1040        path: Option<String>,
1041
1042        /// Only include specific providers (comma-separated: copilot,cursor,ollama)
1043        #[arg(long, value_delimiter = ',')]
1044        providers: Option<Vec<String>>,
1045
1046        /// Exclude specific providers (comma-separated)
1047        #[arg(long, value_delimiter = ',')]
1048        exclude: Option<Vec<String>>,
1049
1050        /// Only harvest sessions changed since last run
1051        #[arg(long)]
1052        incremental: bool,
1053
1054        /// Auto-commit changes to git after harvest
1055        #[arg(long)]
1056        commit: bool,
1057
1058        /// Commit message (requires --commit)
1059        #[arg(short, long)]
1060        message: Option<String>,
1061    },
1062
1063    /// Show harvest database status
1064    Status {
1065        /// Path to the harvest database
1066        #[arg(long)]
1067        path: Option<String>,
1068    },
1069
1070    /// List sessions in the harvest database
1071    List {
1072        /// Path to the harvest database
1073        #[arg(long)]
1074        path: Option<String>,
1075
1076        /// Filter by provider name
1077        #[arg(long)]
1078        provider: Option<String>,
1079
1080        /// Maximum number of sessions to show
1081        #[arg(long, default_value = "20")]
1082        limit: usize,
1083
1084        /// Search sessions by title or ID
1085        #[arg(long)]
1086        search: Option<String>,
1087    },
1088
1089    /// Export sessions from the harvest database
1090    Export {
1091        /// Output file path
1092        output: String,
1093
1094        /// Path to the harvest database
1095        #[arg(long)]
1096        path: Option<String>,
1097
1098        /// Export format: json, jsonl, md (markdown)
1099        #[arg(long, default_value = "json")]
1100        format: String,
1101
1102        /// Filter by provider name
1103        #[arg(long)]
1104        provider: Option<String>,
1105
1106        /// Export specific sessions by ID (comma-separated)
1107        #[arg(long, value_delimiter = ',')]
1108        sessions: Option<Vec<String>>,
1109    },
1110
1111    /// Import a shared chat session from a URL
1112    Share {
1113        /// Share link URL (ChatGPT, Claude, etc.)
1114        url: String,
1115
1116        /// Path to the harvest database
1117        #[arg(long)]
1118        path: Option<String>,
1119
1120        /// Custom name for the imported session
1121        #[arg(long)]
1122        name: Option<String>,
1123
1124        /// Associate with a workspace path
1125        #[arg(long)]
1126        workspace: Option<String>,
1127    },
1128
1129    /// List pending or imported share links
1130    Shares {
1131        /// Path to the harvest database
1132        #[arg(long)]
1133        path: Option<String>,
1134
1135        /// Filter by status: pending, imported, failed, expired
1136        #[arg(long)]
1137        status: Option<String>,
1138
1139        /// Maximum number of links to show
1140        #[arg(long, default_value = "20")]
1141        limit: usize,
1142    },
1143
1144    /// Create a checkpoint (version snapshot) of a session
1145    Checkpoint {
1146        /// Session ID to checkpoint
1147        session: String,
1148
1149        /// Path to the harvest database
1150        #[arg(long)]
1151        path: Option<String>,
1152
1153        /// Checkpoint description message
1154        #[arg(short, long)]
1155        message: Option<String>,
1156    },
1157
1158    /// List checkpoints for a session
1159    Checkpoints {
1160        /// Session ID to list checkpoints for
1161        session: String,
1162
1163        /// Path to the harvest database
1164        #[arg(long)]
1165        path: Option<String>,
1166    },
1167
1168    /// Restore a session to a previous checkpoint
1169    Restore {
1170        /// Session ID to restore
1171        session: String,
1172
1173        /// Checkpoint number to restore to
1174        checkpoint: i64,
1175
1176        /// Path to the harvest database
1177        #[arg(long)]
1178        path: Option<String>,
1179    },
1180
1181    /// Rebuild the full-text search index
1182    Rebuild {
1183        /// Path to the harvest database
1184        #[arg(long)]
1185        path: Option<String>,
1186    },
1187
1188    /// Search messages across all sessions (full-text search)
1189    Search {
1190        /// Search query
1191        query: String,
1192
1193        /// Path to the harvest database
1194        #[arg(long)]
1195        path: Option<String>,
1196
1197        /// Filter by provider
1198        #[arg(long)]
1199        provider: Option<String>,
1200
1201        /// Maximum results to show
1202        #[arg(long, default_value = "20")]
1203        limit: usize,
1204    },
1205
1206    /// Git operations for the harvest database
1207    Git {
1208        #[command(subcommand)]
1209        command: HarvestGitCommands,
1210    },
1211}
1212
1213#[derive(Subcommand)]
1214pub enum HarvestGitCommands {
1215    /// Initialize git tracking for the harvest database
1216    Init {
1217        /// Path to the harvest database
1218        #[arg(long)]
1219        path: Option<String>,
1220    },
1221
1222    /// Commit changes to the harvest database
1223    Commit {
1224        /// Path to the harvest database
1225        #[arg(long)]
1226        path: Option<String>,
1227
1228        /// Commit message
1229        #[arg(short, long)]
1230        message: Option<String>,
1231    },
1232
1233    /// Show git log for the harvest database
1234    Log {
1235        /// Path to the harvest database
1236        #[arg(long)]
1237        path: Option<String>,
1238
1239        /// Number of commits to show
1240        #[arg(short = 'n', long, default_value = "10")]
1241        count: usize,
1242    },
1243
1244    /// Show changes to the harvest database
1245    Diff {
1246        /// Path to the harvest database
1247        #[arg(long)]
1248        path: Option<String>,
1249
1250        /// Compare against specific commit
1251        #[arg(long)]
1252        commit: Option<String>,
1253    },
1254
1255    /// Restore harvest database from a commit
1256    Restore {
1257        /// Commit hash to restore from
1258        commit: String,
1259
1260        /// Path to the harvest database
1261        #[arg(long)]
1262        path: Option<String>,
1263    },
1264}
1265
1266// ============================================================================
1267// API Server Subcommands
1268// ============================================================================
1269
1270#[derive(Subcommand)]
1271pub enum ApiCommands {
1272    /// Start the API server
1273    Serve {
1274        /// Host to bind to (default: 0.0.0.0 for all interfaces)
1275        #[arg(long, default_value = "0.0.0.0")]
1276        host: String,
1277
1278        /// Port to listen on (default: 8787)
1279        #[arg(short, long, default_value = "8787")]
1280        port: u16,
1281
1282        /// Path to the database file
1283        #[arg(long)]
1284        database: Option<String>,
1285    },
1286}
1287
1288// ============================================================================
1289// Agency (Agent Development Kit) Subcommands
1290// ============================================================================
1291
1292#[derive(Subcommand)]
1293pub enum AgencyCommands {
1294    /// List available agents and their roles
1295    List {
1296        /// Show detailed information
1297        #[arg(short, long)]
1298        verbose: bool,
1299    },
1300
1301    /// Show agent information
1302    Info {
1303        /// Agent name or ID
1304        name: String,
1305    },
1306
1307    /// List supported orchestration modes
1308    Modes,
1309
1310    /// Run an agent with a prompt
1311    Run {
1312        /// Agent name to run
1313        #[arg(short, long, default_value = "assistant")]
1314        agent: String,
1315
1316        /// Prompt or task for the agent
1317        prompt: String,
1318
1319        /// Model to use (e.g., gemini-2.0-flash, gpt-4o)
1320        #[arg(short, long)]
1321        model: Option<String>,
1322
1323        /// Orchestration mode (single, sequential, parallel, swarm)
1324        #[arg(long, default_value = "single")]
1325        orchestration: String,
1326
1327        /// Enable verbose output
1328        #[arg(short, long)]
1329        verbose: bool,
1330    },
1331
1332    /// Create a new agent configuration
1333    Create {
1334        /// Agent name
1335        name: String,
1336
1337        /// Agent role (coordinator, researcher, coder, reviewer, executor, writer, tester, custom)
1338        #[arg(short, long, default_value = "custom")]
1339        role: String,
1340
1341        /// System instruction for the agent
1342        #[arg(short, long)]
1343        instruction: Option<String>,
1344
1345        /// Model to use
1346        #[arg(short, long)]
1347        model: Option<String>,
1348    },
1349
1350    /// List available tools
1351    Tools,
1352
1353    /// Show swarm templates
1354    Templates,
1355}