cli.rs

  1use clap::{Parser, Subcommand};
  2
  3#[derive(Parser)]
  4#[command(name = "td", version, about = "Todo tracker for AI agents")]
  5pub struct Cli {
  6    /// Output JSON
  7    #[arg(short = 'j', long = "json", global = true)]
  8    pub json: bool,
  9
 10    #[command(subcommand)]
 11    pub command: Command,
 12}
 13
 14#[derive(Subcommand)]
 15pub enum Command {
 16    /// Initialize .td directory
 17    Init {
 18        /// Add .td/ to .gitignore
 19        #[arg(long)]
 20        stealth: bool,
 21    },
 22
 23    /// Create a new task
 24    #[command(visible_alias = "add")]
 25    Create {
 26        /// Task title
 27        title: Option<String>,
 28
 29        /// Priority level (1=high, 2=medium, 3=low)
 30        #[arg(short, long, default_value_t = 2)]
 31        priority: i32,
 32
 33        /// Effort level (1=low, 2=medium, 3=high)
 34        #[arg(short, long, default_value_t = 2)]
 35        effort: i32,
 36
 37        /// Task type
 38        #[arg(short = 't', long = "type", default_value = "task")]
 39        task_type: String,
 40
 41        /// Description
 42        #[arg(short = 'd', long = "desc")]
 43        desc: Option<String>,
 44
 45        /// Parent task ID (creates a subtask)
 46        #[arg(long)]
 47        parent: Option<String>,
 48
 49        /// Labels (comma-separated)
 50        #[arg(short, long)]
 51        labels: Option<String>,
 52    },
 53
 54    /// List tasks
 55    #[command(visible_alias = "ls")]
 56    List {
 57        /// Filter by status
 58        #[arg(short, long)]
 59        status: Option<String>,
 60
 61        /// Filter by priority
 62        #[arg(short, long)]
 63        priority: Option<i32>,
 64
 65        /// Filter by label
 66        #[arg(short, long)]
 67        label: Option<String>,
 68    },
 69
 70    /// Show task details
 71    Show {
 72        /// Task ID
 73        id: String,
 74    },
 75
 76    /// Update a task
 77    Update {
 78        /// Task ID
 79        id: String,
 80
 81        /// Set status
 82        #[arg(short, long)]
 83        status: Option<String>,
 84
 85        /// Set priority
 86        #[arg(short, long)]
 87        priority: Option<i32>,
 88
 89        /// Set title
 90        #[arg(short = 't', long)]
 91        title: Option<String>,
 92
 93        /// Set description
 94        #[arg(short = 'd', long = "desc")]
 95        desc: Option<String>,
 96    },
 97
 98    /// Mark task(s) as closed
 99    #[command(visible_alias = "close")]
100    Done {
101        /// Task IDs
102        #[arg(required = true)]
103        ids: Vec<String>,
104    },
105
106    /// Reopen task(s)
107    Reopen {
108        /// Task IDs
109        #[arg(required = true)]
110        ids: Vec<String>,
111    },
112
113    /// Manage dependencies / blockers
114    Dep {
115        #[command(subcommand)]
116        action: DepAction,
117    },
118
119    /// Manage labels
120    Label {
121        #[command(subcommand)]
122        action: LabelAction,
123    },
124
125    /// Search tasks by title or description
126    Search {
127        /// Search query
128        query: String,
129    },
130
131    /// Show tasks with no open blockers
132    Ready,
133
134    /// Show task statistics (always JSON)
135    Stats,
136
137    /// Vacuum the database
138    Compact,
139
140    /// Export tasks to JSONL (one JSON object per line)
141    Export,
142
143    /// Import tasks from a JSONL file
144    Import {
145        /// Path to JSONL file (- for stdin)
146        file: String,
147    },
148
149    /// Install the agent skill file (SKILL.md)
150    Skill {
151        /// Skills directory (writes managing-tasks-with-td/SKILL.md inside)
152        #[arg(long)]
153        dir: Option<String>,
154    },
155}
156
157#[derive(Subcommand)]
158pub enum DepAction {
159    /// Add a dependency (child is blocked by parent)
160    Add {
161        /// Task that is blocked
162        child: String,
163        /// Task that blocks it
164        parent: String,
165    },
166    /// Remove a dependency
167    Rm {
168        /// Task that was blocked
169        child: String,
170        /// Task that was blocking
171        parent: String,
172    },
173    /// Show child tasks
174    Tree {
175        /// Parent task ID
176        id: String,
177    },
178}
179
180#[derive(Subcommand)]
181pub enum LabelAction {
182    /// Add a label to a task
183    Add {
184        /// Task ID
185        id: String,
186        /// Label to add
187        label: String,
188    },
189    /// Remove a label from a task
190    Rm {
191        /// Task ID
192        id: String,
193        /// Label to remove
194        label: String,
195    },
196    /// List labels on a task
197    List {
198        /// Task ID
199        id: String,
200    },
201    /// List all distinct labels
202    ListAll,
203}