git_x/
cli.rs

1use clap::Parser;
2use clap_complete::Shell;
3
4#[derive(Parser)]
5pub struct Cli {
6    #[clap(subcommand)]
7    pub command: Commands,
8}
9
10#[derive(clap::Subcommand)]
11pub enum Commands {
12    #[clap(about = "Rename the current branch")]
13    RenameBranch {
14        #[clap(help = "New name for the current branch")]
15        new_name: String,
16    },
17    #[clap(about = "Delete merged local branches (except protected ones)")]
18    PruneBranches {
19        #[clap(
20            long = "except",
21            value_name = "branches",
22            help = "Comma-separated list of branches to exclude"
23        )]
24        except: Option<String>,
25        #[clap(long = "dry-run", help = "Show which branches would be deleted without actually deleting them", action = clap::ArgAction::SetTrue)]
26        dry_run: bool,
27    },
28    #[clap(about = "Show a high-level overview of the current repo")]
29    Info,
30    #[clap(about = "Pretty Git log with branches, remotes, and HEADs")]
31    Graph,
32    #[clap(about = "Colorized Git log with branches, remotes, and HEADs")]
33    ColorGraph,
34    #[clap(about = "Check repository health and show potential issues")]
35    Health,
36    #[clap(about = "Show commits since a reference (e.g., cb676ec, origin/main)")]
37    Since {
38        #[clap(help = "Reference point")]
39        reference: String,
40    },
41    #[clap(about = "Undo the last commit (without losing changes)")]
42    Undo,
43    #[clap(about = "Delete all fully merged local branches (except protected ones)")]
44    CleanBranches {
45        #[clap(long = "dry-run", help = "Prints the branches it would delete instead of actually deleting them", action = clap::ArgAction::SetTrue)]
46        dry_run: bool,
47    },
48    #[clap(about = "Show what’s different between this branch and another (default: main)")]
49    What {
50        #[clap(long = "target", help = "Branch to compare to")]
51        target: Option<String>,
52    },
53    #[clap(about = "Show a short, changelog-style summary of recent commits")]
54    Summary {
55        #[clap(
56            long = "since",
57            help = "Accepts flexible formats like \"yesterday\", \"3 days ago\", \"2025-07-01\", etc. (same as git log --since)"
58        )]
59        since: Option<String>,
60    },
61    #[clap(about = "Sync current branch with upstream (fetch + rebase)")]
62    Sync {
63        #[clap(long = "merge", help = "Use merge instead of rebase", action = clap::ArgAction::SetTrue)]
64        merge: bool,
65    },
66    #[clap(about = "Create and switch to a new branch")]
67    New {
68        #[clap(help = "Name of the new branch")]
69        branch_name: String,
70        #[clap(
71            long = "from",
72            help = "Base branch to create from (default: current branch)"
73        )]
74        from: Option<String>,
75    },
76    #[clap(about = "Find largest files in repository history")]
77    LargeFiles {
78        #[clap(long = "limit", default_value = "10", help = "Number of files to show")]
79        limit: usize,
80        #[clap(
81            long = "threshold",
82            help = "Minimum file size in MB (default: show all)"
83        )]
84        threshold: Option<f64>,
85    },
86    #[clap(about = "Create fixup commits for easier interactive rebasing")]
87    Fixup {
88        #[clap(help = "Commit hash to create fixup for")]
89        commit_hash: String,
90        #[clap(long = "rebase", help = "Automatically rebase with autosquash after creating fixup", action = clap::ArgAction::SetTrue)]
91        rebase: bool,
92    },
93    #[clap(about = "Advanced stash management with branch integration")]
94    StashBranch {
95        #[clap(subcommand)]
96        action: StashBranchAction,
97    },
98    #[clap(about = "Manage upstream branch relationships")]
99    Upstream {
100        #[clap(subcommand)]
101        action: UpstreamAction,
102    },
103    #[clap(about = "Interactive picker for recent branches")]
104    SwitchRecent,
105    #[clap(about = "Show contributor statistics for the repository")]
106    Contributors,
107    #[clap(about = "Analyze code complexity and technical debt metrics")]
108    TechnicalDebt,
109    #[clap(about = "Simplified bisect workflow")]
110    Bisect {
111        #[clap(subcommand)]
112        action: BisectAction,
113    },
114    #[clap(
115        name = "completion-install",
116        about = "Install shell completion to standard location"
117    )]
118    CompletionInstall {
119        #[clap(help = "Shell to install completion for")]
120        shell: Shell,
121    },
122}
123
124#[derive(clap::Subcommand)]
125pub enum StashBranchAction {
126    #[clap(about = "Create a new branch from a stash")]
127    Create {
128        #[clap(help = "Name for the new branch")]
129        branch_name: String,
130        #[clap(long = "stash", help = "Stash reference (default: latest stash)")]
131        stash_ref: Option<String>,
132    },
133    #[clap(about = "Clean old stashes")]
134    Clean {
135        #[clap(
136            long = "older-than",
137            help = "Remove stashes older than (e.g., '7d', '2w', '1m')"
138        )]
139        older_than: Option<String>,
140        #[clap(long = "dry-run", help = "Show what would be cleaned without doing it", action = clap::ArgAction::SetTrue)]
141        dry_run: bool,
142    },
143    #[clap(about = "Apply stashes from a specific branch")]
144    ApplyByBranch {
145        #[clap(help = "Branch name to filter stashes by")]
146        branch_name: String,
147        #[clap(long = "list", help = "List stashes instead of applying", action = clap::ArgAction::SetTrue)]
148        list_only: bool,
149    },
150    #[clap(about = "Interactive stash management with fuzzy search")]
151    Interactive,
152    #[clap(about = "Export stashes to patch files")]
153    Export {
154        #[clap(help = "Output directory for patch files")]
155        output_dir: String,
156        #[clap(
157            long = "stash",
158            help = "Specific stash to export (default: all stashes)"
159        )]
160        stash_ref: Option<String>,
161    },
162}
163
164#[derive(clap::Subcommand)]
165pub enum UpstreamAction {
166    #[clap(about = "Set upstream for current branch")]
167    Set {
168        #[clap(help = "Upstream branch reference (e.g., origin/main)")]
169        upstream: String,
170    },
171    #[clap(about = "Show upstream status for all branches")]
172    Status,
173    #[clap(about = "Sync all local branches with their upstreams")]
174    SyncAll {
175        #[clap(long = "dry-run", help = "Show what would be synced without doing it", action = clap::ArgAction::SetTrue
176        )]
177        dry_run: bool,
178        #[clap(long = "merge", help = "Use merge instead of rebase", action = clap::ArgAction::SetTrue
179        )]
180        merge: bool,
181    },
182}
183
184#[derive(clap::Subcommand)]
185pub enum BisectAction {
186    #[clap(about = "Start bisect session")]
187    Start {
188        #[clap(help = "Good commit reference")]
189        good: String,
190        #[clap(help = "Bad commit reference")]
191        bad: String,
192    },
193    #[clap(about = "Mark current commit as good")]
194    Good,
195    #[clap(about = "Mark current commit as bad")]
196    Bad,
197    #[clap(about = "Skip current commit (untestable)")]
198    Skip,
199    #[clap(about = "End bisect session")]
200    Reset,
201    #[clap(about = "Show bisect status")]
202    Status,
203}