The Ralph Wiggum Loop: One Prompt, Fresh Context, Repeat
The Ralph Wiggum loop runs one prompt against your repo in a bash while true, with fresh context every iteration. No orchestration framework, no agent graph, no memory store. The architecture is three lines of bash; everything else is markdown files in the repo.
Geoffrey Huntley named and popularized the pattern (ghuntley.com/ralph) and used it to brute-force entire codebases into existence. The name is accurate: like Ralph from The Simpsons, the loop has no plan and keeps going anyway. This guide covers how it works, why fresh context wins, where it fails, and how to run one without letting it eat your repo.
The loop
while :; do claude -p "$(cat prompt.md)" --dangerously-skip-permissions done
Everything interesting lives in prompt.md and in the files the agent reads and writes between iterations.
Why fresh context beats a long conversation
A long-running session sounds smarter because it remembers what it tried. In practice, long agent sessions degrade: the context fills with stale diffs, dead ends, and the model's own earlier mistakes, and quality slides with it.
Ralph inverts this. Every iteration starts clean. The agent knows exactly three things:
1. The prompt (prompt.md, same every time)
2. The repo state (whatever previous iterations committed)
3. Whatever files the prompt tells it to read first
All state lives in the repo. A backlog file tracks what's done, a guardrails file accumulates hard-won lessons, and git history is the memory. Each iteration picks one item, does it, commits, and dies. The next iteration is born knowing only what got written down.
That is why Ralph survives overnight runs where a single session would collapse: iteration 200 is exactly as sharp as iteration 1.
Anatomy of prompt.md
A working Ralph prompt has four sections. Here is a condensed real-world shape:
# Task Read BACKLOG.md. Pick the FIRST unchecked item. Implement it completely.
Rules - Read GUARDRAILS.md before doing anything. Follow every rule in it. - ONE item per run. Do not start a second item. - All tests must pass before you commit: `npm test` - Commit with message "ralph: <item>". Check the item off in BACKLOG.md.
When you get stuck - If blocked, write the blocker under the item in BACKLOG.md and stop.
Before you exit - Append anything you learned the hard way to GUARDRAILS.md (a gotcha, a convention, a command that doesn't work here). ```
The two files it references do the heavy lifting:
- BACKLOG.md — the work queue. A checklist of small, independent items. The loop's exit condition is "no unchecked items remain."
- GUARDRAILS.md — the learning file. This file decides whether the loop converges or makes the same mistake 40 times.
The guardrails file: Ralph's only memory
Every iteration has amnesia, so mistakes repeat by default. Iteration 12 rediscovers that the test suite needs DATABASE_URL set. Iteration 13 rediscovers it again.
The fix: every iteration ends by appending lessons to GUARDRAILS.md, and every iteration begins by reading it. Signal compounds:
# GUARDRAILS.md - Tests need `DATABASE_URL=postgres://localhost:5432/test` exported. - Do NOT touch src/billing/ — human review required. - `npm run lint -- --fix` breaks the generated files in src/gen/. Never run it there. - The e2e suite is flaky on first run after migration; run migrations first.
Each failure gets written down once and stops recurring. The loop learns your repo's rules one mistake at a time. ralph-guardrails-learning in the directory is a ready-to-run version of this pattern.
What Ralph is good at
Ralph fits work that is a queue of small, verifiable, independent items:
| Work | Directory loop |
|---|---|
| Burning down a PRD, feature by feature | ralph-prd-backlog |
| Adding test coverage file-by-file | ralph-test-backlog |
| Mechanical refactors across a codebase | ralph-refactor-backlog |
| Docs that trail the code | ralph-docs-backlog |
| A bug list nobody wants | ralph-bug-backlog |
Common thread: each item fits in one context window, each item has a mechanical check (tests pass, types compile), and no item depends on the loop remembering another. Everything Ralph-shaped is at /type/ralph.
Where Ralph fails
Know the failure modes before you run one overnight:
| Failure mode | What happens | Fix |
|---|---|---|
| Architectural work | "Redesign the data layer" produces 30 commits pulling in 30 directions | Design first; give Ralph the resulting task list |
| Vague backlog items | "Improve error handling" churns plausibly forever | Every item must be mechanically checkable |
| Reward hacking | With --dangerously-skip-permissions, deleting a test satisfies "make tests pass" | Forbid it in GUARDRAILS.md and verify test count in an evaluator |
| No budget | A raw while : runs until your API bill stops it | for i in $(seq 1 50), plus a wall-clock timeout |
These failure modes show up directly in the directory's safety grades: most Ralph loops land at C or below, mostly for missing exit conditions and turn caps. Disciplined Ralph loops still grade A — some score a perfect 100.
A safer Ralph
The production version adds a budget, isolation, and a completion check:
git worktree add ../ralph-run && cd ../ralph-run for i in $(seq 1 50); do claude -p "$(cat prompt.md)" --dangerously-skip-permissions grep -q "\- \[ \]" BACKLOG.md || break # exit when backlog is empty done
Run it in a worktree so a bad night costs you nothing. Review the commits in the morning the way you'd review a junior's PR stack, because that is what it is. If you want the loop to email you when the backlog hits empty (or when it stalls), ConnectMyEmail gives your agent an email channel without you writing SMTP glue at midnight.
Roll your own
Start with a backlog of 5–10 genuinely small items, a guardrails file pre-seeded with your repo's known gotchas, and a 20-iteration cap. The loop builder generates the prompt.md, the harness script, and the safety rails for you — pick the Ralph template and fill in your backlog.