intent_engine/cli.rs
1use clap::{Parser, Subcommand};
2
3#[derive(Parser)]
4#[command(name = "intent-engine")]
5#[command(about = "A command-line database service for tracking strategic intent", long_about = None)]
6#[command(version)]
7pub struct Cli {
8 #[command(subcommand)]
9 pub command: Commands,
10}
11
12#[derive(Subcommand)]
13pub enum Commands {
14 /// Task management commands
15 #[command(subcommand)]
16 Task(TaskCommands),
17
18 /// Workspace state management
19 Current {
20 /// Set the current task ID
21 #[arg(long)]
22 set: Option<i64>,
23 },
24
25 /// Generate analysis and reports
26 Report {
27 /// Time duration (e.g., "7d", "2h", "30m")
28 #[arg(long)]
29 since: Option<String>,
30
31 /// Filter by status
32 #[arg(long)]
33 status: Option<String>,
34
35 /// Filter by name pattern (FTS5)
36 #[arg(long)]
37 filter_name: Option<String>,
38
39 /// Filter by spec pattern (FTS5)
40 #[arg(long)]
41 filter_spec: Option<String>,
42
43 /// Output format
44 #[arg(long, default_value = "json")]
45 format: String,
46
47 /// Return summary only
48 #[arg(long)]
49 summary_only: bool,
50 },
51
52 /// Event logging commands
53 #[command(subcommand)]
54 Event(EventCommands),
55
56 /// Check system health and dependencies
57 Doctor,
58
59 /// Start MCP server for AI assistants (JSON-RPC stdio)
60 #[command(name = "mcp-server")]
61 McpServer,
62}
63
64#[derive(Subcommand)]
65pub enum TaskCommands {
66 /// Add a new task
67 Add {
68 /// Task name
69 #[arg(long)]
70 name: String,
71
72 /// Parent task ID
73 #[arg(long)]
74 parent: Option<i64>,
75
76 /// Read spec from stdin
77 #[arg(long)]
78 spec_stdin: bool,
79 },
80
81 /// Get a task by ID
82 Get {
83 /// Task ID
84 id: i64,
85
86 /// Include events summary
87 #[arg(long)]
88 with_events: bool,
89 },
90
91 /// Update a task
92 Update {
93 /// Task ID
94 id: i64,
95
96 /// New task name
97 #[arg(long)]
98 name: Option<String>,
99
100 /// New parent task ID
101 #[arg(long)]
102 parent: Option<i64>,
103
104 /// New status
105 #[arg(long)]
106 status: Option<String>,
107
108 /// Task complexity (1-10)
109 #[arg(long)]
110 complexity: Option<i32>,
111
112 /// Task priority (critical, high, medium, low)
113 #[arg(long)]
114 priority: Option<String>,
115
116 /// Read spec from stdin
117 #[arg(long)]
118 spec_stdin: bool,
119 },
120
121 /// Delete a task
122 Del {
123 /// Task ID
124 id: i64,
125 },
126
127 /// List tasks with filters
128 List {
129 /// Filter by status
130 #[arg(long)]
131 status: Option<String>,
132
133 /// Filter by parent ID (use "null" for no parent)
134 #[arg(long)]
135 parent: Option<String>,
136 },
137
138 /// Find tasks with filters (deprecated: use 'list' instead)
139 #[command(hide = true)]
140 Find {
141 /// Filter by status
142 #[arg(long)]
143 status: Option<String>,
144
145 /// Filter by parent ID (use "null" for no parent)
146 #[arg(long)]
147 parent: Option<String>,
148 },
149
150 /// Start a task (atomic: update status + set current)
151 Start {
152 /// Task ID
153 id: i64,
154
155 /// Include events summary
156 #[arg(long)]
157 with_events: bool,
158 },
159
160 /// Complete the current focused task (atomic: check children + update status + clear current)
161 /// This command only operates on the current_task_id. It will:
162 /// - Check all subtasks are done
163 /// - Update the task status to done
164 /// - Clear the current_task_id
165 ///
166 /// Prerequisites: A task must be set as current (via `current --set <ID>`)
167 Done,
168
169 /// Intelligently recommend the next task to work on
170 ///
171 /// This command uses a context-aware priority model to recommend a single task:
172 /// 1. First priority: Subtasks of the current focused task (depth-first)
173 /// 2. Second priority: Top-level tasks (breadth-first)
174 ///
175 /// The command is non-interactive and does not modify task status.
176 PickNext {
177 /// Output format (text or json)
178 #[arg(long, default_value = "text")]
179 format: String,
180 },
181
182 /// Create a subtask under current task and switch to it
183 SpawnSubtask {
184 /// Subtask name
185 #[arg(long)]
186 name: String,
187
188 /// Read spec from stdin
189 #[arg(long)]
190 spec_stdin: bool,
191 },
192
193 /// Switch to a specific task (atomic: update to doing + set current)
194 Switch {
195 /// Task ID
196 id: i64,
197 },
198
199 /// Search tasks by content using full-text search
200 Search {
201 /// Search query (supports FTS5 syntax like "bug AND NOT critical")
202 query: String,
203 },
204
205 /// Add a dependency between tasks
206 ///
207 /// Creates a dependency where BLOCKED_TASK depends on BLOCKING_TASK.
208 /// The BLOCKING_TASK must be completed before BLOCKED_TASK can be started.
209 ///
210 /// Example: `task depends-on 42 41` means Task 42 depends on Task 41
211 /// (Task 41 must be done before Task 42 can start)
212 #[command(name = "depends-on")]
213 DependsOn {
214 /// Task ID that has the dependency (blocked task)
215 blocked_task_id: i64,
216
217 /// Task ID that must be completed first (blocking task)
218 blocking_task_id: i64,
219 },
220}
221
222#[derive(Subcommand)]
223pub enum EventCommands {
224 /// Add a new event
225 Add {
226 /// Task ID (optional, uses current task if not specified)
227 #[arg(long)]
228 task_id: Option<i64>,
229
230 /// Log type
231 #[arg(long = "type")]
232 log_type: String,
233
234 /// Read discussion data from stdin
235 #[arg(long)]
236 data_stdin: bool,
237 },
238
239 /// List events for a task
240 List {
241 /// Task ID
242 #[arg(long)]
243 task_id: i64,
244
245 /// Maximum number of events to return
246 #[arg(long)]
247 limit: Option<i64>,
248
249 /// Filter by log type (e.g., "decision", "blocker", "milestone", "note")
250 #[arg(long = "type")]
251 log_type: Option<String>,
252
253 /// Filter events created within duration (e.g., "7d", "24h", "30m")
254 #[arg(long)]
255 since: Option<String>,
256 },
257}