Ralph Loop is a milestone-driven development process for Claude Code that automates iterative implementation while capturing learnings at every step. It uses Claude Code's /ralph-loop slash command to create an autonomous loop that works through milestones sequentially -- implementing code, running tests, documenting progress, and committing -- all with human oversight.
This guide distills the patterns proven across 22+ milestones in the go-wasm-cli project into a reusable recipe for any new project.
- What is Ralph Loop?
- Prerequisites
- Project Structure
- Step 1: Define Your Milestones
- Step 2: Write Milestone Plans
- Step 3: Create the Master Prompt
- Step 4: Set Up the Control Directory
- Step 5: Configure CLAUDE.md
- Step 6: Run the Loop
- The Learnings System
- Iteration Lifecycle
- Tips from 22 Milestones of Experience
Ralph Loop is a structured pattern for using Claude Code's autonomous loop feature (/ralph-loop) to implement a project milestone by milestone. The key principles are:
- Milestone-driven: Work is broken into sequential milestones with clear deliverables and exit criteria
- Learning-first: Before each iteration, Claude reads all accumulated learnings from previous milestones
- Test-driven: Every milestone includes tests; tests are the specification
- Documented progress: Every milestone produces a LEARNINGS file capturing what worked, what didn't, and decisions made
- Git-disciplined: Each milestone lives on its own branch, gets a PR, and merges to main
The loop runs autonomously but can be cancelled at any time. Claude works through tasks, verifies them, commits, and moves to the next milestone until everything is done.
- Claude Code CLI installed with the Ralph Loop plugin (provides
/ralph-loopand/cancel-ralphcommands) - Git repository initialized
- GitHub CLI (
gh) installed (for automated PR creation and merging) - A project with a build and test command (e.g.,
make build,go test ./...,npm test)
Create this directory structure in your project root:
your-project/
├── .ralph/ # Active control files (committed)
│ ├── README.md # Quick start instructions
│ ├── MASTER-PROMPT.md # The prompt that drives the loop
│ └── STATUS.md # Tracks milestone completion
│
├── milestones/ # Milestone documentation (committed)
│ ├── OVERVIEW.md # Summary table + dependency graph
│ ├── M00-FIRST-MILESTONE/
│ │ ├── M00-PLAN-*.md # Detailed plan with tasks
│ │ └── M00-LEARNINGS-*.md # Post-completion learnings
│ ├── M01-SECOND-MILESTONE/
│ │ ├── M01-PLAN-*.md
│ │ └── M01-LEARNINGS-*.md
│ └── ...
│
├── CLAUDE.md # Project instructions for Claude Code
└── .gitignore # Must include ralph-loop state file
Add to .gitignore:
# Ralph Loop state file (created during loop execution)
.claude/ralph-loop.local.md
Start with a milestone overview. Each milestone should be:
- Small enough to complete in one Claude Code session (aim for 1-3 hours of work)
- Self-contained with clear exit criteria
- Sequential with explicit dependencies
- Testable with verifiable outcomes
Create milestones/OVERVIEW.md:
# Implementation Plan Overview
## Milestone Summary
| Milestone | Name | Description | Dependencies |
|-----------|-------------------|------------------------------------|--------------|
| M0 | Project Setup | Scaffold project, prove build works | None |
| M1 | Test Suite | Write comprehensive failing tests | M0 |
| M2 | Core Feature | Implement main functionality | M1 |
| M3 | API Layer | REST/GraphQL API | M2 |
| M4 | Frontend | Web UI | M3 |
## Dependency Graph
M0 (Project Setup) └── M1 (Test Suite) └── M2 (Core Feature) ├── M3 (API Layer) └── M4 (Frontend)
## Implementation Philosophy
### Test-Driven Development
1. Write failing tests first (M1)
2. Implement minimum code to pass tests
3. Refactor while keeping tests green
4. Tests are the specification
### Incremental Validation
- Each milestone produces working, testable output
- Integration points validated early
For each milestone, create a detailed plan file. The plan is what Claude reads to know what to implement.
Create milestones/M00-PROJECT-SETUP/M00-PLAN-PROJECT-SETUP.md:
# M0: Project Setup - Plan
## Objective
Scaffold the project and prove the build pipeline works end to end.
## Tasks
### 0.1 Initialize Project
- [ ] Create directory structure
- [ ] Initialize package manager / module system
- [ ] Set up linting and formatting
### 0.2 Build System
- [ ] Create Makefile / build scripts
- [ ] `make build` produces output
- [ ] `make test` runs (even if no tests yet)
### 0.3 CI Pipeline
- [ ] GitHub Actions workflow
- [ ] Runs tests on push/PR
- [ ] Runs linter
## Exit Criteria
- [ ] `make build` succeeds without errors
- [ ] `make test` runs successfully
- [ ] CI pipeline passes on push
- [ ] README exists with setup instructions
## Reference Documents
- Design docs: `docs/design/`
- Architecture: `docs/architecture.md`Key qualities of a good plan:
- Numbered, checkable deliverables (Claude tracks progress against these)
- Clear exit criteria (Claude uses these to know when a milestone is done)
- References to any design docs or specs Claude should read
- Enough detail that Claude can work autonomously
This is the core of Ralph Loop -- the prompt that tells Claude how to work through milestones.
Create .ralph/MASTER-PROMPT.md:
# Ralph Loop Master Prompt
Implement all pending milestones. Check `.ralph/STATUS.md` for current progress.
## Workflow for Each Milestone
### 1. Start Milestone
```bash
git checkout main
git pull origin main
git checkout -b feature/m{N}-{lowercase-name}- Read the milestone plan in
milestones/M{NN}-NAME/ - Read ALL existing LEARNINGS files:
milestones/*/M*-LEARNINGS-*.md - Check progress against deliverables checklist
- Implement the next incomplete deliverable
- Run tests:
YOUR_TEST_COMMAND - Run build:
YOUR_BUILD_COMMAND - Commit with descriptive message
When ALL deliverables for a milestone are done:
# Ensure tests pass
YOUR_TEST_COMMAND
# Ensure build succeeds
YOUR_BUILD_COMMAND
# Push branch
git push -u origin feature/m{N}-{name}
# Create PR
gh pr create --title "M{N}: {Title}" --body "## Summary
{Brief description of changes}
## Test plan
- [ ] All tests pass
- [ ] Build succeeds
Generated with Claude Code and Ralph Loop"
# Merge PR
gh pr merge --merge
# Return to main
git checkout main
git pull origin mainCreate/update milestones/M{NN}-NAME/M{NN}-LEARNINGS-NAME.md with:
- Summary of what was accomplished
- What worked well
- Challenges encountered and resolutions
- Adaptations made to original plan
- Key technical decisions and rationale
- Impact on future milestones
- Test results summary
Update .ralph/STATUS.md, then start the next pending milestone.
Only output <promise>ALL MILESTONES COMPLETE</promise> when:
- ALL milestone deliverables are implemented
- ALL tests pass
- ALL PRs are merged to main
- ALL learnings are documented
- No pending milestones remain
- Work through milestones sequentially
- Each iteration should make measurable progress
- Never skip tests or build verification
- Never output false promises to escape the loop
- If stuck, try a different approach or simplify
- Read ALL learnings before starting each milestone
Customize `YOUR_TEST_COMMAND` and `YOUR_BUILD_COMMAND` for your project (e.g., `go test ./...`, `npm test`, `pytest`, `cargo test`).
---
## Step 4: Set Up the Control Directory
### `.ralph/STATUS.md`
This file tracks progress. Claude updates it as milestones complete.
```markdown
# Ralph Loop Status
## Completed Milestones
| Milestone | Name | Status | PR |
|-----------|----------------|-------------|--------|
| (none yet) |
## Pending Milestones
| Milestone | Name | Status | Branch |
|-----------|----------------|---------|--------|
| M0 | Project Setup | Pending | |
| M1 | Test Suite | Pending | |
| M2 | Core Feature | Pending | |
## Current Milestone: M0 - Project Setup
### Deliverables Checklist
- [ ] Initialize project
- [ ] Build system
- [ ] CI pipeline
## Next Action
Start M0.
Quick reference for you and collaborators:
# Ralph Loop Control Files
## Quick Start
```bash
/ralph-loop:ralph-loop "$(cat .ralph/MASTER-PROMPT.md)" --completion-promise "ALL MILESTONES COMPLETE" --max-iterations 100# Start Ralph Loop
/ralph-loop:ralph-loop "$(cat .ralph/MASTER-PROMPT.md)" --completion-promise "ALL MILESTONES COMPLETE" --max-iterations 100
# Check progress
head -10 .claude/ralph-loop.local.md
# Cancel loop
/ralph-loop:cancel-ralphAll milestone plans are in milestones/M{NN}-NAME/
Completed milestone learnings are in milestones/M{NN}-NAME/M{NN}-LEARNINGS-*.md
---
## Step 5: Configure CLAUDE.md
Add a section to your project's `CLAUDE.md` so Claude understands the development process even outside of Ralph Loop:
```markdown
## Development Process: Ralph Loop
This project uses a milestone-driven development process called "Ralph Loop"
(see `.ralph/MASTER-PROMPT.md`).
**Workflow:**
1. **Start**: Branch from main as `feature/m{N}-{lowercase-name}`
2. **Iterate**: Read plan from `milestones/`, implement next deliverable, test, build, commit
3. **Complete**: Push branch, create PR via `gh pr create`, merge, return to main
4. **Repeat**: Move to next milestone
**Key rules:**
- Work through milestones sequentially
- Never skip test or build verification
- Each iteration should make measurable progress
- Milestone plans with deliverables are in `milestones/`
/ralph-loop:ralph-loop "$(cat .ralph/MASTER-PROMPT.md)" --completion-promise "ALL MILESTONES COMPLETE" --max-iterations 100Create a milestone-specific prompt (e.g., .ralph/ITERATION-M0-PROMPT.md):
Implement M0 only. Read the plan at `milestones/M00-PROJECT-SETUP/M00-PLAN-PROJECT-SETUP.md`.
Before starting, read all existing LEARNINGS files:
milestones/*/M*-LEARNINGS-*.md
Follow the same workflow as the master prompt but stop after M0 is complete.Then run:
/ralph-loop:ralph-loop "$(cat .ralph/ITERATION-M0-PROMPT.md)" --completion-promise "M0 COMPLETE" --max-iterations 20# Check loop state
head -10 .claude/ralph-loop.local.md
# Check milestone status
cat .ralph/STATUS.md/ralph-loop:cancel-ralphThe learnings system is the secret weapon of Ralph Loop. It creates a growing knowledge base that Claude reads before every milestone, making each iteration smarter than the last.
Create milestones/M{NN}-NAME/M{NN}-LEARNINGS-NAME.md after each milestone:
# Milestone N: [Name] - Learnings
## Summary
Brief overview of what was accomplished.
## What Worked Well
- Pattern or approach that succeeded
- Tool or library that was a good choice
## Challenges Encountered
- Challenge 1: Description and how it was resolved
- Challenge 2: Description and how it was resolved
## Adaptations Made
- Original plan: X -> Actual implementation: Y
- Test changes: What tests were modified and why
## Key Decisions
- Decision 1: Why we chose approach X over Y
- Decision 2: Trade-offs considered
## Technical Notes
- Important implementation details for future reference
- Gotchas to watch out for
## Impact on Future Milestones
- How this affects M(N+1), M(N+2), etc.
- Dependencies that changed
## Test Results
- Summary of test pass/fail status
- Tests that were adapted and why- Accumulated knowledge: Claude reads ALL learnings before each milestone. Mistakes from M2 prevent repeats in M5.
- Plan adaptation: Original plans rarely survive contact with implementation. Learnings document what changed and why.
- Test evolution: Tests written in M1 may need adaptation based on implementation realities. Learnings justify changes.
- Onboarding: A new developer (or a new Claude session) can read all LEARNINGS files to understand the project history.
From the go-wasm-cli project's M0 learnings:
Challenge: wasm_exec.js location changed in Go 1.25
- Original plan assumed
$GOROOT/misc/wasm/wasm_exec.js- Actual location in Go 1.25:
$GOROOT/lib/wasm/wasm_exec.js- Resolution: Updated Makefile to check both locations
This learning was captured once and prevented the same issue from blocking future milestones.
Here's what happens in each iteration of the loop:
┌─────────────────────────────────────────────────┐
│ 1. READ LEARNINGS │
│ Read all milestones/*/M*-LEARNINGS-*.md │
│ (accumulated knowledge from all milestones) │
├─────────────────────────────────────────────────┤
│ 2. READ PLAN │
│ Read milestones/M{NN}-NAME/M{NN}-PLAN-*.md │
│ Check deliverables checklist for next task │
├─────────────────────────────────────────────────┤
│ 3. IMPLEMENT │
│ Work on next incomplete deliverable │
│ Adapt approach based on learnings │
├─────────────────────────────────────────────────┤
│ 4. VERIFY │
│ Run tests (must pass) │
│ Run build (must succeed) │
├─────────────────────────────────────────────────┤
│ 5. COMMIT │
│ Git commit with descriptive message │
├─────────────────────────────────────────────────┤
│ 6. CHECK: Milestone complete? │
│ NO → Loop back to step 2 │
│ YES → Continue to step 7 │
├─────────────────────────────────────────────────┤
│ 7. DOCUMENT │
│ Create LEARNINGS file for this milestone │
│ Update .ralph/STATUS.md │
├─────────────────────────────────────────────────┤
│ 8. SHIP │
│ Push branch, create PR, merge │
│ Return to main │
├─────────────────────────────────────────────────┤
│ 9. CHECK: More milestones? │
│ YES → Start next milestone (step 1) │
│ NO → Output completion promise │
└─────────────────────────────────────────────────┘
These insights come from running Ralph Loop through M0-M22 on a real project:
- Start with M0 as a "Hello World" proof of concept. Validate your build pipeline and deployment targets before investing in features.
- Write tests as their own milestone (M1). Having failing tests first gives Claude a clear specification to implement against.
- Keep milestones small. If a milestone has more than 5-6 deliverables, split it.
- Define the dependency graph. Some milestones can run in parallel; make dependencies explicit.
- The Master Prompt should be self-contained. Claude needs to be able to work autonomously from just the prompt + project files.
- Include exact build/test commands. Don't make Claude guess. Specify
go test ./...,npm test, etc. - The completion promise mechanism prevents early exits. Claude can only complete the loop by outputting a specific string, which it's instructed to only do when all criteria are met.
- Read learnings first, always. This is non-negotiable. Make it the first instruction in every prompt.
- Learnings compound. By M10, Claude has absorbed 10 milestones of project-specific knowledge. By M22, it's an expert in your codebase.
- Document test adaptations explicitly. When a test from M1 needs changing in M5, the LEARNINGS file should explain: original expectation, why it changed, new expectation, and rationale.
- One branch per milestone.
feature/m{N}-{lowercase-name}keeps history clean. - PR per milestone. Even if you're the sole developer, PRs create a review checkpoint.
- Return to main between milestones. This ensures each milestone starts from a clean, merged state.
- Set
--max-iterationsgenerously. 20 for a single milestone, 100 for a full run. Better to have headroom than hit the limit mid-work. - Monitor with
head -10 .claude/ralph-loop.local.md. Check progress without interrupting. - Cancel and restart is fine. If something goes wrong,
/ralph-loop:cancel-ralph, fix the issue manually, update STATUS.md, and restart. - Claude will get stuck sometimes. The prompt says "if stuck, try a different approach or simplify" -- but you can also cancel, provide guidance, and restart.
- New milestones can be added anytime. Just add them to STATUS.md and create a plan file. The loop picks up where it left off.
- The pattern works for any language/framework. The go-wasm-cli project used Go + TypeScript + React, but the process is language-agnostic.
- Share learnings across projects. The LEARNINGS template is generic. Technical notes from one project can inform another.
[ ] Create .ralph/ directory with MASTER-PROMPT.md, STATUS.md, README.md
[ ] Create milestones/ directory with OVERVIEW.md
[ ] Write your first milestone plan (M00)
[ ] Add ralph-loop state file to .gitignore
[ ] Add Ralph Loop section to CLAUDE.md
[ ] Commit everything
[ ] Run: /ralph-loop:ralph-loop "$(cat .ralph/MASTER-PROMPT.md)" \
--completion-promise "ALL MILESTONES COMPLETE" --max-iterations 100
[ ] Watch it go