I used to hear “AI coding in a loop” and picture AutoGPT — an agent chasing its own tail, burning tokens, somewhere deep in hallucinated output.
That was my mental model until a few weeks ago. Vague. Wrong. Missing the entire point.
What finally clicked: Ralph isn't a tool. It's a shift in what your job is. You stop writing application code and start engineering the environment that produces it. The loop is the heartbeat. The prompts, backpressure, and operational guide are the actual program.
What is a Ralph Loop, actually?
At its core:
while :; do cat PROMPT.md | claude ; done
That's the orchestrator. The whole thing. No message queues, no state machines, no agent frameworks. Just bash.
Each iteration is a sealed transaction:
- Claude reads
PROMPT.md(instructions) +AGENTS.md(how to build) - Claude reads
IMPLEMENTATION_PLAN.md(what's left) - Picks the top undone task
- Implements it, runs the tests
- Tests must pass before anything gets committed — this is backpressure
- Commits, pushes, exits — context window destroyed
- Bash loop restarts → fresh context → next task
The loop is the heartbeat. Files on disk are the memory. No conversation history, no context drift, no “wait, what were we doing again?”
Two modes. PLANNING: reads your spec files, does a gap analysis against the codebase, generates IMPLEMENTATION_PLAN.md. BUILDING: reads that plan and executes, one task per iteration. The requirements phase — defining what to build and writing specs — happens outside the loop entirely, as a normal human + LLM conversation.
What problem does this actually solve?
If you've used Claude Code or Cursor for anything non-trivial, you know this pattern. First hour is great. By hour three, the context window is bloated. The model forgets constraints you set earlier. It repeats work. It drifts.
Ralph's answer: never accumulate context. Every task gets a fresh window. The model operates in what Huntley calls the “smart zone” — 40-60% context utilisation — for every single task. No degradation.
Then there's correction cost. In a normal session, when the LLM goes off-course, you regenerate within the same conversation. But stale assumptions from earlier messages are still in context, silently steering things wrong. With Ralph, you throw away the plan and regenerate it. One loop iteration. Free.
And the quietest problem: “did you actually run the tests?” Without enforcement, LLMs will happily tell you everything passed when it didn't. Ralph's backpressure makes it non-negotiable — tests run within the iteration, and commits only happen after they pass. CI pipeline, collapsed into each loop cycle.
Where does this fit alongside harnesses and spec-driven tooling?
These three things aren't competitors. They're layers.
| Layer | What it does | Example |
|---|---|---|
| Spec-driven tooling | Generates structured specs, validates scope | Spec Kit, Open Spec |
| Ralph Loop | Execution discipline: context reset, backpressure, commits | The bash loop |
| Harness | Runtime: LLM + tools + subagents + file access | Claude Code, Cursor, pi |
Spec Kit writes specs/. Ralph reads those specs and builds. The harness provides the LLM and tool access. Each layer does one thing — they compose cleanly.
Ralph adds what neither layer provides: execution discipline. A harness gives you an LLM with tools. It doesn't give you context resets, backpressure enforcement, or commit boundaries. Spec Kit gives you structured requirements. It doesn't execute them. Ralph sits in the middle, turning specs into commits with a rhythm you can watch and steer.
Your first Ralph Loop: a todo app
The setup is almost embarrassingly simple. Six files. That's it.
todo-app/
├── loop.sh # Heartbeat
├── PROMPT_plan.md # Planning instructions
├── PROMPT_build.md # Building instructions
├── AGENTS.md # Build/run commands
├── IMPLEMENTATION_PLAN.md # Generated by Ralph (start empty)
├── specs/
│ └── 01-task-management.md
└── src/ # Ralph writes this
Step 1 — Write a spec. Outside the loop. Just describe what the app should do:
# specs/01-task-management.md
Users can create, read, update, and delete todo items.
Tasks persist across page reloads (localStorage or backend).
Step 2 — Write AGENTS.md. Operational knowledge. What Ralph needs to build and test your project:
## Build & Run
- Install: `npm install`
- Dev server: `npm run dev`
- Tests: `npm test`
- Typecheck: `npx tsc --noEmit`
Step 3 — Write loop.sh. The heartbeat:
#!/bin/bash
PROMPT_FILE="PROMPT_build.md"
if [ "$1" = "plan" ]; then PROMPT_FILE="PROMPT_plan.md"; fi
while true; do
cat "$PROMPT_FILE" | claude -p --dangerously-skip-permissions --verbose
git push origin "$(git branch --show-current)"
echo "======== LOOP ITERATION COMPLETE ========"
done
Step 4 — Run it. ./loop.sh plan generates your task list. ./loop.sh starts building, one task per iteration. Watch the loop — watch where it fails. That's where you add a guardrail or a better test. You're not debugging the code. You're tuning the environment.
The prompts you start with won't be the prompts you end with. Start with a nearly empty AGENTS.md and add only what Ralph actually needs. One guardrail worth adding on day one: “don't assume not implemented.” Without it, Ralph will happily rewrite your entire codebase every iteration.
The meta-programming framing is the thing I keep coming back to. You're not writing a todo app. You're writing the program that writes todo apps. The six files in your repo are the real source code. Everything in src/ is just output.
The loop is dumb. That's the point. The intelligence is in the environment you build around it.
Ideas to develop further:
Cost economics — what does 500 Sonnet subagents per planning iteration actually cost for a real app?
Team workflows — the playbook is single-dev; how does code review and merge conflict resolution work with Ralph?
Non-coding use cases — does the spec→plan→build funnel transfer to research, writing, or design work?