โ† All guides
๐Ÿ—บplanning

What Is Loop Engineering? The Discipline After Prompting

What Is Loop Engineering? The Discipline After Prompting

Prompt engineering was about getting one good answer out of one model call. Loop engineering is about getting one good *outcome* out of many model calls you never watch. You stop writing prompts and start writing the machine that writes them: the goal, the exit condition, the budget, the guardrails, and the state that survives between iterations.

The people building these tools already made the switch. Boris Cherny, who leads Claude Code at Anthropic, told the Pragmatic Engineer that 100% of his Claude Code contributions are now written by Claude Code โ€” 259 PRs landed in 30 days โ€” and he's described his job bluntly: he doesn't prompt Claude anymore. He has loops that prompt Claude. "My job is to write loops." Peter Steinberger said the same thing from the OpenAI side: stop prompting coding agents, start "designing loops that prompt your agents." Addy Osmani put a name on the discipline โ€” and a warning: the same loop gives opposite results depending on who runs it, and the whole thing rests on a verifiable stopping condition. Build loops like someone who intends to stay the engineer.

That last clause is the actual job description. Loop engineering isn't "press go and leave." It's designing a system where leaving is *safe*.

The definition

Loop engineering is the practice of designing agent runs as bounded, verifiable, restartable loops instead of supervised conversations. Five design decisions, made up front:

GOAL:    one concrete outcome ("all tests pass", not "improve tests")
CHECK:   a command whose exit code proves it (npm test && npm run lint)
BUDGET:  max iterations AND max wall-clock AND max spend
SCOPE:   what the agent may touch (worktree, allowed paths, tools)
STOP:    what happens on repeated failure (notes + halt, never retry forever)

If you've written a cron job, a CI pipeline, or a supervisor config, you already know the shape. The new part is that the worker inside the loop is nondeterministic, motivated, and perfectly happy to delete the failing test instead of fixing it. So the loop, not the model, has to hold the line.

The loop stack

In Claude Code, loop engineering has first-class primitives. Learn these four and you can read every entry in [the directory](/loops) at a glance.

### /loop โ€” interval reruns, in-session

/loop 5m check the deploy re-runs a prompt while your session stays open. Give it no interval and Claude self-paces between 1 minute and 1 hour based on what it observed last iteration. Loops are session-scoped โ€” they live in the current conversation and expire after 7 days by design, so a forgotten loop can't run forever. Drop a loop.md in .claude/ and bare /loop runs *your* maintenance prompt instead of the built-in one โ€” that's a team-wide default loop in one Markdown file. Browse the pattern at [/type/loop](/type/loop); [ship-pr-until-green](/loops/ship-pr-until-green) is the canonical "poll until done" example.

### /goal โ€” run until a condition is true

/goal all tests pass; verify with npm test sets a completion condition, and after every turn a small fast model (Haiku by default) checks the transcript: condition met? No โ†’ another turn, with the evaluator's reason as guidance. Yes โ†’ the goal clears itself. Two things loop engineers must know: the evaluator only reads the transcript โ€” it can't run commands โ€” so your condition has to be provable from output Claude surfaces ("npm test exits 0"). And there is no built-in turn cap โ€” you write the cap into the condition itself: ...or stop after 20 turns. [fix-tests-and-lint](/loops/fix-tests-and-lint) and [kill-flaky-tests](/loops/kill-flaky-tests) are goal loops; more at [/type/goal](/type/goal).

### /schedule โ€” cloud routines

/schedule daily PR review at 9am creates a Routine: your prompt plus repos plus connectors, running on Anthropic's cloud with your laptop closed. Minimum interval is 1 hour, runs get no permission prompts at all, and blast radius is controlled structurally โ€” fresh clones, pushes restricted to claude/-prefixed branches by default, a daily per-account run cap. Routines can also fire from an API endpoint or GitHub events, which turns "cron for agents" into "event-driven agents." See [/type/schedule](/type/schedule).

### Ralph โ€” brute force with fresh context

The [Ralph Wiggum loop](/loops/the-original-ralph-wiggum-loop) (Geoffrey Huntley's invention) is the maximalist move: the same prompt in a bash while true, fresh context every iteration, all state in files. It's dumb, it ships, and it's where loop engineering's rules were learned the hard way โ€” hard iteration caps, guardrails files, and never letting the loop grade its own homework. There's even a bashless variant using a Stop hook to re-inject the prompt: [stop-hook-ralph](/loops/stop-hook-ralph-deterministic-loop-without-bash). The family lives at [/type/ralph](/type/ralph).

Anatomy of a harness

A harness is everything wrapped around the model call. Whatever stack you use, the load-bearing parts are the same:

1. The reload. Fresh-context loops know nothing except what they re-read from disk or GitHub each iteration. As saulius.io puts it: "you engineer the reload." Progress files, issue labels, PR comments โ€” design the rehydration path, not the conversation. 2. The check. Machine-verifiable, external to the model. Tests, builds, linters. The claudefa.st Ralph guide's rule: Ralph works "when you can verify success programmatically... rather than relying on Claude to self-assess completion." 3. The budget. Iteration cap, timeout, and spend cap, enforced by the harness. Headless runs give you --output-format json with total_cost_usd per invocation โ€” log it, sum it, kill at the threshold. 4. The stop taxonomy. The OpenAI Cookbook's iterative repair loop names the four legitimate reasons a production loop stops: validation passes, max attempts reached, the remaining delta stops changing, or the next decision needs human review. If your harness can't detect all four, it isn't done. 5. The evaluator gate. Before accepting a result: did the diff stay in scope? Did test count go *down*? Default-fail โ€” if the gate can't tell, reject. Then grade the whole thing against a checklist; our [safety grader](/grade) does exactly that for any loop you paste in.

One more piece of plumbing people forget: a loop that runs while you sleep needs a way to reach you when it finishes or wedges. Wiring email into an agent is its own yak-shave โ€” ConnectMyEmail exists so the loop just sends the email and gets back to work.

Why this is a discipline and not a vibe

Because the failure modes are real, documented, and expensive โ€” wiped home directories, subagent recursion burning millions of tokens, weekend refactors that turn into four-figure bills. We catalog the documented incidents (with sources) in our loops-gone-wrong guide, and every one traces back to a missing slot in the five-line skeleton above. The difference between an automation and an incident is rarely the model. It's the loop.

Start engineering

Pick one chore with a mechanical check โ€” failing CI is the classic. Write the five slots. Run it in a worktree. Watch the first three iterations, then stop watching.

Or skip the boilerplate: the [loop builder](/builder) walks you through goal, check, budget, scope, and stop, and hands back a harness you can run tonight. When it's written, run it through [/grade](/grade) before you leave it alone with your repo. That's loop engineering: the prompt was never the product โ€” the loop is.

Ready to run one? Browse the loop directory โ†’