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 /// Unified setup command for AI tool integrations
85 ///
86 /// This command provides a unified interface for setting up intent-engine integration
87 /// with various AI assistant tools. It handles both hook installation and MCP server
88 /// configuration in one step.
89 ///
90 /// Features:
91 /// - User-level or project-level installation
92 /// - Atomic setup with rollback on failure
93 /// - Built-in connectivity testing
94 /// - Diagnosis mode for troubleshooting
95 Setup {
96 /// Target tool to configure (claude-code, gemini-cli, codex)
97 #[arg(long)]
98 target: Option<String>,
99
100 /// Installation scope: user (default, recommended), project, or both
101 #[arg(long, default_value = "user")]
102 scope: String,
103
104 /// Show what would be done without actually doing it
105 #[arg(long)]
106 dry_run: bool,
107
108 /// Overwrite existing configuration
109 #[arg(long)]
110 force: bool,
111
112 /// Run diagnosis on existing setup instead of installing
113 #[arg(long)]
114 diagnose: bool,
115
116 /// Custom config file path (advanced)
117 #[arg(long)]
118 config_path: Option<String>,
119
120 /// Project directory for INTENT_ENGINE_PROJECT_DIR env var
121 #[arg(long)]
122 project_dir: Option<String>,
123 },
124}
125
126#[derive(Subcommand)]
127pub enum TaskCommands {
128 /// Add a new task
129 Add {
130 /// Task name
131 #[arg(long)]
132 name: String,
133
134 /// Parent task ID
135 #[arg(long)]
136 parent: Option<i64>,
137
138 /// Read spec from stdin
139 #[arg(long)]
140 spec_stdin: bool,
141 },
142
143 /// Get a task by ID
144 Get {
145 /// Task ID
146 id: i64,
147
148 /// Include events summary
149 #[arg(long)]
150 with_events: bool,
151 },
152
153 /// Update a task
154 Update {
155 /// Task ID
156 id: i64,
157
158 /// New task name
159 #[arg(long)]
160 name: Option<String>,
161
162 /// New parent task ID
163 #[arg(long)]
164 parent: Option<i64>,
165
166 /// New status
167 #[arg(long)]
168 status: Option<String>,
169
170 /// Task complexity (1-10)
171 #[arg(long)]
172 complexity: Option<i32>,
173
174 /// Task priority (critical, high, medium, low)
175 #[arg(long)]
176 priority: Option<String>,
177
178 /// Read spec from stdin
179 #[arg(long)]
180 spec_stdin: bool,
181 },
182
183 /// Delete a task
184 Del {
185 /// Task ID
186 id: i64,
187 },
188
189 /// List tasks with filters
190 List {
191 /// Filter by status
192 #[arg(long)]
193 status: Option<String>,
194
195 /// Filter by parent ID (use "null" for no parent)
196 #[arg(long)]
197 parent: Option<String>,
198 },
199
200 /// Start a task (atomic: update status + set current)
201 Start {
202 /// Task ID
203 id: i64,
204
205 /// Include events summary
206 #[arg(long)]
207 with_events: bool,
208 },
209
210 /// Complete the current focused task (atomic: check children + update status + clear current)
211 /// This command only operates on the current_task_id. It will:
212 /// - Check all subtasks are done
213 /// - Update the task status to done
214 /// - Clear the current_task_id
215 ///
216 /// Prerequisites: A task must be set as current (via `current --set <ID>`)
217 Done,
218
219 /// Intelligently recommend the next task to work on
220 ///
221 /// This command uses a context-aware priority model to recommend a single task:
222 /// 1. First priority: Subtasks of the current focused task (depth-first)
223 /// 2. Second priority: Top-level tasks (breadth-first)
224 ///
225 /// The command is non-interactive and does not modify task status.
226 PickNext {
227 /// Output format (text or json)
228 #[arg(long, default_value = "text")]
229 format: String,
230 },
231
232 /// Create a subtask under current task and switch to it
233 SpawnSubtask {
234 /// Subtask name
235 #[arg(long)]
236 name: String,
237
238 /// Read spec from stdin
239 #[arg(long)]
240 spec_stdin: bool,
241 },
242
243 /// Switch to a specific task (atomic: update to doing + set current)
244 Switch {
245 /// Task ID
246 id: i64,
247 },
248
249 /// Search tasks by content using full-text search
250 Search {
251 /// Search query (supports FTS5 syntax like "bug AND NOT critical")
252 query: String,
253 },
254
255 /// Add a dependency between tasks
256 ///
257 /// Creates a dependency where BLOCKED_TASK depends on BLOCKING_TASK.
258 /// The BLOCKING_TASK must be completed before BLOCKED_TASK can be started.
259 ///
260 /// Example: `task depends-on 42 41` means Task 42 depends on Task 41
261 /// (Task 41 must be done before Task 42 can start)
262 #[command(name = "depends-on")]
263 DependsOn {
264 /// Task ID that has the dependency (blocked task)
265 blocked_task_id: i64,
266
267 /// Task ID that must be completed first (blocking task)
268 blocking_task_id: i64,
269 },
270}
271
272#[derive(Subcommand)]
273pub enum EventCommands {
274 /// Add a new event
275 Add {
276 /// Task ID (optional, uses current task if not specified)
277 #[arg(long)]
278 task_id: Option<i64>,
279
280 /// Log type
281 #[arg(long = "type")]
282 log_type: String,
283
284 /// Read discussion data from stdin
285 #[arg(long)]
286 data_stdin: bool,
287 },
288
289 /// List events for a task
290 List {
291 /// Task ID
292 #[arg(long)]
293 task_id: i64,
294
295 /// Maximum number of events to return
296 #[arg(long)]
297 limit: Option<i64>,
298
299 /// Filter by log type (e.g., "decision", "blocker", "milestone", "note")
300 #[arg(long = "type")]
301 log_type: Option<String>,
302
303 /// Filter events created within duration (e.g., "7d", "24h", "30m")
304 #[arg(long)]
305 since: Option<String>,
306 },
307}