---
status: completed
created: 2026-01-15
started: 2026-01-15
completed: 2026-01-15
---
# Task: Implement `ralph init` Command

## Description
Add a new `ralph init` subcommand that initializes a repository with a minimal Ralph configuration. Supports two modes: generating a minimal config for a specific backend, or copying an embedded preset. Presets are compiled into the binary for self-contained distribution.

## Background
Currently, users must manually create `ralph.yml` configuration files or copy from examples. This creates friction for new users and requires access to the source repository for presets. By embedding presets in the binary and providing an `init` command, users get a streamlined onboarding experience with a fully self-contained tool.

## Technical Requirements

1. **New CLI Subcommand**: Add `Init` variant to the `Commands` enum in `main.rs`
   - `--backend <claude|kiro|gemini|codex|amp|custom>`: Generate minimal config for specified backend
   - `--preset <preset-name>`: Copy embedded preset to `ralph.yml`
   - `--list-presets`: Display all available embedded presets with descriptions
   - `--force`: Overwrite existing `ralph.yml` if present
   - `--backend` and `--preset` are mutually exclusive (use clap `conflicts_with`)

2. **Embedded Presets Module**: Create `crates/ralph-cli/src/presets.rs`
   - Use `include_str!` to embed all YAML files from `presets/` directory at compile time
   - Extract description from each preset's header comment
   - Provide `list_presets()` and `get_preset(name)` functions
   - Struct: `EmbeddedPreset { name, description, content }`

3. **Init Module**: Create `crates/ralph-cli/src/init.rs`
   - `init_from_backend(backend: &str, force: bool)`: Generate minimal template
   - `init_from_preset(preset_name: &str, force: bool)`: Write embedded preset content
   - Check if `ralph.yml` exists; error unless `--force` is specified

4. **Minimal Backend Template**: Generate this config for `--backend`:
```yaml
# Ralph Orchestrator Configuration
# Generated by: ralph init --backend {backend}
# Docs: https://github.com/mikeyobrien/ralph-orchestrator

cli:
  backend: "{backend}"

event_loop:
  prompt_file: "PROMPT.md"
  completion_promise: "LOOP_COMPLETE"
  max_iterations: 100
  # max_runtime_seconds: 14400    # 4 hours max

# ─────────────────────────────────────────────────────────────────────────────
# Additional Configuration (uncomment to customize)
# ─────────────────────────────────────────────────────────────────────────────

# core:
#   scratchpad: ".agent/scratchpad.md"
#   specs_dir: "./specs/"

# Custom hats for multi-agent workflows:
# hats:
#   builder:
#     name: "Builder"
#     triggers: ["build.task"]
#     publishes: ["build.done", "build.blocked"]
#
#   reviewer:
#     name: "Reviewer"
#     triggers: ["review.request"]
#     publishes: ["review.approved", "review.changes_requested"]

# Create PROMPT.md with your task, then run: ralph run
```

5. **Update README.md**: Update Quick Start section to reflect new init behavior
   - Remove outdated claim that `ralph init` creates PROMPT.md and .agent/
   - Document `--backend` flag with examples
   - Document `--preset` flag with examples
   - Add `--list-presets` to show available workflows
   - Keep it concise - link to docs for full preset descriptions

## Dependencies
- Existing CLI infrastructure in `crates/ralph-cli/src/main.rs`
- All preset files in `presets/*.yml` directory (22 presets)
- clap for argument parsing (already a dependency)

## Implementation Approach

1. **Create `presets.rs` module**
   - Define `EmbeddedPreset` struct
   - Use `include_str!` macro to embed each preset file
   - Parse first comment block from each preset to extract description
   - Implement `list_presets()` returning slice of all presets
   - Implement `get_preset(name)` returning Option

2. **Create `init.rs` module**
   - Implement `init_from_backend()` with template string interpolation
   - Implement `init_from_preset()` that looks up and writes preset content
   - Add file existence check with force flag handling
   - Return appropriate Result types with user-friendly errors

3. **Update `main.rs`**
   - Add `Init(InitArgs)` to Commands enum
   - Define `InitArgs` struct with all flags
   - Add `init_command()` handler function
   - Wire up to main match statement

4. **Add tests**
   - Unit tests for preset lookup (all presets findable by name)
   - Unit tests for template generation (valid YAML output)
   - Test mutual exclusivity of flags

## Acceptance Criteria

1. **README Documentation**
   - Given the implementation is complete
   - When reviewing README.md Quick Start section
   - Then it accurately documents `ralph init --backend`, `--preset`, and `--list-presets` usage

2. **Backend Initialization**
   - Given no `ralph.yml` exists in current directory
   - When running `ralph init --backend claude`
   - Then `ralph.yml` is created with minimal claude configuration

2. **Preset Initialization**
   - Given no `ralph.yml` exists in current directory
   - When running `ralph init --preset tdd-red-green`
   - Then `ralph.yml` is created with full tdd-red-green preset content

3. **List Presets**
   - Given the ralph binary
   - When running `ralph init --list-presets`
   - Then all 22 embedded presets are displayed with names and descriptions

4. **File Exists Protection**
   - Given `ralph.yml` already exists in current directory
   - When running `ralph init --backend claude` without `--force`
   - Then command fails with error message suggesting `--force`

5. **Force Overwrite**
   - Given `ralph.yml` already exists in current directory
   - When running `ralph init --backend claude --force`
   - Then existing file is overwritten with new configuration

6. **Mutual Exclusivity**
   - Given the ralph binary
   - When running `ralph init --backend claude --preset tdd-red-green`
   - Then command fails with clap error about conflicting arguments

7. **Invalid Preset Name**
   - Given the ralph binary
   - When running `ralph init --preset nonexistent-preset`
   - Then command fails with error listing available preset names

8. **Generated Config Valid**
   - Given a newly generated `ralph.yml` from `--backend`
   - When parsing with `RalphConfig::from_file()`
   - Then config parses successfully with expected values

9. **All Presets Embedded**
   - Given the compiled binary
   - When calling `list_presets()`
   - Then all presets from `presets/` directory are available

## Metadata
- **Complexity**: Medium
- **Labels**: CLI, Init, Presets, Onboarding, DX
- **Required Skills**: Rust, clap, include_str! macro, file I/O
