1use clap::{Args, Parser, Subcommand, ValueEnum};
18
19use super::{
20 app, cleanup, color::ColorArg, completions, config, context, daemon, doctor, init, machine,
21 migrate, plugin, prd, productivity, prompt, queue, run, runner, scan, task, tutorial, undo,
22 version, watch, webhook,
23};
24
25#[derive(Parser)]
26#[command(name = "ralph")]
27#[command(about = "Ralph")]
28#[command(version)]
29#[command(after_long_help = r#"Runner selection:
30 - CLI flags override project config, which overrides global config, which overrides built-in defaults.
31 - Default runner/model come from config files: project config (.ralph/config.jsonc) > global config (~/.config/ralph/config.jsonc) > built-in.
32 - `task` and `scan` accept --runner/--model/--effort as one-off overrides.
33 - `run one` and `run loop` accept --runner/--model/--effort as one-off overrides; otherwise they use task.agent overrides when present; otherwise config agent defaults.
34
35Config example (.ralph/config.jsonc):
36 {
37 "version": 2,
38 "agent": {
39 "runner": "codex",
40 "model": "gpt-5.4",
41 "codex_bin": "codex",
42 "gemini_bin": "gemini",
43 "claude_bin": "claude"
44 }
45 }
46
47Notes:
48 - Allowed runners: codex, opencode, gemini, claude, cursor, kimi, pi
49 - Allowed models: gpt-5.4, gpt-5.3-codex, gpt-5.3-codex-spark, gpt-5.3, zai-coding-plan/glm-4.7, gemini-3-pro-preview, gemini-3-flash-preview, sonnet, opus, kimi-for-coding (codex supports only gpt-5.4 + gpt-5.3-codex + gpt-5.3-codex-spark + gpt-5.3; opencode/gemini/claude/cursor/kimi/pi accept arbitrary model ids))
50 - On macOS: use `ralph app open` to launch the GUI (requires an installed Ralph.app)
51 - App-launched runs are noninteractive: they stream output, but interactive approvals remain terminal-only.
52
53Examples:
54 ralph app open
55 ralph queue list
56 ralph queue show RQ-0008
57 ralph queue next --with-title
58 ralph scan --runner opencode --model gpt-5.3 --focus "CI gaps"
59 ralph task --runner codex --model gpt-5.4 --effort high "Fix the flaky test"
60 ralph scan --runner gemini --model gemini-3-flash-preview --focus "risk audit"
61 ralph scan --runner claude --model sonnet --focus "risk audit"
62 ralph task --runner claude --model opus "Add tests for X"
63 ralph scan --runner cursor --model claude-opus-4-5-20251101 --focus "risk audit"
64 ralph task --runner cursor --model claude-opus-4-5-20251101 "Add tests for X"
65 ralph scan --runner kimi --focus "risk audit"
66 ralph task --runner kimi --model kimi-for-coding "Add tests for X"
67 ralph run one
68 ralph run loop --max-tasks 1
69 ralph run loop
70
71More help:
72 - Default help shows core commands only.
73 - Run `ralph help-all` to see advanced and experimental commands."#)]
74pub struct Cli {
75 #[command(subcommand)]
76 pub command: Command,
77
78 #[arg(long, global = true)]
80 pub force: bool,
81
82 #[arg(short, long, global = true)]
84 pub verbose: bool,
85
86 #[arg(long, value_enum, default_value = "auto", global = true)]
88 pub color: ColorArg,
89
90 #[arg(long, global = true)]
93 pub no_color: bool,
94
95 #[arg(long, global = true, conflicts_with = "no_sanity_checks")]
98 pub auto_fix: bool,
99
100 #[arg(long, global = true, conflicts_with = "auto_fix")]
102 pub no_sanity_checks: bool,
103}
104
105#[derive(Subcommand)]
106pub enum Command {
107 Queue(queue::QueueArgs),
108 Config(config::ConfigArgs),
109 Run(Box<run::RunArgs>),
110 Task(Box<task::TaskArgs>),
111 Scan(scan::ScanArgs),
112 Init(init::InitArgs),
113 App(app::AppArgs),
115 HelpAll,
117 #[command(hide = true)]
119 Machine(Box<machine::MachineArgs>),
120 #[command(
122 hide = true,
123 after_long_help = "Examples:\n ralph prompt worker --phase 1 --repo-prompt plan\n ralph prompt worker --phase 2 --task-id RQ-0001 --plan-file .ralph/cache/plans/RQ-0001.md\n ralph prompt scan --focus \"CI gaps\" --repo-prompt off\n ralph prompt task-builder --request \"Add tests\" --tags rust,tests --scope crates/ralph --repo-prompt tools\n"
124 )]
125 Prompt(prompt::PromptArgs),
126 #[command(
128 hide = true,
129 after_long_help = "Examples:\n ralph doctor\n ralph doctor --auto-fix\n ralph doctor --no-sanity-checks\n ralph doctor --format json\n ralph doctor --format json --auto-fix"
130 )]
131 Doctor(doctor::DoctorArgs),
132 #[command(
134 hide = true,
135 after_long_help = "Examples:\n ralph context init\n ralph context init --project-type rust\n ralph context update --section troubleshooting\n ralph context validate\n ralph context update --dry-run"
136 )]
137 Context(context::ContextArgs),
138 #[command(
140 hide = true,
141 after_long_help = "Examples:\n ralph daemon start\n ralph daemon start --empty-poll-ms 5000\n ralph daemon stop\n ralph daemon status"
142 )]
143 Daemon(daemon::DaemonArgs),
144 #[command(
146 hide = true,
147 after_long_help = "Examples:\n ralph prd create docs/prd/new-feature.md\n ralph prd create docs/prd/new-feature.md --multi\n ralph prd create docs/prd/new-feature.md --dry-run\n ralph prd create docs/prd/new-feature.md --priority high --tag feature\n ralph prd create docs/prd/new-feature.md --draft"
148 )]
149 Prd(prd::PrdArgs),
150 #[command(
152 hide = true,
153 after_long_help = "Examples:\n ralph completions bash\n ralph completions bash > ~/.local/share/bash-completion/completions/ralph\n ralph completions zsh > ~/.zfunc/_ralph\n ralph completions fish > ~/.config/fish/completions/ralph.fish\n ralph completions powershell\n\nInstallation locations by shell:\n Bash: ~/.local/share/bash-completion/completions/ralph\n Zsh: ~/.zfunc/_ralph (and add 'fpath+=~/.zfunc' to ~/.zshrc)\n Fish: ~/.config/fish/completions/ralph.fish\n PowerShell: Add to $PROFILE (see: $PROFILE | Get-Member -Type NoteProperty)"
154 )]
155 Completions(completions::CompletionsArgs),
156 #[command(
158 hide = true,
159 after_long_help = "Examples:\n ralph migrate # Check for pending migrations\n ralph migrate --check # Exit with error code if migrations pending (CI)\n ralph migrate --apply # Apply all pending migrations\n ralph migrate --list # List all migrations and their status\n ralph migrate status # Show detailed migration status"
160 )]
161 Migrate(migrate::MigrateArgs),
162 #[command(
164 hide = true,
165 after_long_help = "Examples:\n ralph cleanup # Clean temp files older than 7 days\n ralph cleanup --force # Clean all ralph temp files\n ralph cleanup --dry-run # Show what would be deleted without deleting"
166 )]
167 Cleanup(cleanup::CleanupArgs),
168 #[command(after_long_help = "Examples:\n ralph version\n ralph version --verbose")]
170 Version(version::VersionArgs),
171 #[command(
173 hide = true,
174 after_long_help = "Examples:\n ralph watch\n ralph watch src/\n ralph watch --patterns \"*.rs,*.toml\"\n ralph watch --auto-queue\n ralph watch --notify\n ralph watch --comments todo,fixme\n ralph watch --debounce-ms 1000\n ralph watch --ignore-patterns \"vendor/,target/,node_modules/\""
175 )]
176 Watch(watch::WatchArgs),
177 #[command(
179 hide = true,
180 after_long_help = "Examples:\n ralph webhook test\n ralph webhook test --event task_completed\n ralph webhook status --format json\n ralph webhook replay --dry-run --id wf-1700000000-1"
181 )]
182 Webhook(webhook::WebhookArgs),
183
184 #[command(
186 hide = true,
187 after_long_help = "Examples:\n ralph productivity summary\n ralph productivity velocity\n ralph productivity streak"
188 )]
189 Productivity(productivity::ProductivityArgs),
190
191 #[command(
193 hide = true,
194 after_long_help = "Examples:\n ralph plugin init my.plugin\n ralph plugin init my.plugin --scope global\n ralph plugin list\n ralph plugin validate\n ralph plugin install ./my-plugin --scope project\n ralph plugin uninstall my.plugin --scope project"
195 )]
196 Plugin(plugin::PluginArgs),
197
198 #[command(
200 hide = true,
201 after_long_help = "Examples:\n ralph runner capabilities codex\n ralph runner capabilities claude --format json\n ralph runner list\n ralph runner list --format json"
202 )]
203 Runner(runner::RunnerArgs),
204
205 #[command(
207 hide = true,
208 after_long_help = "Examples:\n ralph tutorial\n ralph tutorial --keep-sandbox\n ralph tutorial --non-interactive"
209 )]
210 Tutorial(tutorial::TutorialArgs),
211
212 #[command(
214 after_long_help = "Continuation workflow:\n - `ralph undo --list` shows the checkpoints Ralph created before queue-changing operations.\n - `ralph undo --dry-run` previews the restore path without modifying queue files.\n - `ralph undo` restores the most recent checkpoint; `--id` restores a specific one.\n - After restoring, run `ralph queue validate` and then continue normal work.\n\nExamples:\n ralph undo\n ralph undo --list\n ralph undo --dry-run\n ralph undo --id undo-20260215073000000000\n\nCheckpoints are created automatically before queue mutations such as:\n - ralph task mutate / task decompose --write\n - ralph task done/reject/start/ready/schedule\n - ralph task edit/field/clone/split\n - ralph task relate/blocks/mark-duplicate\n - ralph queue archive/prune/sort/import/repair\n - ralph queue issue publish/publish-many\n - ralph task batch operations"
215 )]
216 Undo(undo::UndoArgs),
217
218 #[command(name = "cli-spec", alias = "__cli-spec", hide = true)]
220 CliSpec(CliSpecArgs),
221}
222
223#[derive(Args, Debug, Clone)]
224pub struct CliSpecArgs {
225 #[arg(long, value_enum, default_value_t = CliSpecFormatArg::Json)]
227 pub format: CliSpecFormatArg,
228}
229
230#[derive(ValueEnum, Debug, Copy, Clone, PartialEq, Eq)]
231pub enum CliSpecFormatArg {
232 Json,
233}