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