Skip to content

Latest commit

 

History

History
195 lines (142 loc) · 6.83 KB

File metadata and controls

195 lines (142 loc) · 6.83 KB

Ralph Wiggum Loop Guide

What Is It?

A development pattern where an AI agent runs in a bash loop, iterating on tasks until a machine-verifiable exit condition is met. State persists in files (PLAN.md) and git, not in the LLM's context window.

while tasks_remain; do
  claude -p "Read PLAN.md. Do the next task. Validate. Mark done."
done

Named after the Simpsons character. Each iteration starts with fresh context — the agent reads the plan from scratch, picks up where the previous iteration left off, and works on one task.

When to Use Ralph vs. Single-Shot

Signal Single-Shot Ralph Loop
Output needs human review Yes No
Clear pass/fail criteria Either Yes
Might need multiple attempts No Yes
Requires judgment or taste Yes No
Tightly bounded scope Either Yes
Architectural decisions Yes No

Use Ralph for: Bug fixes, boilerplate, test writing, "make the build pass" work, migration scripts, refactoring with clear patterns.

Use single-shot for: Documentation, UX copy, API design, architectural decisions, anything where "done" requires human judgment.

PLAN.md Format

The plan file is the central state artifact. The agent reads it fresh every iteration.

# Plan: [Feature/Fix Name]

## Validation
Run after every task. All must pass before marking [x].
- `npm run build`
- `npm test`

## Tasks
- [ ] First task — `file.tsx:line` — what to change and why
- [ ] Second task — `file.tsx:line` — specific, measurable outcome
- [ ] **HARD STOP** — Risky task — review before continuing
- [ ] Fourth task — `file.tsx:line` — depends on third task

## Completed
(agent moves checked items here to keep the task list focused)

Conventions

  • One task per checkbox — specific, measurable, with file:line references
  • HARD STOP markers — agent completes the task, commits, and stops. The loop restarts with fresh context, giving you a chance to review
  • Completed section — agent moves [x] items here to keep the active list short as context grows
  • Validation at top — agent runs these after every task
  • Be specific: "Remove the !isMobile guard at todo-card.tsx:83" not "Fix mobile checkbox"
  • Be measurable: Include success criteria the agent can verify

Common Mistakes

  • Wrong file paths — verify every file:line reference before starting the loop. Wrong paths waste iterations.
  • Tasks too large — each task should be completable in one iteration (5-15 minutes). Split large tasks.
  • Tasks too vague — "improve the component" is not a task. "Add error boundary to UserProfile.tsx that catches fetch failures and shows a retry button" is.
  • Missing dependencies — if task 3 depends on task 2, add a note. Better yet, use HARD STOP if the dependency is critical.

AGENTS.md

A short file (~30-60 lines) with validation commands and code constraints. Lives alongside PLAN.md in the worktree.

# Agent Instructions

## Validation Commands
Run these after every task. All must pass before marking [x].
- `npm run build`
- `npm test`

## Code Guidelines
- Follow existing patterns in the codebase
- Keep changes minimal — fix the specific issue, don't refactor surroundings
- Do not add new dependencies without justification

## Stuck Protocol
If tests fail 3 times on the same issue:
1. Add a STUCK note to the task in PLAN.md
2. Move to the next task
3. Do NOT disable tests or loosen types

The Loop Script

loop.sh handles the full lifecycle:

  1. Pre-flight checks — PLAN.md exists, AGENTS.md exists
  2. Dependency installnpm ci for Node projects (worktrees don't have node_modules)
  3. Env file setup — symlink .env.local from main repo
  4. Pre-flight build — verify the baseline compiles before starting
  5. Main loop — invoke claude -p with scoped permissions, check for completion
  6. Safety net — auto-commit staged changes if agent didn't commit

Scoped Permissions

The --allowedTools flag pre-approves specific tools so the agent runs unattended:

--allowedTools "Edit" "Write" "Read" "Glob" "Grep" \
  "Bash(npm run build)" "Bash(npm test)" \
  "Bash(git add *)" "Bash(git commit *)" "Bash(git diff *)" "Bash(git status)"

Critical: Do NOT use Bash(*). Scoped permissions prevent the agent from running unexpected commands.

The Auto-Commit Safety Net

In production, the agent commits on its own about 1 in 9 times. It reliably stages changes (git add) but rarely follows through with git commit. The safety net catches this:

if ! git diff --cached --quiet; then
  git add PLAN.md
  git commit -m "ralph: auto-commit from iteration $ITERATION"
fi

This is essential infrastructure, not optional.

Git Worktrees

Ralph loops use worktrees for isolation — each agent gets its own working directory and branch:

# Create
git worktree add -b fix/feature-a ../project-wt-feature-a

# Copy plan
cp .ralph/plans/feature-a.md ../project-wt-feature-a/PLAN.md

# Run loop
cd ../project-wt-feature-a
bash ../project/.ralph/loop.sh 15

# When done, merge and clean up
cd ../project
bash .ralph/cleanup.sh feature-a

Worktree Gotchas

Issue Solution
No node_modules loop.sh runs npm ci automatically
No .env.local loop.sh symlinks from main repo
Need -b flag git worktree add -b branch path for new branches
Stale symlinks loop.sh detects and removes them
Cleanup needs --staged git restore --staged --worktree . for full reset

Parallel Execution

Run multiple Ralph loops simultaneously in separate tmux windows:

# Launch (from main repo)
bash .ralph/launch.sh teammate-a .ralph/plans/teammate-a.md 15
bash .ralph/launch.sh teammate-b .ralph/plans/teammate-b.md 20

# Monitor from main window
while true; do
  clear
  for wt in teammate-a teammate-b; do
    echo "=== $wt ==="
    grep '^\- \[' ../project-wt-$wt/PLAN.md
    echo ""
  done
  sleep 10
done

# Clean up when done
bash .ralph/cleanup.sh teammate-a
bash .ralph/cleanup.sh teammate-b

Cost

Approximate per-iteration cost with Claude Sonnet: ~$1-2. A 10-task feature across 3 worktrees typically costs $15-25 total.

Always set max_iterations to cap cost. If the agent can't solve it in N iterations, it's better to escalate to a human than burn tokens.

References