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 /// Restore session context for AI agents (Focus Restoration - Phase 1)
64 ///
65 /// This command returns all context needed to restore work continuity:
66 /// - Current focused task
67 /// - Parent task and siblings progress
68 /// - Child tasks status
69 /// - Recent events (decisions, blockers, notes)
70 /// - Suggested next commands
71 ///
72 /// Designed for SessionStart hooks to inject context at the beginning of new sessions.
73 #[command(name = "session-restore")]
74 SessionRestore {
75 /// Number of recent events to include (default: 3)
76 #[arg(long, default_value = "3")]
77 include_events: usize,
78
79 /// Workspace path (default: current directory)
80 #[arg(long)]
81 workspace: Option<String>,
82 },
83
84 /// Setup Claude Code integration (install SessionStart hook)
85 ///
86 /// Automatically configures .claude/hooks/session-start.sh to enable
87 /// focus restoration on every new Claude Code session.
88 #[command(name = "setup-claude-code")]
89 SetupClaudeCode {
90 /// Show what would be done without actually doing it
91 #[arg(long)]
92 dry_run: bool,
93
94 /// Specify .claude directory location (default: ./.claude)
95 #[arg(long)]
96 claude_dir: Option<String>,
97
98 /// Overwrite existing hook
99 #[arg(long)]
100 force: bool,
101 },
102}
103
104#[derive(Subcommand)]
105pub enum TaskCommands {
106 /// Add a new task
107 Add {
108 /// Task name
109 #[arg(long)]
110 name: String,
111
112 /// Parent task ID
113 #[arg(long)]
114 parent: Option<i64>,
115
116 /// Read spec from stdin
117 #[arg(long)]
118 spec_stdin: bool,
119 },
120
121 /// Get a task by ID
122 Get {
123 /// Task ID
124 id: i64,
125
126 /// Include events summary
127 #[arg(long)]
128 with_events: bool,
129 },
130
131 /// Update a task
132 Update {
133 /// Task ID
134 id: i64,
135
136 /// New task name
137 #[arg(long)]
138 name: Option<String>,
139
140 /// New parent task ID
141 #[arg(long)]
142 parent: Option<i64>,
143
144 /// New status
145 #[arg(long)]
146 status: Option<String>,
147
148 /// Task complexity (1-10)
149 #[arg(long)]
150 complexity: Option<i32>,
151
152 /// Task priority (critical, high, medium, low)
153 #[arg(long)]
154 priority: Option<String>,
155
156 /// Read spec from stdin
157 #[arg(long)]
158 spec_stdin: bool,
159 },
160
161 /// Delete a task
162 Del {
163 /// Task ID
164 id: i64,
165 },
166
167 /// List tasks with filters
168 List {
169 /// Filter by status
170 #[arg(long)]
171 status: Option<String>,
172
173 /// Filter by parent ID (use "null" for no parent)
174 #[arg(long)]
175 parent: Option<String>,
176 },
177
178 /// Find tasks with filters (deprecated: use 'list' instead)
179 #[command(hide = true)]
180 Find {
181 /// Filter by status
182 #[arg(long)]
183 status: Option<String>,
184
185 /// Filter by parent ID (use "null" for no parent)
186 #[arg(long)]
187 parent: Option<String>,
188 },
189
190 /// Start a task (atomic: update status + set current)
191 Start {
192 /// Task ID
193 id: i64,
194
195 /// Include events summary
196 #[arg(long)]
197 with_events: bool,
198 },
199
200 /// Complete the current focused task (atomic: check children + update status + clear current)
201 /// This command only operates on the current_task_id. It will:
202 /// - Check all subtasks are done
203 /// - Update the task status to done
204 /// - Clear the current_task_id
205 ///
206 /// Prerequisites: A task must be set as current (via `current --set <ID>`)
207 Done,
208
209 /// Intelligently recommend the next task to work on
210 ///
211 /// This command uses a context-aware priority model to recommend a single task:
212 /// 1. First priority: Subtasks of the current focused task (depth-first)
213 /// 2. Second priority: Top-level tasks (breadth-first)
214 ///
215 /// The command is non-interactive and does not modify task status.
216 PickNext {
217 /// Output format (text or json)
218 #[arg(long, default_value = "text")]
219 format: String,
220 },
221
222 /// Create a subtask under current task and switch to it
223 SpawnSubtask {
224 /// Subtask name
225 #[arg(long)]
226 name: String,
227
228 /// Read spec from stdin
229 #[arg(long)]
230 spec_stdin: bool,
231 },
232
233 /// Switch to a specific task (atomic: update to doing + set current)
234 Switch {
235 /// Task ID
236 id: i64,
237 },
238
239 /// Search tasks by content using full-text search
240 Search {
241 /// Search query (supports FTS5 syntax like "bug AND NOT critical")
242 query: String,
243 },
244
245 /// Add a dependency between tasks
246 ///
247 /// Creates a dependency where BLOCKED_TASK depends on BLOCKING_TASK.
248 /// The BLOCKING_TASK must be completed before BLOCKED_TASK can be started.
249 ///
250 /// Example: `task depends-on 42 41` means Task 42 depends on Task 41
251 /// (Task 41 must be done before Task 42 can start)
252 #[command(name = "depends-on")]
253 DependsOn {
254 /// Task ID that has the dependency (blocked task)
255 blocked_task_id: i64,
256
257 /// Task ID that must be completed first (blocking task)
258 blocking_task_id: i64,
259 },
260}
261
262#[derive(Subcommand)]
263pub enum EventCommands {
264 /// Add a new event
265 Add {
266 /// Task ID (optional, uses current task if not specified)
267 #[arg(long)]
268 task_id: Option<i64>,
269
270 /// Log type
271 #[arg(long = "type")]
272 log_type: String,
273
274 /// Read discussion data from stdin
275 #[arg(long)]
276 data_stdin: bool,
277 },
278
279 /// List events for a task
280 List {
281 /// Task ID
282 #[arg(long)]
283 task_id: i64,
284
285 /// Maximum number of events to return
286 #[arg(long)]
287 limit: Option<i64>,
288
289 /// Filter by log type (e.g., "decision", "blocker", "milestone", "note")
290 #[arg(long = "type")]
291 log_type: Option<String>,
292
293 /// Filter events created within duration (e.g., "7d", "24h", "30m")
294 #[arg(long)]
295 since: Option<String>,
296 },
297}