rusty-commit 1.0.27

Rust-powered AI commit message generator - Write impressive commits in seconds
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
use clap::{Parser, Subcommand};

use crate::output::prelude::OutputFormat;

#[derive(Parser)]
#[command(
    name = "rco",
    version,
    author,
    about = "Rusty Commit - AI-powered commit message generator written in Rust 🚀🤖",
    after_help = r#"EXAMPLES:
    # Generate a commit message for staged changes
    rco

    # Generate with context and copy to clipboard
    rco -c "Focus on auth changes" --clipboard

    # Generate 3 variations and skip confirmation
    rco -g 3 -y

    # Use GitMoji format
    rco --fgm

    # Use a custom prompt file
    rco --prompt-file ~/.rco/prompts/my-prompt.md

    # Preview commit message without committing (dry-run)
    rco --dry-run

    # Open generated message in $EDITOR before committing
    rco --edit

    # Authenticate with Anthropic
    rco auth login

    # Setup git hooks
    rco hook set

    # Generate PR description
    rco pr generate --base main

    # List available skills
    rco skills list

    # Create a new skill
    rco skills create my-template --category template

    # Use a skill for commit generation
    rco --skill my-template

    # Generate shell completions
    rco completions bash
    rco completions zsh
    rco completions fish
"#
)]
pub struct Cli {
    #[command(subcommand)]
    pub command: Option<Commands>,

    #[command(flatten)]
    pub global: GlobalOptions,
}

#[derive(Parser, Clone)]
pub struct GlobalOptions {
    /// Use full GitMoji specification
    #[arg(long = "fgm", default_value = "false")]
    pub full_gitmoji: bool,

    /// Additional user input context for the commit message
    #[arg(short = 'c', long = "context")]
    pub context: Option<String>,

    /// Skip commit confirmation prompt
    #[arg(short = 'y', long = "yes", default_value = "false")]
    pub skip_confirmation: bool,

    /// Show the prompt that would be used without generating commit
    #[arg(long = "show-prompt", default_value = "false")]
    pub show_prompt: bool,

    /// Disable running pre-hooks
    #[arg(long = "no-pre-hooks", default_value = "false")]
    pub no_pre_hooks: bool,

    /// Disable running post-hooks
    #[arg(long = "no-post-hooks", default_value = "false")]
    pub no_post_hooks: bool,

    /// Number of commit message variations to generate (1-5)
    #[arg(short = 'g', long = "generate", default_value = "1")]
    pub generate_count: u8,

    /// Copy generated message to clipboard instead of committing
    #[arg(short = 'C', long = "clipboard", default_value = "false")]
    pub clipboard: bool,

    /// Exclude specific files from the diff sent to AI
    #[arg(short = 'x', long = "exclude")]
    pub exclude_files: Option<Vec<String>>,

    /// Show detailed timing information
    #[arg(long = "timing", default_value = "false")]
    pub timing: bool,

    /// Strip <thinking> tags from AI responses (for reasoning models)
    #[arg(long = "strip-thinking", default_value = "false")]
    pub strip_thinking: bool,

    /// Output commit message to stdout instead of committing (for hooks)
    #[arg(long = "print", default_value = "false")]
    pub print_message: bool,

    /// Output format (pretty, json, markdown)
    #[arg(long = "output-format", default_value = "pretty")]
    pub output_format: OutputFormat,

    /// Use a custom prompt template file
    #[arg(long = "prompt-file")]
    pub prompt_file: Option<String>,

    /// Preview the generated commit message without committing (dry-run mode)
    #[arg(long = "dry-run", default_value = "false")]
    pub dry_run: bool,

    /// Open the generated message in $EDITOR before committing
    #[arg(short = 'e', long = "edit", default_value = "false")]
    pub edit: bool,

    /// Use a specific skill for commit generation
    #[arg(long = "skill")]
    pub skill: Option<String>,
}

#[derive(Parser)]
pub struct SetupCommand {
    /// Skip interactive prompts and use defaults
    #[arg(long, default_value = "false")]
    pub defaults: bool,

    /// Run advanced setup with all configuration options
    #[arg(long, default_value = "false")]
    pub advanced: bool,
}

#[derive(Subcommand)]
pub enum Commands {
    /// Manage Rusty Commit configuration
    Config(ConfigCommand),

    /// Setup git hooks
    Hook(HookCommand),

    /// Generate commitlint configuration
    #[command(name = "commitlint")]
    CommitLint(CommitLintCommand),

    /// Authenticate with Claude using OAuth
    Auth(AuthCommand),

    /// Start MCP (Model Context Protocol) server
    Mcp(McpCommand),

    /// Check for updates and update rusty-commit
    Update(UpdateCommand),

    /// Generate PR description
    Pr(PrCommand),

    /// Interactive model selection
    Model(ModelCommand),

    /// Interactive setup wizard
    Setup(SetupCommand),

    /// Generate shell completions
    Completions(CompletionsCommand),

    /// Manage skills (custom templates, analyzers, formatters)
    Skills(SkillsCommand),
}

#[derive(Parser)]
pub struct PrCommand {
    #[command(subcommand)]
    pub action: PrAction,
}

