Skip to main content

track/cli/
mod.rs

1//! Command-line interface definitions for the track CLI.
2//!
3//! This module defines the CLI structure using `clap`, including all commands,
4//! subcommands, and their arguments. The actual command handling logic is in the
5//! [`handler`] module.
6
7pub mod handler;
8pub mod handlers;
9
10use clap::{Parser, Subcommand, ValueEnum};
11
12/// Types of completion data that can be output
13#[derive(Debug, Clone, ValueEnum)]
14pub enum CompletionType {
15    /// Task IDs and names for 'track switch'
16    Tasks,
17    /// TODO IDs and content for current task
18    Todos,
19    /// Link IDs and URLs for current task
20    Links,
21    /// Repository IDs and paths for current task
22    Repos,
23}
24
25/// Main CLI structure for the track application.
26#[derive(Parser)]
27#[command(name = "track")]
28#[command(about = "WorkTracker CLI - Manage your development tasks and context", long_about = None)]
29pub struct Cli {
30    #[command(subcommand)]
31    pub command: Commands,
32}
33
34#[derive(Subcommand)]
35pub enum Commands {
36    /// Create a new task and switch to it
37    New {
38        /// Task name
39        name: String,
40
41        /// Task description
42        #[arg(short, long)]
43        description: Option<String>,
44
45        /// Ticket ID (e.g., PROJ-123, owner/repo/456)
46        #[arg(short, long)]
47        ticket: Option<String>,
48
49        /// Ticket URL
50        #[arg(long)]
51        ticket_url: Option<String>,
52
53        /// Template task reference (ID, ticket, or alias) to copy TODOs from
54        #[arg(long)]
55        template: Option<String>,
56    },
57
58    /// List tasks
59    List {
60        /// Include archived tasks
61        #[arg(short, long)]
62        all: bool,
63    },
64
65    /// Switch to a different task
66    Switch {
67        /// Task ID or ticket reference (e.g., 1 or t:PROJ-123)
68        task_ref: String,
69    },
70
71    /// Show detailed information about the current task
72    Status {
73        /// Task ID or ticket reference (e.g., 1 or t:PROJ-123)
74        id: Option<String>,
75
76        /// Output in JSON format
77        #[arg(short, long)]
78        json: bool,
79
80        /// Show all scraps
81        #[arg(short, long)]
82        all: bool,
83    },
84
85    /// View or set task description
86    Desc {
87        /// Description text (if omitted, displays current description)
88        description: Option<String>,
89
90        /// Target task ID (defaults to current task)
91        #[arg(short, long)]
92        task: Option<i64>,
93    },
94
95    /// Link a ticket to a task
96    Ticket {
97        /// Ticket ID
98        ticket_id: String,
99
100        /// Ticket URL
101        url: String,
102
103        /// Target task ID (defaults to current task)
104        #[arg(long)]
105        task: Option<i64>,
106    },
107
108    /// Archive a task
109    Archive {
110        /// Task ID or ticket reference (defaults to current task)
111        task_ref: Option<String>,
112    },
113
114    /// TODO management
115    #[command(subcommand)]
116    Todo(TodoCommands),
117
118    /// Link management
119    #[command(subcommand)]
120    Link(LinkCommands),
121
122    /// Scrap (work notes) management
123    #[command(subcommand)]
124    Scrap(ScrapCommands),
125
126    /// Sync repositories and setup task branches
127    Sync,
128
129    /// Repository management
130    #[command(subcommand)]
131    Repo(RepoCommands),
132
133    /// Task alias management
134    #[command(subcommand)]
135    Alias(AliasCommands),
136
137    /// Show help optimized for LLM agents
138    LlmHelp,
139
140    /// Generate shell completion script
141    Completion {
142        /// Shell to generate completions for
143        #[arg(value_enum)]
144        shell: clap_complete::Shell,
145
146        /// Generate dynamic completion script (with real-time data)
147        #[arg(short, long)]
148        dynamic: bool,
149    },
150
151    /// Output completion candidates (hidden, for shell completion scripts)
152    #[command(hide = true)]
153    #[command(name = "_complete")]
154    Complete {
155        /// Type of completion data to output
156        #[arg(value_enum)]
157        completion_type: CompletionType,
158    },
159
160    /// Configuration management
161    #[command(subcommand)]
162    Config(ConfigCommands),
163
164    /// Start web-based user interface
165    Webui {
166        /// Port to listen on
167        #[arg(short, long, default_value = "3000")]
168        port: u16,
169
170        /// Open browser automatically
171        #[arg(short, long)]
172        open: bool,
173    },
174}
175
176#[derive(Subcommand)]
177pub enum TodoCommands {
178    /// Add a new TODO
179    Add {
180        /// TODO content
181        text: String,
182
183        /// Create worktrees for this TODO
184        #[arg(short, long)]
185        worktree: bool,
186    },
187
188    /// List TODOs
189    List,
190
191    /// Update TODO status
192    Update {
193        /// TODO ID
194        id: i64,
195
196        /// New status (done or cancelled; reopen to pending is not allowed)
197        status: String,
198    },
199
200    /// Complete a TODO (merges worktree if exists)
201    Done {
202        /// TODO ID
203        id: i64,
204    },
205
206    /// Create or show worktrees for a TODO in the current repo
207    Workspace {
208        /// TODO ID
209        id: i64,
210
211        /// Recreate worktrees from the latest bookmark
212        #[arg(long)]
213        recreate: bool,
214
215        /// Force recreation even if uncommitted changes exist
216        #[arg(short, long)]
217        force: bool,
218
219        /// Operate on all registered repos for the task
220        #[arg(long)]
221        all: bool,
222    },
223
224    /// Delete a TODO
225    Delete {
226        /// TODO ID
227        id: i64,
228
229        /// Skip confirmation prompt
230        #[arg(short, long)]
231        force: bool,
232    },
233
234    /// Move a TODO to the front (make it the next todo to work on)
235    Next {
236        /// TODO ID
237        id: i64,
238    },
239}
240
241#[derive(Subcommand)]
242pub enum LinkCommands {
243    /// Add a new link
244    Add {
245        /// URL
246        url: String,
247
248        /// Link title (defaults to URL)
249        title: Option<String>,
250    },
251
252    /// List links
253    List,
254
255    /// Delete a link
256    Delete {
257        /// Link index (1-based)
258        index: usize,
259    },
260}
261
262#[derive(Subcommand)]
263pub enum ScrapCommands {
264    /// Add a new scrap (work note)
265    Add {
266        /// Scrap content
267        content: String,
268    },
269
270    /// List scraps
271    List,
272}
273
274#[derive(Subcommand)]
275pub enum RepoCommands {
276    /// Add a repository to the current task
277    Add {
278        /// Repository path (defaults to current directory)
279        path: Option<String>,
280
281        /// Base branch to use (defaults to current branch)
282        #[arg(short, long)]
283        base: Option<String>,
284    },
285
286    /// List repositories
287    List,
288
289    /// Remove a repository
290    Remove {
291        /// Repository ID
292        id: i64,
293    },
294}
295
296#[derive(Subcommand)]
297pub enum AliasCommands {
298    /// Set an alias for the current task
299    Set {
300        /// Alias name
301        alias: String,
302
303        /// Target task ID (defaults to current task)
304        #[arg(short, long)]
305        task: Option<i64>,
306
307        /// Force overwrite if alias already exists on another task
308        #[arg(short, long)]
309        force: bool,
310    },
311
312    /// Remove the alias from the current task
313    Remove {
314        /// Target task ID (defaults to current task)
315        #[arg(short, long)]
316        task: Option<i64>,
317    },
318}
319
320#[derive(Subcommand)]
321pub enum ConfigCommands {
322    /// Set a configuration value (e.g. vcs-mode jj|git)
323    Set {
324        /// Configuration key (e.g. vcs-mode)
325        key: String,
326
327        /// Configuration value
328        value: String,
329    },
330
331    /// Set Google Calendar ID for today task
332    SetCalendar {
333        /// Google Calendar ID
334        calendar_id: String,
335    },
336
337    /// Show current configuration
338    Show,
339}