sc/cli/mod.rs
1//! CLI definitions using clap.
2
3use clap::{Args, Parser, Subcommand, ValueEnum};
4use std::path::PathBuf;
5
6/// Output format for list/query commands.
7#[derive(ValueEnum, Clone, Debug, Default, PartialEq, Eq)]
8pub enum OutputFormat {
9 /// Human-readable table (default)
10 #[default]
11 Table,
12 /// JSON (same as --json)
13 Json,
14 /// Comma-separated values
15 Csv,
16}
17
18pub mod commands;
19
20/// SaveContext CLI - The OS for AI coding agents
21#[derive(Parser, Debug)]
22#[command(name = "sc", author, version, about, long_about = None)]
23pub struct Cli {
24 #[command(subcommand)]
25 pub command: Commands,
26
27 /// Database path (default: ~/.savecontext/data/savecontext.db)
28 #[arg(long, global = true, env = "SC_DB")]
29 pub db: Option<PathBuf>,
30
31 /// Actor name for audit trail
32 #[arg(long, global = true, env = "SC_ACTOR")]
33 pub actor: Option<String>,
34
35 /// Active session ID (passed by MCP server)
36 #[arg(long, global = true, env = "SC_SESSION")]
37 pub session: Option<String>,
38
39 /// Output as JSON (for agent integration)
40 #[arg(long, alias = "robot", global = true)]
41 pub json: bool,
42
43 /// Output format (table, json, csv)
44 #[arg(long, value_enum, global = true, default_value_t)]
45 pub format: OutputFormat,
46
47 /// Output only the ID/key (for agent scripting)
48 #[arg(long, global = true)]
49 pub silent: bool,
50
51 /// Preview changes without writing to the database
52 #[arg(long, global = true)]
53 pub dry_run: bool,
54
55 /// Increase logging verbosity (-v, -vv)
56 #[arg(short, long, action = clap::ArgAction::Count, global = true)]
57 pub verbose: u8,
58
59 /// Quiet mode (no output except errors)
60 #[arg(short, long, global = true)]
61 pub quiet: bool,
62
63 /// Disable colored output
64 #[arg(long, global = true)]
65 pub no_color: bool,
66}
67
68#[derive(Subcommand, Debug)]
69pub enum Commands {
70 /// Initialize a SaveContext workspace
71 Init {
72 /// Use global location (~/.savecontext/)
73 #[arg(long)]
74 global: bool,
75
76 /// Overwrite existing database
77 #[arg(long)]
78 force: bool,
79 },
80
81 /// Print version information
82 Version,
83
84 /// Session management
85 Session {
86 #[command(subcommand)]
87 command: SessionCommands,
88 },
89
90 /// Show current session status
91 Status,
92
93 /// Save a context item
94 Save(SaveArgs),
95
96 /// Get/search context items
97 Get(GetArgs),
98
99 /// Delete a context item
100 Delete {
101 /// Key of the item to delete
102 key: String,
103 },
104
105 /// Update a context item
106 Update(UpdateArgs),
107
108 /// Tag context items
109 Tag {
110 #[command(subcommand)]
111 command: TagCommands,
112 },
113
114 /// Issue management
115 Issue {
116 #[command(subcommand)]
117 command: IssueCommands,
118 },
119
120 /// Checkpoint management
121 Checkpoint {
122 #[command(subcommand)]
123 command: CheckpointCommands,
124 },
125
126 /// Project memory (persistent across sessions)
127 Memory {
128 #[command(subcommand)]
129 command: MemoryCommands,
130 },
131
132 /// Sync with JSONL files
133 Sync {
134 #[command(subcommand)]
135 command: SyncCommands,
136 },
137
138 /// Project management
139 Project {
140 #[command(subcommand)]
141 command: ProjectCommands,
142 },
143
144 /// Plan management (PRDs, specs, feature docs)
145 Plan {
146 #[command(subcommand)]
147 command: PlanCommands,
148 },
149
150 /// Prepare context for compaction (auto-checkpoint + summary)
151 Compaction,
152
153 /// Generate context primer for agent injection
154 Prime {
155 /// Include Claude Code transcript summaries
156 #[arg(long)]
157 transcript: bool,
158
159 /// Maximum transcript entries to include
160 #[arg(long, default_value = "5")]
161 transcript_limit: usize,
162
163 /// Compact output for agent system prompt injection
164 #[arg(long)]
165 compact: bool,
166 },
167
168 /// Generate shell completions
169 Completions {
170 /// Shell to generate completions for
171 #[arg(value_enum)]
172 shell: Shell,
173 },
174
175 /// Embedding configuration and management
176 Embeddings {
177 #[command(subcommand)]
178 command: EmbeddingsCommands,
179 },
180}
181
182/// Supported shells for completions.
183#[derive(clap::ValueEnum, Clone, Debug)]
184pub enum Shell {
185 Bash,
186 Zsh,
187 Fish,
188 PowerShell,
189 Elvish,
190}
191
192// ============================================================================
193// Session Commands
194// ============================================================================
195
196#[derive(Subcommand, Debug)]
197pub enum SessionCommands {
198 /// Start a new session
199 Start {
200 /// Session name
201 name: String,
202
203 /// Session description
204 #[arg(short, long)]
205 description: Option<String>,
206
207 /// Project path (defaults to current directory)
208 #[arg(short, long)]
209 project: Option<String>,
210
211 /// Channel name (auto-derived from git branch if not provided)
212 #[arg(long)]
213 channel: Option<String>,
214
215 /// Force create a new session instead of resuming existing one
216 #[arg(long)]
217 force_new: bool,
218 },
219
220 /// End current session
221 End,
222
223 /// Pause current session
224 Pause,
225
226 /// Resume a paused session
227 Resume {
228 /// Session ID to resume
229 id: String,
230 },
231
232 /// List sessions
233 List {
234 /// Filter by status (active, paused, completed, all)
235 #[arg(short, long, default_value = "active")]
236 status: String,
237
238 /// Maximum sessions to return
239 #[arg(short, long, default_value = "10")]
240 limit: usize,
241
242 /// Search sessions by name or description
243 #[arg(long)]
244 search: Option<String>,
245
246 /// Filter by project path
247 #[arg(short, long)]
248 project: Option<String>,
249
250 /// Show sessions from all projects (ignore project filter)
251 #[arg(long)]
252 all_projects: bool,
253
254 /// Include completed sessions (when status is not 'all' or 'completed')
255 #[arg(long)]
256 include_completed: bool,
257 },
258
259 /// Switch to a different session
260 Switch {
261 /// Session ID to switch to
262 id: String,
263 },
264
265 /// Rename current session
266 Rename {
267 /// New session name
268 name: String,
269 },
270
271 /// Delete a session permanently
272 Delete {
273 /// Session ID
274 id: String,
275
276 /// Skip confirmation and delete
277 #[arg(short, long)]
278 force: bool,
279 },
280
281 /// Add a project path to a session
282 AddPath {
283 /// Session ID (uses current active session if not specified)
284 #[arg(short, long)]
285 id: Option<String>,
286
287 /// Project path to add (defaults to current directory)
288 path: Option<String>,
289 },
290
291 /// Remove a project path from a session
292 RemovePath {
293 /// Session ID (uses current active session if not specified)
294 #[arg(short, long)]
295 id: Option<String>,
296
297 /// Project path to remove
298 path: String,
299 },
300}
301
302// ============================================================================
303// Context Item Commands (Save/Get)
304// ============================================================================
305
306#[derive(Args, Debug)]
307pub struct SaveArgs {
308 /// Unique key for this context item
309 pub key: String,
310
311 /// Value to save
312 pub value: String,
313
314 /// Category (reminder, decision, progress, note)
315 #[arg(short, long, default_value = "note")]
316 pub category: String,
317
318 /// Priority (high, normal, low)
319 #[arg(short, long, default_value = "normal")]
320 pub priority: String,
321}
322
323#[derive(Args, Debug, Default)]
324pub struct GetArgs {
325 /// Search query (keyword search)
326 #[arg(short = 's', long)]
327 pub query: Option<String>,
328
329 /// Get by exact key
330 #[arg(short, long)]
331 pub key: Option<String>,
332
333 /// Filter by category
334 #[arg(short, long)]
335 pub category: Option<String>,
336
337 /// Filter by priority
338 #[arg(short = 'P', long)]
339 pub priority: Option<String>,
340
341 /// Search across all sessions (not just current)
342 #[arg(long)]
343 pub search_all_sessions: bool,
344
345 /// Semantic search threshold (0.0-1.0, lower = more results)
346 #[arg(long)]
347 pub threshold: Option<f64>,
348
349 /// Semantic search mode (fast, quality, tiered)
350 ///
351 /// - fast: Instant results using Model2Vec (lower accuracy)
352 /// - quality: Slower but more accurate results using Ollama/HuggingFace
353 /// - tiered: Fast candidates, quality re-ranking (default)
354 #[arg(long, value_parser = parse_search_mode)]
355 pub search_mode: Option<crate::embeddings::SearchMode>,
356
357 /// Pagination offset
358 #[arg(long)]
359 pub offset: Option<usize>,
360
361 /// Maximum items to return
362 #[arg(short, long, default_value = "50")]
363 pub limit: usize,
364}
365
366/// Parse search mode from string
367fn parse_search_mode(s: &str) -> std::result::Result<crate::embeddings::SearchMode, String> {
368 s.parse()
369}
370
371#[derive(Args, Debug)]
372pub struct UpdateArgs {
373 /// Key of the item to update
374 pub key: String,
375
376 /// New value
377 #[arg(long)]
378 pub value: Option<String>,
379
380 /// New category (reminder, decision, progress, note)
381 #[arg(short, long)]
382 pub category: Option<String>,
383
384 /// New priority (high, normal, low)
385 #[arg(short, long)]
386 pub priority: Option<String>,
387
388 /// New channel
389 #[arg(long)]
390 pub channel: Option<String>,
391}
392
393#[derive(Subcommand, Debug)]
394pub enum TagCommands {
395 /// Add tags to context items
396 Add {
397 /// Key of the item to tag
398 key: String,
399
400 /// Tags to add (comma-separated or multiple --tag flags)
401 #[arg(short, long, value_delimiter = ',', required = true)]
402 tags: Vec<String>,
403 },
404
405 /// Remove tags from context items
406 Remove {
407 /// Key of the item to untag
408 key: String,
409
410 /// Tags to remove (comma-separated or multiple --tag flags)
411 #[arg(short, long, value_delimiter = ',', required = true)]
412 tags: Vec<String>,
413 },
414}
415
416// ============================================================================
417// Issue Commands
418// ============================================================================
419
420#[derive(Subcommand, Debug)]
421pub enum IssueCommands {
422 /// Create a new issue
423 Create(IssueCreateArgs),
424
425 /// List issues
426 List(IssueListArgs),
427
428 /// Show issue details
429 Show {
430 /// Issue ID (short or full)
431 id: String,
432 },
433
434 /// Update an issue
435 Update(IssueUpdateArgs),
436
437 /// Mark issue(s) as complete
438 Complete {
439 /// Issue IDs (one or more)
440 ids: Vec<String>,
441 },
442
443 /// Claim issue(s) (assign to self)
444 Claim {
445 /// Issue IDs (one or more)
446 ids: Vec<String>,
447 },
448
449 /// Release issue(s)
450 Release {
451 /// Issue IDs (one or more)
452 ids: Vec<String>,
453 },
454
455 /// Delete issue(s)
456 Delete {
457 /// Issue IDs (one or more)
458 ids: Vec<String>,
459 },
460
461 /// Manage issue labels
462 Label {
463 #[command(subcommand)]
464 command: IssueLabelCommands,
465 },
466
467 /// Manage issue dependencies
468 Dep {
469 #[command(subcommand)]
470 command: IssueDepCommands,
471 },
472
473 /// Clone an issue
474 Clone {
475 /// Issue ID to clone
476 id: String,
477
478 /// New title (defaults to "Copy of <original>")
479 #[arg(short, long)]
480 title: Option<String>,
481 },
482
483 /// Mark issue as duplicate of another
484 Duplicate {
485 /// Issue ID to mark as duplicate
486 id: String,
487
488 /// Issue ID this is a duplicate of
489 #[arg(long)]
490 of: String,
491 },
492
493 /// List issues ready to work on
494 Ready {
495 /// Maximum issues to return
496 #[arg(short, long, default_value = "10")]
497 limit: usize,
498 },
499
500 /// Get next block of issues and claim them
501 NextBlock {
502 /// Number of issues to claim
503 #[arg(short, long, default_value = "3")]
504 count: usize,
505 },
506
507 /// Create multiple issues at once with dependencies
508 Batch {
509 /// JSON input containing issues array, dependencies, and optional planId
510 #[arg(long)]
511 json_input: String,
512 },
513}
514
515#[derive(Subcommand, Debug)]
516pub enum IssueLabelCommands {
517 /// Add labels to an issue
518 Add {
519 /// Issue ID
520 id: String,
521
522 /// Labels to add (comma-separated)
523 #[arg(short, long, value_delimiter = ',', required = true)]
524 labels: Vec<String>,
525 },
526
527 /// Remove labels from an issue
528 Remove {
529 /// Issue ID
530 id: String,
531
532 /// Labels to remove (comma-separated)
533 #[arg(short, long, value_delimiter = ',', required = true)]
534 labels: Vec<String>,
535 },
536}
537
538#[derive(Subcommand, Debug)]
539pub enum IssueDepCommands {
540 /// Add a dependency to an issue
541 Add {
542 /// Issue ID
543 id: String,
544
545 /// ID of issue this depends on
546 #[arg(long)]
547 depends_on: String,
548
549 /// Dependency type (blocks, related, parent-child, discovered-from)
550 #[arg(short = 't', long, default_value = "blocks")]
551 dep_type: String,
552 },
553
554 /// Remove a dependency from an issue
555 Remove {
556 /// Issue ID
557 id: String,
558
559 /// ID of issue to remove dependency on
560 #[arg(long)]
561 depends_on: String,
562 },
563}
564
565#[derive(Args, Debug)]
566pub struct IssueCreateArgs {
567 /// Issue title
568 pub title: String,
569
570 /// Issue description
571 #[arg(short, long)]
572 pub description: Option<String>,
573
574 /// Implementation details or notes
575 #[arg(long)]
576 pub details: Option<String>,
577
578 /// Issue type (task, bug, feature, epic, chore)
579 #[arg(short = 't', long, default_value = "task")]
580 pub issue_type: String,
581
582 /// Priority (0=lowest to 4=critical)
583 #[arg(short, long, default_value = "2")]
584 pub priority: i32,
585
586 /// Parent issue ID (for subtasks)
587 #[arg(long)]
588 pub parent: Option<String>,
589
590 /// Link issue to a Plan (PRD/spec)
591 #[arg(long)]
592 pub plan_id: Option<String>,
593
594 /// Labels (-l bug -l security or -l bug,security)
595 #[arg(short, long, value_delimiter = ',')]
596 pub labels: Option<Vec<String>>,
597
598 /// Import issues from a JSONL file (one JSON object per line)
599 #[arg(short, long)]
600 pub file: Option<PathBuf>,
601}
602
603#[derive(Args, Debug, Default)]
604pub struct IssueListArgs {
605 /// Filter by specific issue ID (short or full)
606 #[arg(long)]
607 pub id: Option<String>,
608
609 /// Filter by status (backlog, open, in_progress, blocked, closed, deferred, all)
610 #[arg(short, long, default_value = "open")]
611 pub status: String,
612
613 /// Filter by exact priority (0-4)
614 #[arg(short, long)]
615 pub priority: Option<i32>,
616
617 /// Filter by minimum priority
618 #[arg(long)]
619 pub priority_min: Option<i32>,
620
621 /// Filter by maximum priority
622 #[arg(long)]
623 pub priority_max: Option<i32>,
624
625 /// Filter by type
626 #[arg(short = 't', long)]
627 pub issue_type: Option<String>,
628
629 /// Filter by labels (all must match, comma-separated)
630 #[arg(long, value_delimiter = ',')]
631 pub labels: Option<Vec<String>>,
632
633 /// Filter by labels (any must match, comma-separated)
634 #[arg(long, value_delimiter = ',')]
635 pub labels_any: Option<Vec<String>>,
636
637 /// Filter by parent issue ID
638 #[arg(long)]
639 pub parent: Option<String>,
640
641 /// Filter by plan ID
642 #[arg(long)]
643 pub plan: Option<String>,
644
645 /// Filter issues with subtasks
646 #[arg(long)]
647 pub has_subtasks: bool,
648
649 /// Filter issues without subtasks
650 #[arg(long)]
651 pub no_subtasks: bool,
652
653 /// Filter issues with dependencies
654 #[arg(long)]
655 pub has_deps: bool,
656
657 /// Filter issues without dependencies
658 #[arg(long)]
659 pub no_deps: bool,
660
661 /// Sort by field (priority, createdAt, updatedAt)
662 #[arg(long, default_value = "createdAt")]
663 pub sort: String,
664
665 /// Sort order (asc, desc)
666 #[arg(long, default_value = "desc")]
667 pub order: String,
668
669 /// Filter by issues created in last N days
670 #[arg(long)]
671 pub created_days: Option<i64>,
672
673 /// Filter by issues created in last N hours
674 #[arg(long)]
675 pub created_hours: Option<i64>,
676
677 /// Filter by issues updated in last N days
678 #[arg(long)]
679 pub updated_days: Option<i64>,
680
681 /// Filter by issues updated in last N hours
682 #[arg(long)]
683 pub updated_hours: Option<i64>,
684
685 /// Search in title/description
686 #[arg(long)]
687 pub search: Option<String>,
688
689 /// Filter by assignee
690 #[arg(long)]
691 pub assignee: Option<String>,
692
693 /// Search across all projects
694 #[arg(long)]
695 pub all_projects: bool,
696
697 /// Maximum issues to return
698 #[arg(short, long, default_value = "50")]
699 pub limit: usize,
700}
701
702#[derive(Args, Debug)]
703pub struct IssueUpdateArgs {
704 /// Issue ID
705 pub id: String,
706
707 /// New title
708 #[arg(long)]
709 pub title: Option<String>,
710
711 /// New description
712 #[arg(short, long)]
713 pub description: Option<String>,
714
715 /// New details
716 #[arg(long)]
717 pub details: Option<String>,
718
719 /// New status
720 #[arg(short, long)]
721 pub status: Option<String>,
722
723 /// New priority
724 #[arg(short, long)]
725 pub priority: Option<i32>,
726
727 /// New type
728 #[arg(short = 't', long)]
729 pub issue_type: Option<String>,
730
731 /// New parent issue ID
732 #[arg(long)]
733 pub parent: Option<String>,
734
735 /// New plan ID
736 #[arg(long)]
737 pub plan: Option<String>,
738}
739
740// ============================================================================
741// Checkpoint Commands
742// ============================================================================
743
744#[derive(Subcommand, Debug)]
745pub enum CheckpointCommands {
746 /// Create a checkpoint
747 Create {
748 /// Checkpoint name
749 name: String,
750
751 /// Description
752 #[arg(short, long)]
753 description: Option<String>,
754
755 /// Include git status
756 #[arg(long)]
757 include_git: bool,
758 },
759
760 /// List checkpoints
761 List {
762 /// Search checkpoints by name or description
763 #[arg(short, long)]
764 search: Option<String>,
765
766 /// Filter by session ID
767 #[arg(long)]
768 session: Option<String>,
769
770 /// Filter by project path
771 #[arg(long)]
772 project: Option<String>,
773
774 /// Include checkpoints from all projects
775 #[arg(long)]
776 all_projects: bool,
777
778 /// Maximum checkpoints to return
779 #[arg(short, long, default_value = "20")]
780 limit: usize,
781
782 /// Pagination offset
783 #[arg(long)]
784 offset: Option<usize>,
785 },
786
787 /// Show checkpoint details
788 Show {
789 /// Checkpoint ID
790 id: String,
791 },
792
793 /// Restore from checkpoint
794 Restore {
795 /// Checkpoint ID
796 id: String,
797
798 /// Only restore items in these categories (comma-separated)
799 #[arg(long, value_delimiter = ',')]
800 categories: Option<Vec<String>>,
801
802 /// Only restore items with these tags (comma-separated)
803 #[arg(long, value_delimiter = ',')]
804 tags: Option<Vec<String>>,
805 },
806
807 /// Delete a checkpoint
808 Delete {
809 /// Checkpoint ID
810 id: String,
811 },
812
813 /// Add items to an existing checkpoint
814 AddItems {
815 /// Checkpoint ID
816 id: String,
817
818 /// Context item keys to add (comma-separated)
819 #[arg(short, long, value_delimiter = ',', required = true)]
820 keys: Vec<String>,
821 },
822
823 /// Remove items from a checkpoint
824 RemoveItems {
825 /// Checkpoint ID
826 id: String,
827
828 /// Context item keys to remove (comma-separated)
829 #[arg(short, long, value_delimiter = ',', required = true)]
830 keys: Vec<String>,
831 },
832
833 /// List items in a checkpoint
834 Items {
835 /// Checkpoint ID
836 id: String,
837 },
838}
839
840// ============================================================================
841// Memory Commands (Project-level persistent storage)
842// ============================================================================
843
844#[derive(Subcommand, Debug)]
845pub enum MemoryCommands {
846 /// Save a memory item
847 Save {
848 /// Key
849 key: String,
850
851 /// Value
852 value: String,
853
854 /// Category (command, config, note)
855 #[arg(short, long, default_value = "command")]
856 category: String,
857 },
858
859 /// Get a memory item
860 Get {
861 /// Key
862 key: String,
863 },
864
865 /// List memory items
866 List {
867 /// Filter by category
868 #[arg(short, long)]
869 category: Option<String>,
870 },
871
872 /// Delete a memory item
873 Delete {
874 /// Key
875 key: String,
876 },
877}
878
879// ============================================================================
880// Sync Commands
881// ============================================================================
882
883#[derive(Subcommand, Debug)]
884pub enum SyncCommands {
885 /// Export to JSONL
886 Export {
887 /// Force export even if JSONL is newer
888 #[arg(long)]
889 force: bool,
890 },
891
892 /// Import from JSONL
893 Import {
894 /// Force import even with conflicts
895 #[arg(long)]
896 force: bool,
897 },
898
899 /// Show sync status
900 Status,
901}
902
903// ============================================================================
904// Project Commands
905// ============================================================================
906
907#[derive(Subcommand, Debug)]
908pub enum ProjectCommands {
909 /// Create a new project
910 Create(ProjectCreateArgs),
911
912 /// List all projects
913 List {
914 /// Include session count for each project
915 #[arg(long)]
916 session_count: bool,
917
918 /// Maximum projects to return
919 #[arg(short, long, default_value = "50")]
920 limit: usize,
921 },
922
923 /// Show project details
924 Show {
925 /// Project ID or path
926 id: String,
927 },
928
929 /// Update a project
930 Update(ProjectUpdateArgs),
931
932 /// Delete a project
933 Delete {
934 /// Project ID or path
935 id: String,
936
937 /// Skip confirmation and delete
938 #[arg(short, long)]
939 force: bool,
940 },
941}
942
943#[derive(Args, Debug)]
944pub struct ProjectCreateArgs {
945 /// Project path (defaults to current directory)
946 pub path: Option<String>,
947
948 /// Project name (defaults to directory name)
949 #[arg(short, long)]
950 pub name: Option<String>,
951
952 /// Project description
953 #[arg(short, long)]
954 pub description: Option<String>,
955
956 /// Issue ID prefix (e.g., "SC" creates SC-1, SC-2)
957 #[arg(short = 'p', long)]
958 pub issue_prefix: Option<String>,
959}
960
961#[derive(Args, Debug)]
962pub struct ProjectUpdateArgs {
963 /// Project ID or path
964 pub id: String,
965
966 /// New project name
967 #[arg(short, long)]
968 pub name: Option<String>,
969
970 /// New description
971 #[arg(short, long)]
972 pub description: Option<String>,
973
974 /// New issue ID prefix
975 #[arg(short = 'p', long)]
976 pub issue_prefix: Option<String>,
977}
978
979// ============================================================================
980// Plan Commands
981// ============================================================================
982
983#[derive(Subcommand, Debug)]
984pub enum PlanCommands {
985 /// Create a new plan
986 Create(PlanCreateArgs),
987
988 /// List plans
989 List {
990 /// Filter by status (draft, active, completed, all)
991 #[arg(short, long, default_value = "active")]
992 status: String,
993
994 /// Maximum plans to return
995 #[arg(short, long, default_value = "50")]
996 limit: usize,
997 },
998
999 /// Show plan details
1000 Show {
1001 /// Plan ID
1002 id: String,
1003 },
1004
1005 /// Update a plan
1006 Update(PlanUpdateArgs),
1007}
1008
1009#[derive(Args, Debug)]
1010pub struct PlanCreateArgs {
1011 /// Plan title
1012 pub title: String,
1013
1014 /// Plan content (markdown PRD/spec)
1015 #[arg(short, long)]
1016 pub content: Option<String>,
1017
1018 /// Plan status (draft, active, completed)
1019 #[arg(short, long, default_value = "active")]
1020 pub status: String,
1021
1022 /// Success criteria
1023 #[arg(long)]
1024 pub success_criteria: Option<String>,
1025}
1026
1027#[derive(Args, Debug)]
1028pub struct PlanUpdateArgs {
1029 /// Plan ID
1030 pub id: String,
1031
1032 /// New title
1033 #[arg(long)]
1034 pub title: Option<String>,
1035
1036 /// New content
1037 #[arg(short, long)]
1038 pub content: Option<String>,
1039
1040 /// New status (draft, active, completed)
1041 #[arg(short, long)]
1042 pub status: Option<String>,
1043
1044 /// New success criteria
1045 #[arg(long)]
1046 pub success_criteria: Option<String>,
1047}
1048
1049// ============================================================================
1050// Embeddings Commands
1051// ============================================================================
1052
1053#[derive(Subcommand, Debug, Clone)]
1054pub enum EmbeddingsCommands {
1055 /// Show embeddings status and configuration
1056 Status,
1057
1058 /// Configure embedding provider
1059 Configure {
1060 /// Provider (ollama, huggingface)
1061 #[arg(short, long)]
1062 provider: Option<String>,
1063
1064 /// Enable embeddings
1065 #[arg(long)]
1066 enable: bool,
1067
1068 /// Disable embeddings
1069 #[arg(long)]
1070 disable: bool,
1071
1072 /// Model to use (provider-specific)
1073 #[arg(short, long)]
1074 model: Option<String>,
1075
1076 /// API endpoint (for custom servers)
1077 #[arg(long)]
1078 endpoint: Option<String>,
1079
1080 /// API token (for HuggingFace)
1081 #[arg(long)]
1082 token: Option<String>,
1083 },
1084
1085 /// Backfill embeddings for existing context items
1086 Backfill {
1087 /// Maximum items to process
1088 #[arg(short, long)]
1089 limit: Option<usize>,
1090
1091 /// Session ID to backfill (defaults to current)
1092 #[arg(short, long)]
1093 session: Option<String>,
1094
1095 /// Force regeneration of existing embeddings
1096 #[arg(long)]
1097 force: bool,
1098 },
1099
1100 /// Test embedding provider connectivity
1101 Test {
1102 /// Text to generate test embedding for
1103 #[arg(default_value = "Hello world")]
1104 text: String,
1105 },
1106
1107 /// Process pending embeddings in background (internal use)
1108 #[command(hide = true)]
1109 ProcessPending {
1110 /// Maximum items to process
1111 #[arg(short, long, default_value = "10")]
1112 limit: usize,
1113
1114 /// Run silently (no output)
1115 #[arg(long)]
1116 quiet: bool,
1117 },
1118
1119 /// Upgrade items with fast embeddings to quality embeddings
1120 ///
1121 /// Items saved with the 2-tier system get instant fast embeddings (Model2Vec).
1122 /// This command generates higher-quality embeddings (Ollama/HuggingFace)
1123 /// for items that only have fast embeddings.
1124 UpgradeQuality {
1125 /// Maximum items to process
1126 #[arg(short, long)]
1127 limit: Option<usize>,
1128
1129 /// Session ID to upgrade (defaults to all sessions)
1130 #[arg(short, long)]
1131 session: Option<String>,
1132 },
1133}