Anyone who has run a coding agent on a real task β not a demo, a multi-hour grind through a milestone β has watched the same decay curve. The first hour is sharp. By the third, the agent is re-reading files it already read, contradicting decisions it made earlier, and confidently "fixing" things it broke twenty minutes ago. Nothing is wrong with the model. What's wrong is the session: the context window has filled up with stale file dumps, dead ends, and its own chatter, and the signal is drowning in it.
The fix that actually works in practice is embarrassingly stupid, and it has a name: the Ralph loop.
This isn't theory for me. I run this pattern today on Zenve3D: I hand a master agent a milestone, it works through the issues one by one, and every worker starts with a fresh context while LLMBrain carries the project state between them. The rest of this post is how that works, from the dumb bash loop it started as to the skill it became.
The technique comes from Geoffrey Huntley, who named it after Ralph Wiggum from The Simpsons β the kid who is not the sharpest but keeps cheerfully showing up. In its original form it is literally this:
while :; do
cat PROMPT.md | claude -p
done
That's it. Run the agent with the same prompt, in a fresh session, forever. Each iteration the agent wakes up blank, reads the plan file, picks the most important unfinished item, does that one thing, writes its progress back to disk, and dies. The loop restarts it. Repeat until the plan is empty.
The genius is in what the loop doesn't do. It doesn't try to keep one long-lived, ever-smarter session alive. It accepts that a fresh context window is the most valuable resource an agent has, and spends it deliberately: one full window per unit of work, then throw the session away.
People have used this to build entire codebases overnight. Not because each iteration is brilliant β individual iterations occasionally do something profoundly dumb, which is why it's named after Ralph β but because the loop is relentless and the dumb iterations get corrected by later ones. It's stochastic gradient descent for software: noisy steps, consistent direction.
It's worth being precise about the failure mode, because "the context window is too small" is not it. Windows are enormous now. The problem is that an agent's judgment degrades long before its window fills β retrieval gets worse, instructions from fifty turns ago stop binding, and the model starts attending to its own earlier mistakes as if they were ground truth. This degradation is commonly called context rot.
You cannot prompt your way out of it, because the prompt is in the rotting context. The only real fix is architectural:
State lives outside the model. Sessions are disposable.
Once you frame it that way, the Ralph loop stops looking like a hack and starts looking like a design pattern. The deterministic outer loop (bash) holds nothing. The stochastic inner agent holds everything β for exactly one task. Between iterations, the only thing that survives is whatever the agent wrote down: files on disk, commits in git, checkboxes in a plan.
Which exposes the pattern's one weak point. A Ralph loop is only as good as its external memory. The naive version stores state in markdown files scattered through the repo β PROMPT.md
, fix_plan.md
, a TODO
section the agent rewrites every pass. It works, but it's fragile: the plan file and reality drift apart, "why did we decide this?" has no home and gets re-litigated every third iteration, and none of it carries across repos or machines. The loop has a body; what it needs is a brain.
This is exactly the shape LLMBrain was built for. It's a hosted MCP server that acts as a cross-project brain for coding agents: canonical docs per project (architecture, data model, product, status), milestones and issues as the roadmap, an append-only decision log, and small remembered facts β all readable and writable by the agent itself, from any session, in any repo clone.
Wire that into a Ralph loop and every piece of loop state gets a proper home:
βββββββββββββββββββββββββββββ
β LLMBrain β
β β
β status doc where we are β
β issues the queue β
β comments handoffs β
β decisions the "why" β
βββββββββββββββ²ββββββββββββββ
β read / write
ββββββββββββββ΄βββββββββββββ
β β
βββββββββ΄ββββββ βββββββ΄βββββββββ
β iteration N β fresh ctx β iteration N+1β
β pick β work β βββββββββββΆ β pick β work β
βββββββββββββββ ββββββββββββββββ
session dies; the state above survives
Concretely, each iteration of the loop maps onto brain calls:
start_session
returns the project card, the status doc, and the open issues β the agent knows where the last iteration left off without grepping the repo for a plan file.in_progress
when it picks it up and done
when it finishes β in the master/worker variant below, closing an issue is deliberately the master's job β so the queue doesn't silently drift from reality the way a hand-edited plan file does.The loop stays dumb. The memory gets smart. And because the brain is hosted and cross-project, the same loop pattern works on every project you own, with nothing to set up in the repo.
LLMBrain ships this as a skill, so you don't hand-assemble the loop. In Claude Code:
/work-on-milestone M1
Here's what that looks like on a real project β the master agent opening the loop on a Zenve3D milestone, ordering twelve issues into a queue and handing the first one to a fresh worker:
This starts a Ralph loop over everything in the milestone β with one twist on the classic recipe. Instead of a bash while
loop restarting the whole process, there is a master agent that never writes code. Its instructions open with the whole idea in two sentences: you do not write the code; you pick the work, hand each issue to a fresh worker agent, and keep the brain honest about where things stand. The master's context stays cheap β it holds conclusions, never file contents β so it can run the loop for hours without rotting itself.
Each pass through the loop:
in_progress
.done
β deliberately its job, not the worker's, so a worker that dies silently can't close work it didn't finish β relays a two-line summary to you, and picks the next issue.Workers run sequentially, not fanned out, because issues in one milestone routinely touch the same files, and two agents editing one working tree corrupt each other in ways that surface hours later. And when an issue says "owner's call", the master doesn't stall the queue to ask: reversible calls with a cheap option get taken and flagged in the relay; irreversible or product-shaped ones get parked for you. You launched a loop precisely so you wouldn't have to sit in it.
The loop ends when the milestone has no open issues, when you stop it, or when everything left needs a human decision. On the way out it does the thing naive Ralph loops always skip: comments on any unfinished issue with the tree state and where to resume, records the loop's own decisions, and updates the status doc β so the next loop's first start_session
call starts exactly where this one stopped.
Worth naming the adjacent thing, because Claude Code now ships it natively: /goal keeps a single session re-running until a condition you set is met. It's useful, and it's solving a different problem. A
/goal
session grinds toward its condition inside one context window β the very thing that rots β and everything it learned dies with the session. The Ralph loop makes the opposite trade: fresh context per issue, with the state that matters held outside the session entirely, where the next loop, the next repo clone, or the next machine can read it.The Ralph loop's insight is that agent sessions should be cattle, not pets: fresh context per unit of work, all state external, let the loop grind. What the original bash version leaves unsolved is the quality of that external state β and that, more than the loop itself, is what determines whether hour six is still productive.
Give the loop a real brain β a queue that stays honest, handoffs that survive death, decisions that don't get re-litigated β and the pattern stops being a party trick for overnight demos and becomes a way you actually ship: point it at a milestone, walk away, and come back to a working tree and an honest account of what happened.
/work-on-milestone M1
. That's the whole workflow.
I'm building this into LLMBrain right now, and it's what runs my own projects. If you're experimenting with long-running coding agents and want a brain behind your loops, try it β and tell me what your loops do with it.
This post was first published here: https://www.ghalex.dev/blog/running-agents-in-a-ralph-loop