Skip to content

Instantly share code, notes, and snippets.

@johnoscott
Created February 13, 2026 23:02
Show Gist options
  • Select an option

  • Save johnoscott/345f565b0dbfa6e9acb9c0a061593836 to your computer and use it in GitHub Desktop.

Select an option

Save johnoscott/345f565b0dbfa6e9acb9c0a061593836 to your computer and use it in GitHub Desktop.
How to set up a Ralph Loop: milestone-driven, learning, test-driven development with Claude Code

How to Set Up a Ralph Loop in a New Project

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.


Table of Contents

  1. What is Ralph Loop?
  2. Prerequisites
  3. Project Structure
  4. Step 1: Define Your Milestones
  5. Step 2: Write Milestone Plans
  6. Step 3: Create the Master Prompt
  7. Step 4: Set Up the Control Directory
  8. Step 5: Configure CLAUDE.md
  9. Step 6: Run the Loop
  10. The Learnings System
  11. Iteration Lifecycle
  12. Tips from 22 Milestones of Experience

What is Ralph Loop?

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.


Prerequisites

  • Claude Code CLI installed with the Ralph Loop plugin (provides /ralph-loop and /cancel-ralph commands)
  • 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)

Project Structure

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

Step 1: Define Your Milestones

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

Step 2: Write Milestone Plans

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

Step 3: Create the Master Prompt

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}

2. Each Iteration

  1. Read the milestone plan in milestones/M{NN}-NAME/
  2. Read ALL existing LEARNINGS files: milestones/*/M*-LEARNINGS-*.md
  3. Check progress against deliverables checklist
  4. Implement the next incomplete deliverable
  5. Run tests: YOUR_TEST_COMMAND
  6. Run build: YOUR_BUILD_COMMAND
  7. Commit with descriptive message

3. Complete Milestone

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 main

4. Capture Learnings

Create/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

5. Move to Next Milestone

Update .ralph/STATUS.md, then start the next pending milestone.

Completion

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

Rules

  • 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.

.ralph/README.md

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

Commands

# 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-ralph

Milestone Plans

All milestone plans are in milestones/M{NN}-NAME/

Learnings

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/`

Step 6: Run the Loop

Start a full run (all milestones)

/ralph-loop:ralph-loop "$(cat .ralph/MASTER-PROMPT.md)" --completion-promise "ALL MILESTONES COMPLETE" --max-iterations 100

Start a single milestone

Create 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

Monitor progress

# Check loop state
head -10 .claude/ralph-loop.local.md

# Check milestone status
cat .ralph/STATUS.md

Cancel the loop

/ralph-loop:cancel-ralph

The Learnings System

The 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.

What goes in a LEARNINGS file

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

Why learnings matter

  1. Accumulated knowledge: Claude reads ALL learnings before each milestone. Mistakes from M2 prevent repeats in M5.
  2. Plan adaptation: Original plans rarely survive contact with implementation. Learnings document what changed and why.
  3. Test evolution: Tests written in M1 may need adaptation based on implementation realities. Learnings justify changes.
  4. Onboarding: A new developer (or a new Claude session) can read all LEARNINGS files to understand the project history.

Real example

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.


Iteration Lifecycle

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              │
└─────────────────────────────────────────────────┘

Tips from 22 Milestones of Experience

These insights come from running Ralph Loop through M0-M22 on a real project:

Planning

  • 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.

Prompts

  • 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.

Learnings

  • 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.

Git Workflow

  • 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.

Execution

  • Set --max-iterations generously. 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.

Scaling

  • 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.

Quick Start Checklist

[ ] 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment