The Ralph Loop¶
The Ralph Loop is Melliza's core execution model: a continuous cycle that drives Gemini to complete user stories one by one. It's the engine that makes autonomous development possible.
Tip
For the motivation and philosophy behind this approach, read the blog post Ship Features in Your Sleep with Ralph Loops.
The Loop Visualized¶
Here's the complete Ralph Loop as a flowchart:
┌─────────────┐
│ Start Melliza │
└──────┬──────┘
│
▼
┌─────────────┐
│ Show TUI │
└──────┬──────┘
│
▼
┌─────────────┐
│ Press 's' │◀─────────────────────────────────────┐
└──────┬──────┘ │
│ │
▼ │
┌─────────────┐ │
│ Read State │ │
└──────┬──────┘ │
│ │
▼ │
╔═════════════╗ all complete ┌────────────┐ │
║ Next Story? ║─────────────────────▶│ ✓ Done │ │
╚══════╤══════╝ └────────────┘ │
│ story found ▲ │
▼ │ │
┌─────────────┐ │ │
│Build Prompt │ │ │
└──────┬──────┘ │ │
│ │ │
▼ │ │
┌─────────────┐ │ │
│Invoke Gemini│ │ │
└──────┬──────┘ │ │
│ │ │
▼ │ │
┌─────────────┐ <melliza-complete/> │ │
│Stream Output├────────────────────────────▶┘ │
└──────┬──────┘ │
│ session ends │
▼ │
╔═════════════╗ no ┌────────────┐ │
║ Max Iters? ║────────────────────▶│ Continue │───┘
╚══════╤══════╝ └────────────┘
│ yes
▼
┌─────────────┐
│ ✗ Stop │
└─────────────┘
Before the Loop: Worktree Setup¶
Before the loop starts, Melliza sets up the working environment. When you press s to start a PRD, the TUI shows a dialog offering to create an isolated worktree:
- Create branch — A new branch (e.g.,
melliza/auth-system) is created from your default branch - Create worktree — A git worktree is set up at
.melliza/worktrees/<prd-name>/ - Run setup — If a setup command is configured (e.g.,
npm install), it runs in the worktree
This setup happens once per PRD. The loop then runs entirely within the worktree directory, isolating all file changes and commits to that branch.
You can also skip worktree creation and run in the current directory if you prefer.
Step by Step¶
Each step in the loop has a specific purpose. Here's what happens in each one.
1. Read State¶
Melliza reads all the files it needs to understand the current situation:
| File | What Melliza Learns |
|---|---|
prd.json |
Which stories are complete (passes: true), which are pending, and which is in progress |
progress.md |
What happened in previous iterations: learnings, patterns, and context |
| Codebase files | Current state of the code (via Gemini's file reading) |
This step ensures Gemini always has fresh, accurate information about what's done and what's left to do.
2. Select Next Story¶
Melliza picks the next story to work on by looking at prd.json:
- Find all stories where
passes: false - Sort by
priority(lowest number = highest priority) - Pick the first one
If a story has inProgress: true, Melliza continues with that story instead of starting a new one. This handles cases where Gemini was interrupted mid-story.
3. Build Prompt¶
Melliza constructs a prompt that tells Gemini exactly what to do. The prompt includes:
- The user story: ID, title, description, and acceptance criteria
- Instructions: Read the PRD, pick the next story, implement it, run checks, commit
- Progress context: Any patterns or learnings from
progress.md
Here's a simplified version of what Gemini receives:
## Your Task
1. Read the PRD at `.melliza/prds/your-prd/prd.json`
2. Read `progress.md` if it exists (check Codebase Patterns first)
3. Pick the highest priority story where `passes: false`
4. Mark it as `inProgress: true` in the PRD
5. Implement that single user story using test-first TDD (red → green → refactor)
6. Run quality checks (typecheck, lint, test)
7. For visual/UI changes, capture screenshot verification (or document environment limitations)
8. If checks pass, commit with message: `feat: [Story ID] - [Story Title]`
9. Update the PRD to set `passes: true` and `inProgress: false`
10. Append your progress to `progress.md`
The prompt is embedded directly in Melliza's code. There's no external template file to manage.
4. Invoke Gemini CLI¶
Melliza runs Gemini CLI via the CLI, passing the constructed prompt:
The flags tell Gemini to: - Skip permission prompts (Melliza runs unattended) - Output structured JSON for parsing
Gemini now has full control. It can read files, write code, run tests, and commit changes, all autonomously.
5. Stream & Parse Output¶
As Gemini works, it produces a stream of JSON messages. Melliza parses this stream in real-time using a streaming JSON parser. This is what allows the TUI to show live progress.
Here's what the output stream looks like:
Each message contains: - type: What kind of output (text, tool_use, etc.) - content: The actual output or tool details
Melliza parses this stream to display progress in the TUI. When Gemini's session ends, Melliza checks if the story was completed (by reading the updated PRD) and continues the loop.
6. The Completion Signal¶
When Gemini determines that all stories are complete, it outputs a special marker:
This signal tells Melliza to break out of the loop early. There's no need to spawn another iteration just to discover there's nothing left to do. It's an optimization, not the primary mechanism for tracking story completion.
Individual story completion is tracked through the PRD itself (passes: true), not through this signal.
7. Continue the Loop¶
After each Gemini session ends, Melliza:
- Increments the iteration counter
- Checks if max iterations is reached
- If not at limit, loops back to step 1 (Read State)
The next iteration starts fresh. Gemini reads the updated PRD, sees the completed story, and picks the next one. If all stories are done, Melliza stops.
Iteration Limits¶
Melliza has a safety limit on iterations to prevent runaway loops. When --max-iterations is not specified, the limit is calculated dynamically based on the number of remaining stories plus a buffer. You can also adjust the limit at runtime with +/- in the TUI.
| Scenario | What Happens |
|---|---|
| Story completes normally | Iteration counter goes up by 1, loop continues |
| Story takes multiple Gemini sessions | Each Gemini invocation is 1 iteration |
| Limit reached | Melliza stops and displays a message |
If you hit the limit, it usually means:
- A story is too complex and needs to be broken down
- Gemini is stuck in a loop (check gemini.log)
- There's an issue with the PRD format
You can adjust the limit with the --max-iterations flag or in your configuration.
Post-Completion Actions¶
When all stories in a PRD are complete, Melliza can automatically:
- Push the branch — If
onComplete.pushis enabled in.melliza/config.yaml, Melliza pushes the branch to origin - Create a pull request — If
onComplete.createPRis also enabled, Melliza creates a PR via theghCLI with a title and body generated from the PRD
The completion screen shows the progress of these actions with spinners, checkmarks, or error messages. On PR success, the PR URL is displayed and clickable.
If auto-actions aren't configured, the completion screen shows a hint to configure them via the Settings TUI (,).
You can also take manual actions from the completion screen:
- m — Merge the branch locally
- c — Clean up the worktree
- l — Switch to another PRD
- q — Quit Melliza
Why "Ralph"?¶
The name comes from Ralph Wiggum loops, a pattern coined by Geoffrey Huntley. The idea: instead of fighting context window limits with one long session, you run the AI in a loop. Each iteration starts fresh but reads persisted state from the previous run.
Melliza's implementation was inspired by snarktank/ralph, an early proof-of-concept that demonstrated the pattern in practice.
What's Next¶
- The .melliza Directory: Where all this state lives
- PRD Format: How to write effective user stories
- CLI Reference: Running Melliza with different options