#[derive(Subcommand)]
pub enum PrAction {
    /// Generate a PR description
    Generate {
        /// Base branch to compare against (default: main)
        #[arg(short, long)]
        base: Option<String>,
    },
    /// Open PR creation page in browser
    Browse {
        /// Base branch to compare against (default: main)
        #[arg(short, long)]
        base: Option<String>,
    },
}

#[derive(Parser)]
pub struct ConfigCommand {
    #[command(subcommand)]
    pub action: ConfigAction,
}

#[derive(Subcommand)]
pub enum ConfigAction {
    /// Set a configuration value
    Set {
        /// Configuration key=value pairs
        #[arg(required = true)]
        pairs: Vec<String>,
    },
    /// Get a configuration value
    Get {
        /// Configuration key
        key: String,
    },
    /// Reset configuration to defaults
    Reset {
        /// Reset all configuration
        #[arg(long)]
        all: bool,
        /// Specific keys to reset
        keys: Vec<String>,
    },
    /// Show secure storage status
    Status,
    /// Describe all configuration options with examples and descriptions
    Describe,
    /// Add a new provider account
    AddProvider {
        /// Provider to add (openai, anthropic, claude-code, qwen, ollama, xai, gemini, perplexity, azure, mlx, nvidia, and many more)
        #[arg(short, long)]
        provider: Option<String>,
        /// Account alias (e.g., "work", "personal")
        #[arg(short, long)]
        alias: Option<String>,
    },
    /// List all configured accounts
    ListAccounts,
    /// Switch to a different account
    UseAccount {
        /// Account alias to use
        alias: String,
    },
    /// Remove an account
    RemoveAccount {
        /// Account alias to remove
        alias: String,
    },
    /// Show account details
    ShowAccount {
        /// Account alias (defaults to "default")
        alias: Option<String>,
    },
}

#[derive(Parser)]
pub struct HookCommand {
    #[command(subcommand)]
    pub action: HookAction,
}

#[derive(Subcommand)]
pub enum HookAction {
    /// Install prepare-commit-msg git hook
    PrepareCommitMsg,
    /// Install commit-msg git hook (non-interactive)
    CommitMsg,
    /// Uninstall git hooks
    Unset,
    /// Install or uninstall pre-commit hooks
    Precommit {
        /// Install pre-commit hooks
        #[arg(long)]
        set: bool,
        /// Uninstall pre-commit hooks
        #[arg(long)]
        unset: bool,
    },
}

#[derive(Parser)]
pub struct CommitLintCommand {
    /// Set configuration non-interactively
    #[arg(long)]
    pub set: bool,
}

#[derive(Parser)]
pub struct AuthCommand {
    #[command(subcommand)]
    pub action: AuthAction,
}

#[derive(Subcommand)]
pub enum AuthAction {
    /// Login with Claude OAuth
    Login,
    /// Logout and remove stored tokens
    Logout,
    /// Check authentication status
    Status,
}

#[derive(Parser)]
pub struct McpCommand {
    #[command(subcommand)]
    pub action: McpAction,
}

#[derive(Subcommand)]
pub enum McpAction {
    /// Start MCP server on TCP port (for Cursor integration)
    Server {
        /// Port to listen on
        #[arg(short, long, default_value = "3000")]
        port: Option<u16>,
    },
    /// Start MCP server over STDIO (for direct integration)
    Stdio,
}

#[derive(Parser)]
pub struct UpdateCommand {
    /// Check for updates without installing
    #[arg(short, long)]
    pub check: bool,

    /// Force update even if already on latest version
    #[arg(short, long)]
    pub force: bool,

    /// Specify version to update to (e.g., "1.0.2")
    #[arg(short, long)]
    pub version: Option<String>,
}

#[derive(Parser)]
pub struct ModelCommand {
    /// List available models for current provider
    #[arg(long = "list")]
    pub list: bool,
    /// Specify provider to list models for
    #[arg(short, long)]
    pub provider: Option<String>,
}

#[derive(Parser)]
pub struct CompletionsCommand {
    /// Shell to generate completions for
    #[arg(value_enum)]
    pub shell: clap_complete::Shell,
}

#[derive(Parser)]
pub struct SkillsCommand {
    #[command(subcommand)]
    pub action: SkillsAction,
}

#[derive(Subcommand)]
pub enum SkillsAction {
    /// List all available skills
    List {
        /// Filter by category
        #[arg(short, long)]
        category: Option<String>,
    },
    /// Create a new skill from template
    Create {
        /// Skill name
        name: String,
        /// Skill category
        #[arg(short, long, default_value = "template")]
        category: String,
        /// Create as a project-level skill (in .rco/skills/)
        #[arg(short, long, default_value = "false")]
        project: bool,
    },
    /// Show skill details
    Show {
        /// Skill name
        name: String,
    },
    /// Remove a skill
    Remove {
        /// Skill name
        name: String,
        /// Force removal without confirmation
        #[arg(short, long)]
        force: bool,
    },
    /// Open skill directory in default editor/file manager
    Open,
    /// Import skills from external sources (claude-code, github, gist, url)
    Import {
        /// Source to import from (claude-code, github:owner/repo, gist:id, or URL)
        source: String,
        /// Specific skill name to import (optional, imports all if not specified)
        #[arg(short, long)]
        name: Option<String>,
    },
    /// List available external skills without importing
    Available {
        /// External source to check (claude-code)
        #[arg(default_value = "claude-code")]
        source: String,
    },
}