1use clap::{Parser, Subcommand};
2
3use crate::output::prelude::OutputFormat;
4
5#[derive(Parser)]
6#[command(
7 name = "rco",
8 version,
9 author,
10 about = "Rusty Commit - AI-powered commit message generator written in Rust 🚀🤖",
11 after_help = r#"EXAMPLES:
12 # Generate a commit message for staged changes
13 rco
14
15 # Generate with context and copy to clipboard
16 rco -c "Focus on auth changes" --clipboard
17
18 # Generate 3 variations and skip confirmation
19 rco -g 3 -y
20
21 # Use GitMoji format
22 rco --fgm
23
24 # Use a custom prompt file
25 rco --prompt-file ~/.rco/prompts/my-prompt.md
26
27 # Preview commit message without committing (dry-run)
28 rco --dry-run
29
30 # Open generated message in $EDITOR before committing
31 rco --edit
32
33 # Authenticate with Anthropic
34 rco auth login
35
36 # Setup git hooks
37 rco hook set
38
39 # Generate PR description
40 rco pr generate --base main
41
42 # List available skills
43 rco skills list
44
45 # Create a new skill
46 rco skills create my-template --category template
47
48 # Use a skill for commit generation
49 rco --skill my-template
50
51 # Generate shell completions
52 rco completions bash
53 rco completions zsh
54 rco completions fish
55"#
56)]
57pub struct Cli {
58 #[command(subcommand)]
59 pub command: Option<Commands>,
60
61 #[command(flatten)]
62 pub global: GlobalOptions,
63}
64
65#[derive(Parser, Clone)]
66pub struct GlobalOptions {
67 #[arg(long = "fgm", default_value = "false")]
69 pub full_gitmoji: bool,
70
71 #[arg(short = 'c', long = "context")]
73 pub context: Option<String>,
74
75 #[arg(short = 'y', long = "yes", default_value = "false")]
77 pub skip_confirmation: bool,
78
79 #[arg(long = "show-prompt", default_value = "false")]
81 pub show_prompt: bool,
82
83 #[arg(long = "no-pre-hooks", default_value = "false")]
85 pub no_pre_hooks: bool,
86
87 #[arg(long = "no-post-hooks", default_value = "false")]
89 pub no_post_hooks: bool,
90
91 #[arg(short = 'g', long = "generate", default_value = "1")]
93 pub generate_count: u8,
94
95 #[arg(short = 'C', long = "clipboard", default_value = "false")]
97 pub clipboard: bool,
98
99 #[arg(short = 'x', long = "exclude")]
101 pub exclude_files: Option<Vec<String>>,
102
103 #[arg(long = "timing", default_value = "false")]
105 pub timing: bool,
106
107 #[arg(long = "strip-thinking", default_value = "false")]
109 pub strip_thinking: bool,
110
111 #[arg(long = "print", default_value = "false")]
113 pub print_message: bool,
114
115 #[arg(long = "output-format", default_value = "pretty")]
117 pub output_format: OutputFormat,
118
119 #[arg(long = "prompt-file")]
121 pub prompt_file: Option<String>,
122
123 #[arg(long = "dry-run", default_value = "false")]
125 pub dry_run: bool,
126
127 #[arg(short = 'e', long = "edit", default_value = "false")]
129 pub edit: bool,
130
131 #[arg(long = "skill")]
133 pub skill: Option<String>,
134}
135
136#[derive(Parser)]
137pub struct SetupCommand {
138 #[arg(long, default_value = "false")]
140 pub defaults: bool,
141
142 #[arg(long, default_value = "false")]
144 pub advanced: bool,
145}
146
147#[derive(Subcommand)]
148pub enum Commands {
149 Config(ConfigCommand),
151
152 Hook(HookCommand),
154
155 #[command(name = "commitlint")]
157 CommitLint(CommitLintCommand),
158
159 Auth(AuthCommand),
161
162 Mcp(McpCommand),
164
165 Update(UpdateCommand),
167
168 Pr(PrCommand),
170
171 Model(ModelCommand),
173
174 Setup(SetupCommand),
176
177 Completions(CompletionsCommand),
179
180 Skills(SkillsCommand),
182}
183
184#[derive(Parser)]
185pub struct PrCommand {
186 #[command(subcommand)]
187 pub action: PrAction,
188}
189
190#[derive(Subcommand)]
191pub enum PrAction {
192 Generate {
194 #[arg(short, long)]
196 base: Option<String>,
197 },
198 Browse {
200 #[arg(short, long)]
202 base: Option<String>,
203 },
204}
205
206#[derive(Parser)]
207pub struct ConfigCommand {
208 #[command(subcommand)]
209 pub action: ConfigAction,
210}
211
212#[derive(Subcommand)]
213pub enum ConfigAction {
214 Set {
216 #[arg(required = true)]
218 pairs: Vec<String>,
219 },
220 Get {
222 key: String,
224 },
225 Reset {
227 #[arg(long)]
229 all: bool,
230 keys: Vec<String>,
232 },
233 Status,
235 Describe,
237 AddProvider {
239 #[arg(short, long)]
241 provider: Option<String>,
242 #[arg(short, long)]
244 alias: Option<String>,
245 },
246 ListAccounts,
248 UseAccount {
250 alias: String,
252 },
253 RemoveAccount {
255 alias: String,
257 },
258 ShowAccount {
260 alias: Option<String>,
262 },
263}
264
265#[derive(Parser)]
266pub struct HookCommand {
267 #[command(subcommand)]
268 pub action: HookAction,
269}
270
271#[derive(Subcommand)]
272pub enum HookAction {
273 PrepareCommitMsg,
275 CommitMsg,
277 Unset,
279 Precommit {
281 #[arg(long)]
283 set: bool,
284 #[arg(long)]
286 unset: bool,
287 },
288}
289
290#[derive(Parser)]
291pub struct CommitLintCommand {
292 #[arg(long)]
294 pub set: bool,
295}
296
297#[derive(Parser)]
298pub struct AuthCommand {
299 #[command(subcommand)]
300 pub action: AuthAction,
301}
302
303#[derive(Subcommand)]
304pub enum AuthAction {
305 Login,
307 Logout,
309 Status,
311}
312
313#[derive(Parser)]
314pub struct McpCommand {
315 #[command(subcommand)]
316 pub action: McpAction,
317}
318
319#[derive(Subcommand)]
320pub enum McpAction {
321 Server {
323 #[arg(short, long, default_value = "3000")]
325 port: Option<u16>,
326 },
327 Stdio,
329}
330
331#[derive(Parser)]
332pub struct UpdateCommand {
333 #[arg(short, long)]
335 pub check: bool,
336
337 #[arg(short, long)]
339 pub force: bool,
340
341 #[arg(short, long)]
343 pub version: Option<String>,
344}
345
346#[derive(Parser)]
347pub struct ModelCommand {
348 #[arg(long = "list")]
350 pub list: bool,
351 #[arg(short, long)]
353 pub provider: Option<String>,
354}
355
356#[derive(Parser)]
357pub struct CompletionsCommand {
358 #[arg(value_enum)]
360 pub shell: clap_complete::Shell,
361}
362
363#[derive(Parser)]
364pub struct SkillsCommand {
365 #[command(subcommand)]
366 pub action: SkillsAction,
367}
368
369#[derive(Subcommand)]
370pub enum SkillsAction {
371 List {
373 #[arg(short, long)]
375 category: Option<String>,
376 },
377 Create {
379 name: String,
381 #[arg(short, long, default_value = "template")]
383 category: String,
384 #[arg(short, long, default_value = "false")]
386 project: bool,
387 },
388 Show {
390 name: String,
392 },
393 Remove {
395 name: String,
397 #[arg(short, long)]
399 force: bool,
400 },
401 Open,
403 Import {
405 source: String,
407 #[arg(short, long)]
409 name: Option<String>,
410 },
411 Available {
413 #[arg(default_value = "claude-code")]
415 source: String,
416 },
417}