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 (for backward compatibility)
21 #[arg(long)]
22 set: Option<i64>,
23
24 #[command(subcommand)]
25 command: Option<CurrentAction>,
26 },
27
28 /// Generate analysis and reports
29 Report {
30 /// Time duration (e.g., "7d", "2h", "30m")
31 #[arg(long)]
32 since: Option<String>,
33
34 /// Filter by status
35 #[arg(long)]
36 status: Option<String>,
37
38 /// Filter by name pattern (FTS5)
39 #[arg(long)]
40 filter_name: Option<String>,
41
42 /// Filter by spec pattern (FTS5)
43 #[arg(long)]
44 filter_spec: Option<String>,
45
46 /// Output format
47 #[arg(long, default_value = "json")]
48 format: String,
49
50 /// Return summary only
51 #[arg(long)]
52 summary_only: bool,
53 },
54
55 /// Event logging commands
56 #[command(subcommand)]
57 Event(EventCommands),
58
59 /// Unified search across tasks and events
60 Search {
61 /// Search query (supports FTS5 syntax like "JWT AND authentication")
62 query: String,
63
64 /// Search in tasks (default: true)
65 #[arg(long, default_value = "true")]
66 tasks: bool,
67
68 /// Search in events (default: true)
69 #[arg(long, default_value = "true")]
70 events: bool,
71
72 /// Maximum number of results (default: 20)
73 #[arg(long)]
74 limit: Option<i64>,
75 },
76
77 /// Check system health and dependencies
78 Doctor,
79
80 /// Start MCP server for AI assistants (JSON-RPC stdio)
81 #[command(name = "mcp-server")]
82 McpServer,
83
84 /// Restore session context for AI agents (Focus Restoration - Phase 1)
85 ///
86 /// This command returns all context needed to restore work continuity:
87 /// - Current focused task
88 /// - Parent task and siblings progress
89 /// - Child tasks status
90 /// - Recent events (decisions, blockers, notes)
91 /// - Suggested next commands
92 ///
93 /// Designed for SessionStart hooks to inject context at the beginning of new sessions.
94 #[command(name = "session-restore")]
95 SessionRestore {
96 /// Number of recent events to include (default: 3)
97 #[arg(long, default_value = "3")]
98 include_events: usize,
99
100 /// Workspace path (default: current directory)
101 #[arg(long)]
102 workspace: Option<String>,
103 },
104
105 /// Unified setup command for AI tool integrations
106 ///
107 /// This command provides a unified interface for setting up intent-engine integration
108 /// with various AI assistant tools. It handles both hook installation and MCP server
109 /// configuration in one step.
110 ///
111 /// Features:
112 /// - User-level or project-level installation
113 /// - Atomic setup with rollback on failure
114 /// - Built-in connectivity testing
115 /// - Diagnosis mode for troubleshooting
116 Setup {
117 /// Target tool to configure (claude-code, gemini-cli, codex)
118 #[arg(long)]
119 target: Option<String>,
120
121 /// Installation scope: user (default, recommended), project, or both
122 #[arg(long, default_value = "user")]
123 scope: String,
124
125 /// Show what would be done without actually doing it
126 #[arg(long)]
127 dry_run: bool,
128
129 /// Overwrite existing configuration
130 #[arg(long)]
131 force: bool,
132
133 /// Run diagnosis on existing setup instead of installing
134 #[arg(long)]
135 diagnose: bool,
136
137 /// Custom config file path (advanced)
138 #[arg(long)]
139 config_path: Option<String>,
140
141 /// Project directory for INTENT_ENGINE_PROJECT_DIR env var
142 #[arg(long)]
143 project_dir: Option<String>,
144 },
145}
146
147#[derive(Subcommand)]
148pub enum CurrentAction {
149 /// Set the current task (low-level atomic command, prefer 'ie task start')
150 #[command(hide = true)]
151 Set {
152 /// Task ID to set as current
153 task_id: i64,
154 },
155
156 /// Clear the current task (low-level atomic command, prefer 'ie task done')
157 #[command(hide = true)]
158 Clear,
159}
160
161#[derive(Subcommand)]
162pub enum TaskCommands {
163 /// Add a new task
164 Add {
165 /// Task name
166 #[arg(long)]
167 name: String,
168
169 /// Parent task ID
170 #[arg(long)]
171 parent: Option<i64>,
172
173 /// Read spec from stdin
174 #[arg(long)]
175 spec_stdin: bool,
176 },
177
178 /// Get a task by ID
179 Get {
180 /// Task ID
181 id: i64,
182
183 /// Include events summary
184 #[arg(long)]
185 with_events: bool,
186 },
187
188 /// Update a task
189 Update {
190 /// Task ID
191 id: i64,
192
193 /// New task name
194 #[arg(long)]
195 name: Option<String>,
196
197 /// New parent task ID
198 #[arg(long)]
199 parent: Option<i64>,
200
201 /// New status
202 #[arg(long)]
203 status: Option<String>,
204
205 /// Task complexity (1-10)
206 #[arg(long)]
207 complexity: Option<i32>,
208
209 /// Task priority (critical, high, medium, low)
210 #[arg(long)]
211 priority: Option<String>,
212
213 /// Read spec from stdin
214 #[arg(long)]
215 spec_stdin: bool,
216 },
217
218 /// Delete a task
219 Del {
220 /// Task ID
221 id: i64,
222 },
223
224 /// List tasks with filters
225 List {
226 /// Filter by status
227 #[arg(long)]
228 status: Option<String>,
229
230 /// Filter by parent ID (use "null" for no parent)
231 #[arg(long)]
232 parent: Option<String>,
233 },
234
235 /// Start a task (atomic: update status + set current)
236 Start {
237 /// Task ID
238 id: i64,
239
240 /// Include events summary
241 #[arg(long)]
242 with_events: bool,
243 },
244
245 /// Complete the current focused task (atomic: check children + update status + clear current)
246 /// This command only operates on the current_task_id. It will:
247 /// - Check all subtasks are done
248 /// - Update the task status to done
249 /// - Clear the current_task_id
250 ///
251 /// Prerequisites: A task must be set as current (via `current --set <ID>`)
252 Done,
253
254 /// Intelligently recommend the next task to work on
255 ///
256 /// This command uses a context-aware priority model to recommend a single task:
257 /// 1. First priority: Subtasks of the current focused task (depth-first)
258 /// 2. Second priority: Top-level tasks (breadth-first)
259 ///
260 /// The command is non-interactive and does not modify task status.
261 PickNext {
262 /// Output format (text or json)
263 #[arg(long, default_value = "text")]
264 format: String,
265 },
266
267 /// Create a subtask under current task and switch to it
268 SpawnSubtask {
269 /// Subtask name
270 #[arg(long)]
271 name: String,
272
273 /// Read spec from stdin
274 #[arg(long)]
275 spec_stdin: bool,
276 },
277
278 /// Switch to a specific task (atomic: update to doing + set current)
279 Switch {
280 /// Task ID
281 id: i64,
282 },
283
284 /// Add a dependency between tasks
285 ///
286 /// Creates a dependency where BLOCKED_TASK depends on BLOCKING_TASK.
287 /// The BLOCKING_TASK must be completed before BLOCKED_TASK can be started.
288 ///
289 /// Example: `task depends-on 42 41` means Task 42 depends on Task 41
290 /// (Task 41 must be done before Task 42 can start)
291 #[command(name = "depends-on")]
292 DependsOn {
293 /// Task ID that has the dependency (blocked task)
294 blocked_task_id: i64,
295
296 /// Task ID that must be completed first (blocking task)
297 blocking_task_id: i64,
298 },
299
300 /// Get task context (ancestors, siblings, children)
301 ///
302 /// Shows the full family tree of a task to understand its strategic context.
303 /// If no task ID is provided, uses the current focused task.
304 Context {
305 /// Task ID (optional, uses current task if omitted)
306 task_id: Option<i64>,
307 },
308}
309
310#[derive(Subcommand)]
311pub enum EventCommands {
312 /// Add a new event
313 Add {
314 /// Task ID (optional, uses current task if not specified)
315 #[arg(long)]
316 task_id: Option<i64>,
317
318 /// Log type
319 #[arg(long = "type")]
320 log_type: String,
321
322 /// Read discussion data from stdin
323 #[arg(long)]
324 data_stdin: bool,
325 },
326
327 /// List events for a task (or globally if task_id not specified)
328 List {
329 /// Task ID (optional, lists all events if not specified)
330 #[arg(long)]
331 task_id: Option<i64>,
332
333 /// Maximum number of events to return (default: 50)
334 #[arg(long)]
335 limit: Option<i64>,
336
337 /// Filter by log type (e.g., "decision", "blocker", "milestone", "note")
338 #[arg(long = "type")]
339 log_type: Option<String>,
340
341 /// Filter events created within duration (e.g., "7d", "24h", "30m")
342 #[arg(long)]
343 since: Option<String>,
344 },
345}