1use clap::Parser;
6
7#[derive(Parser, Debug, Default)]
9pub struct VerbosityShorthand {
10 #[arg(
12 short,
13 long,
14 conflicts_with = "verbosity",
15 help = "Quiet mode (same as -v0)"
16 )]
17 pub quiet: bool,
18
19 #[arg(
21 long,
22 short,
23 conflicts_with = "verbosity",
24 help = "Full output mode, no truncation (same as -v3)"
25 )]
26 pub full: bool,
27}
28
29#[derive(Parser, Debug, Default)]
31pub struct DebugVerbosity {
32 #[arg(
34 long,
35 conflicts_with = "verbosity",
36 help = "Debug mode (same as -v4)",
37 hide = true
38 )]
39 pub debug: bool,
40}
41
42#[derive(Parser, Debug, Default)]
44pub struct QuickPresets {
45 #[arg(
47 long,
48 short = 'Q',
49 help = "Quick mode: 1 dev iteration + 1 review (for rapid prototyping)"
50 )]
51 pub quick: bool,
52
53 #[arg(
55 long,
56 short = 'U',
57 help = "Rapid mode: 2 dev iterations + 1 review (fast but more thorough than quick)"
58 )]
59 pub rapid: bool,
60
61 #[arg(
63 long,
64 short = 'L',
65 help = "Long mode: 15 dev iterations + 10 reviews (for thorough development)"
66 )]
67 pub long: bool,
68}
69
70#[derive(Parser, Debug, Default)]
72pub struct StandardPresets {
73 #[arg(
75 long,
76 short = 'S',
77 help = "Standard mode: 5 dev iterations + 2 reviews (default workflow)"
78 )]
79 pub standard: bool,
80
81 #[arg(
83 long,
84 short = 'T',
85 help = "Thorough mode: 10 dev iterations + 5 reviews (balanced but thorough)"
86 )]
87 pub thorough: bool,
88}
89
90#[derive(Parser, Debug, Default)]
92pub struct UnifiedInitFlags {
93 #[arg(
115 long,
116 conflicts_with_all = ["init_global", "init_config", "init_legacy", "init_prompt"],
117 help = "Smart init: create config or PROMPT.md (infers from current state)",
118 value_name = "TEMPLATE",
119 num_args = 0..=1,
120 default_missing_value = "",
121 )]
124 pub init: Option<String>,
125
126 #[arg(
128 long,
129 conflicts_with_all = ["init", "init_global", "init_legacy", "init_prompt"],
130 help = "Create ~/.config/ralph-workflow.toml with default settings (recommended)",
131 hide = true
132 )]
133 pub init_config: bool,
134
135 #[arg(
137 long,
138 conflicts_with_all = ["init", "init_config", "init_legacy", "init_prompt"],
139 help = "Create ~/.config/ralph-workflow.toml with default settings (recommended)",
140 hide = true
141 )]
142 pub init_global: bool,
143}
144
145#[derive(Parser, Debug, Default)]
147pub struct LegacyInitFlag {
148 #[arg(
150 long,
151 conflicts_with_all = ["init", "init_global", "init_prompt"],
152 help = "(Legacy) Create .agent/agents.toml with default settings (not recommended)",
153 hide = true
154 )]
155 pub init_legacy: bool,
156}
157
158#[derive(Parser, Debug, Default)]
160pub struct AgentListFlags {
161 #[arg(
163 long,
164 help = "Show all agents from registry and config file",
165 hide = true
166 )]
167 pub list_agents: bool,
168
169 #[arg(
171 long,
172 help = "Show only agents that are installed and available",
173 hide = true
174 )]
175 pub list_available_agents: bool,
176}
177
178#[derive(Parser, Debug, Default)]
180pub struct ProviderListFlag {
181 #[arg(
183 long,
184 help = "Show OpenCode provider types with model prefixes and auth commands",
185 hide = true
186 )]
187 pub list_providers: bool,
188}
189
190#[derive(Parser, Debug, Default)]
192pub struct CompletionFlag {
193 #[arg(
195 long,
196 value_name = "SHELL",
197 value_enum,
198 help = "Generate shell completion script (bash, zsh, fish, elvish, powershell)"
199 )]
200 pub generate_completion: Option<Shell>,
201}
202
203#[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ValueEnum)]
205pub enum Shell {
206 Bash,
208 Zsh,
210 Fish,
212 Elvish,
214 Pwsh,
216}
217
218#[derive(Parser, Debug, Default)]
220pub struct TemplateListFlag {
221 #[arg(
223 long,
224 help = "Show all available Work Guides for PROMPT.md (templates for your tasks)"
225 )]
226 pub list_templates: bool,
227}
228
229#[derive(Parser, Debug, Default)]
231pub struct TemplateCommands {
232 #[arg(
234 long = "init-system-prompts",
235 alias = "init-templates",
236 help = "Create ~/.config/ralph/templates/ with default Agent Prompts (backend AI behavior configuration, NOT Work Guides for PROMPT.md)",
237 default_missing_value = "false",
238 num_args = 0..=1,
239 require_equals = true
240 )]
241 pub init_templates: Option<bool>,
242
243 #[arg(
245 long,
246 requires = "init_templates",
247 help = "Overwrite existing system prompt templates during init (use with caution)"
248 )]
249 pub force: bool,
250
251 #[arg(long, help = "Validate all Agent Prompt templates for syntax errors")]
253 pub validate: bool,
254
255 #[arg(
257 long,
258 value_name = "NAME",
259 help = "Show Agent Prompt template content and metadata"
260 )]
261 pub show: Option<String>,
262
263 #[arg(long, help = "List all Agent Prompt templates with their variables")]
265 pub list: bool,
266
267 #[arg(
269 long,
270 value_name = "NAME",
271 help = "Extract variables from an Agent Prompt template"
272 )]
273 pub variables: Option<String>,
274
275 #[arg(
277 long,
278 value_name = "NAME",
279 help = "Test render a system prompt template with provided variables"
280 )]
281 pub render: Option<String>,
282}
283
284impl TemplateCommands {
285 pub const fn init_templates_enabled(&self) -> bool {
287 self.init_templates.is_some()
288 }
289}
290
291#[derive(Parser, Debug, Default)]
293pub struct CommitPlumbingFlags {
294 #[arg(
296 long,
297 help = "Run only the commit message generation phase, then exit",
298 hide = true
299 )]
300 pub generate_commit_msg: bool,
301
302 #[arg(
304 long,
305 help = "Stage all changes and commit using .agent/commit-message.txt",
306 hide = true
307 )]
308 pub apply_commit: bool,
309}
310
311#[derive(Parser, Debug, Default)]
313pub struct CommitDisplayFlags {
314 #[arg(long, help = "Read and display .agent/commit-message.txt", hide = true)]
316 pub show_commit_msg: bool,
317
318 #[arg(
320 long,
321 help = "Reset .agent/start_commit to current HEAD (for incremental diff generation)",
322 hide = true
323 )]
324 pub reset_start_commit: bool,
325}
326
327#[derive(Parser, Debug, Default)]
329pub struct RecoveryFlags {
330 #[arg(
332 long,
333 help = "Resume from last checkpoint (if one exists from a previous interrupted run)",
334 hide = true
335 )]
336 pub resume: bool,
337
338 #[arg(
340 long,
341 help = "Validate configuration and PROMPT.md without running agents",
342 hide = true
343 )]
344 pub dry_run: bool,
345
346 #[arg(
348 long,
349 short = 'd',
350 help = "Show system info, agent status, and config for troubleshooting"
351 )]
352 pub diagnose: bool,
353}
354
355#[derive(Parser, Debug, Default)]
357pub struct RebaseFlags {
358 #[arg(
360 long,
361 help = "Skip automatic rebase to main branch before and after pipeline"
362 )]
363 pub skip_rebase: bool,
364
365 #[arg(
367 long,
368 help = "Only rebase to main branch, then exit (no pipeline execution)"
369 )]
370 pub rebase_only: bool,
371}
372
373#[derive(Parser, Debug)]
375#[command(name = "ralph")]
376#[command(about = "PROMPT-driven multi-agent orchestrator for git repos")]
377#[command(
378 long_about = "Ralph orchestrates AI coding agents to implement changes based on PROMPT.md.\n\n\
379 It runs a developer agent for code implementation, then a reviewer agent for\n\
380 quality assurance, automatically staging and committing the final result."
381)]
382#[command(version)]
383#[command(
384 after_help = "╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\
385\n\
386NEW TO RALPH?\n\
387 Just want to get started? Run:\n\
388 ralph --init feature-spec # Create PROMPT.md from a Task Template\n\
389 ralph \"fix: my bug\" # Run with AI agents\n\
390\n\
391 WORK GUIDES IN RALPH (two different types):\n\
392\n\
393 1. Work Guides (for PROMPT.md - YOUR task descriptions)\n\
394 These are templates for describing YOUR work to the AI.\n\
395 Examples: bug-fix, feature-spec, refactor, test, docs, etc.\n\
396 \n\
397 Commands:\n\
398 ralph --init <template> # Create PROMPT.md from a Work Guide\n\
399 ralph --list-templates # Show all available Work Guides\n\
400 ralph --init-prompt <name> # Same as --init (legacy alias)\n\
401\n\
402 2. Agent Prompts (backend AI behavior configuration)\n\
403 These configure HOW the AI agents behave (internal prompts).\n\
404 You probably don't need to touch these unless you're customizing agent behavior.\n\
405 \n\
406 Commands:\n\
407 ralph --init-system-prompts # Create default Agent Prompts\n\
408 ralph --list # Show Agent Prompt templates\n\
409 ralph --show <name> # Show a specific Agent Prompt\n\
410\n\
411╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\
412\n\
413SHELL COMPLETION\n\
414 Enable tab-completion for faster command entry:\n\
415 ralph --generate-completion=bash > ~/.local/share/bash-completion/completions/ralph\n\
416 ralph --generate-completion=zsh > ~/.zsh/completion/_ralph\n\
417 ralph --generate-completion=fish > ~/.config/fish/completions/ralph.fish\n\
418\n\
419 Then restart your shell or source the file.\n\
420\n\
421╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\
422\n\
423PRESET MODES (pick how thorough AI should be):\n\
424 -Q Quick: 1 dev + 1 review (typos, small fixes)\n\
425 -U Rapid: 2 dev + 1 review (minor changes)\n\
426 -S Standard: 5 dev + 2 reviews (default for most tasks)\n\
427 -T Thorough: 10 dev + 5 reviews (complex features)\n\
428 -L Long: 15 dev + 10 reviews (most thorough)\n\
429\n\
430╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\
431\n\
432COMMON SHORTHANDS:\n\
433 -D N, -R N Set dev iterations and review cycles\n\
434 -a AGENT Pick developer agent (claude, opencode, etc.)\n\
435 -r AGENT Pick reviewer agent\n\
436 -v N / -q / -f Set verbosity (quiet/normal/full)\n\
437 -d Diagnose/show system info\n\
438 -i Interactive mode (prompt if PROMPT.md missing)\n\
439 -c PATH Use specific config file\n\
440\n\
441╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\
442\n\
443QUICK EXAMPLES:\n\
444 ralph \"fix: typo\" Run with default settings\n\
445 ralph -Q \"fix: small bug\" Quick mode for tiny fixes\n\
446 ralph -U \"feat: add button\" Rapid mode for minor features\n\
447 ralph -a claude \"fix: bug\" Use specific agent\n\
448 ralph --list-templates See all Work Guides\n\
449 ralph --init bug-fix # Create PROMPT.md from a Work Guide\n\
450╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
451)]
452pub struct Args {
455 #[command(flatten)]
457 pub verbosity_shorthand: VerbosityShorthand,
458
459 #[command(flatten)]
461 pub debug_verbosity: DebugVerbosity,
462
463 #[command(flatten)]
465 pub quick_presets: QuickPresets,
466
467 #[command(flatten)]
469 pub standard_presets: StandardPresets,
470
471 #[command(flatten)]
473 pub unified_init: UnifiedInitFlags,
474
475 #[command(flatten)]
477 pub legacy_init: LegacyInitFlag,
478
479 #[command(flatten)]
481 pub agent_list: AgentListFlags,
482
483 #[command(flatten)]
485 pub provider_list: ProviderListFlag,
486
487 #[command(flatten)]
489 pub completion: CompletionFlag,
490
491 #[command(flatten)]
493 pub template_list: TemplateListFlag,
494
495 #[command(flatten)]
497 pub template_commands: TemplateCommands,
498
499 #[command(flatten)]
501 pub commit_plumbing: CommitPlumbingFlags,
502
503 #[command(flatten)]
505 pub commit_display: CommitDisplayFlags,
506
507 #[command(flatten)]
509 pub recovery: RecoveryFlags,
510
511 #[command(flatten)]
513 pub rebase_flags: RebaseFlags,
514
515 #[arg(
517 default_value = "chore: apply PROMPT loop + review/fix/review",
518 help = "Commit message for the final commit"
519 )]
520 pub commit_msg: String,
521
522 #[arg(
524 long = "developer-iters",
525 short = 'D',
526 env = "RALPH_DEVELOPER_ITERS",
527 value_name = "N",
528 help = "Number of developer agent iterations",
529 aliases = ["developer-iteration", "dev-iter", "d-iters"]
530 )]
531 pub developer_iters: Option<u32>,
532
533 #[arg(
535 long = "reviewer-reviews",
536 short = 'R',
537 env = "RALPH_REVIEWER_REVIEWS",
538 value_name = "N",
539 help = "Number of review-fix cycles (0=skip review, 1=one cycle, default: 2)",
540 aliases = ["reviewer-count", "reviewer-review"]
541 )]
542 pub reviewer_reviews: Option<u32>,
543
544 #[arg(
546 long,
547 env = "RALPH_PRESET",
548 value_name = "NAME",
549 help = "Use a preset agent combination (default, opencode)",
550 hide = true
551 )]
552 pub preset: Option<super::presets::Preset>,
553
554 #[arg(
556 long,
557 short = 'a',
558 env = "RALPH_DEVELOPER_AGENT",
559 aliases = ["driver-agent", "dev-agent", "developer"],
560 value_name = "AGENT",
561 help = "Developer agent for code implementation (default: first in agent_chain.developer)"
562 )]
563 pub developer_agent: Option<String>,
564
565 #[arg(
567 long,
568 short = 'r',
569 env = "RALPH_REVIEWER_AGENT",
570 aliases = ["rev-agent", "reviewer"],
571 value_name = "AGENT",
572 help = "Reviewer agent for code review (default: first in agent_chain.reviewer)"
573 )]
574 pub reviewer_agent: Option<String>,
575
576 #[arg(
578 long,
579 env = "RALPH_DEVELOPER_MODEL",
580 value_name = "MODEL_FLAG",
581 help = "Model flag for developer agent (e.g., '-m opencode/glm-4.7-free')",
582 hide = true
583 )]
584 pub developer_model: Option<String>,
585
586 #[arg(
588 long,
589 env = "RALPH_REVIEWER_MODEL",
590 value_name = "MODEL_FLAG",
591 help = "Model flag for reviewer agent (e.g., '-m opencode/claude-sonnet-4')",
592 hide = true
593 )]
594 pub reviewer_model: Option<String>,
595
596 #[arg(
601 long,
602 env = "RALPH_DEVELOPER_PROVIDER",
603 value_name = "PROVIDER",
604 help = "Provider for developer agent: 'opencode' (Zen), 'zai'/'zhipuai' (Z.AI direct), 'anthropic'/'openai' (direct API)",
605 hide = true
606 )]
607 pub developer_provider: Option<String>,
608
609 #[arg(
614 long,
615 env = "RALPH_REVIEWER_PROVIDER",
616 value_name = "PROVIDER",
617 help = "Provider for reviewer agent: 'opencode' (Zen), 'zai'/'zhipuai' (Z.AI direct), 'anthropic'/'openai' (direct API)",
618 hide = true
619 )]
620 pub reviewer_provider: Option<String>,
621
622 #[arg(
625 long,
626 env = "RALPH_REVIEWER_JSON_PARSER",
627 value_name = "PARSER",
628 help = "JSON parser for reviewer (claude, codex, gemini, opencode, generic); overrides agent config",
629 hide = true
630 )]
631 pub reviewer_json_parser: Option<String>,
632
633 #[arg(
635 short,
636 long,
637 value_name = "LEVEL",
638 value_parser = clap::value_parser!(u8).range(0..=4),
639 help = "Output verbosity (0=quiet, 1=normal, 2=verbose [default], 3=full, 4=debug); overrides RALPH_VERBOSITY"
640 )]
641 pub verbosity: Option<u8>,
642
643 #[arg(
645 long,
646 help = "Disable isolation mode: keep NOTES.md and ISSUES.md between runs",
647 hide = true
648 )]
649 pub no_isolation: bool,
650
651 #[arg(
653 long,
654 value_name = "LEVEL",
655 help = "Review depth: standard (balanced), comprehensive (thorough), security (OWASP-focused), incremental (changed files only)",
656 hide = true
657 )]
658 pub review_depth: Option<String>,
659
660 #[arg(
662 long,
663 short = 'c',
664 value_name = "PATH",
665 help = "Path to configuration file (default: ~/.config/ralph-workflow.toml)",
666 hide = true
667 )]
668 pub config: Option<std::path::PathBuf>,
669
670 #[arg(
683 long,
684 value_name = "TEMPLATE",
685 help = "Create PROMPT.md from a Task Template (use --list-templates to see options)"
686 )]
687 pub init_prompt: Option<String>,
688
689 #[arg(
691 long,
692 short = 'i',
693 help = "Interactive mode: prompt to create PROMPT.md from template when missing"
694 )]
695 pub interactive: bool,
696
697 #[arg(
699 long,
700 env = "RALPH_GIT_USER_NAME",
701 value_name = "NAME",
702 help = "Git user name for commits (overrides config, env, and git config)"
703 )]
704 pub git_user_name: Option<String>,
705
706 #[arg(
708 long,
709 env = "RALPH_GIT_USER_EMAIL",
710 value_name = "EMAIL",
711 help = "Git user email for commits (overrides config, env, and git config)"
712 )]
713 pub git_user_email: Option<String>,
714
715 #[arg(
717 long,
718 help = "Display streaming quality metrics (delta stats, repairs, violations) after agent completion"
719 )]
720 pub show_streaming_metrics: bool,
721}