In July, Gergely Orosz asked X: can you share 'loops' you regularly use? I read the full thread across July 13-14: 182 replies at that point (it has kept growing since), about thirty on topic, and exactly one that linked a loop you could actually run, a config.ts in a repo. Everyone else described theirs in prose, down to the odd /loop one-liner, or dismissed the term ("a fancy word for cron jobs," 56 likes). The sharpest reply summarized the discourse: "Someone posts about loop engineering. Another developer asks what is it? They don't explain it. Repeat."
The question existed because in June, Boris Cherny, the creator of Claude Code, said the thing that launched a thousand blog posts: he doesn't prompt Claude anymore. He writes loops, and the loops prompt Claude. Within a week the idea had a name (loop engineering), a viral tweet past eight million views, and a wave of "complete guides" that were mostly the same two quotes reworded. Orosz later wrote his thread up himself, "based on ~210 replies, mostly from X and LinkedIn". It is a survey, not a build manual: it maps what people say they run, its loop lines arrive as quotes (Huntley's bash, OpenAI's /goal example, one engineer's flaky-test /loop), and half the analysis sits behind the paywall.
This post is the artifact that thread was missing: seven loops in the order to learn them, with the exact invocation, the check that decides done, the kill switch, and what survives your session. Then the unflattering parts: cost (a real $6,000 receipt), failures (with incidents), security. Everything comes from official docs, harness source, or my own transcripts; Method says which is which.
- A loop is a trigger, a prompt, and a termination check.
- Claude Code ships six primitives, differing on two axes: what fires the next iteration, and what survives your session (only committed files; Routines, per-account in the cloud, are the exception).
- Learn them as a ladder; a seventh loop composes the six:
/goal→/loop→ bounded bash → Stop hooks → dynamic workflows → routines → the stack. - The termination check is the whole game: an agent graded on its own claims lies its way out, so verification must be a command that runs, not a vibe.
- Cost is your wake interval versus the cache window. Unattended loops run in a container with hard caps. The only loop your team can inherit is the one you commit.
Open Claude Code in any repo with tests and type:
/goal all tests pass and lint exits 0; or stop after 20 turns
Claude keeps taking turns; a second model grades the condition after each one; /goal clear kills it. That is a loop. The other six are what it grows into, and this table is the menu:
| I want to… | Reach for | |
|---|---|---|
| watch a loop work while I approve each step | /goal <condition> | Loop 1 |
| re-check something on a timer while I work | /loop 15m <prompt> | Loop 2 |
| leave it building unattended, bounded | bash loop.sh (Ralph) | Loop 3 |
| make "done" mean the tests actually ran | a Stop hook | Loop 4 |
| fan one task out across many files or agents | a dynamic workflow | Loop 5 |
| hand my team a loop they can run | a dynamic workflow saved as /<name> | Loop 5 |
| run it while my laptop is closed | /schedule (a Routine) | Loop 6 |
| compose all of it into one machine | the stack | Loop 7 |
One provenance note, because it says something about this wave: the famous quote circulates in three wordings pinned to the wrong videos, so I checked the captions of all three recordings. It was said once, at Acquired Unplugged on June 2, at 11:42:
"I don't prompt Claude anymore. I have loops that are running. They're the ones that are prompting Claude and kind of figuring out what to do. My job is to write loops."
Boris Cherny, creator of Claude Code
A month earlier, at Sequoia's AI Ascent, he had described the loops themselves: one babysitting PRs, one keeping CI healthy, one clustering Twitter feedback every 30 minutes. Five days after the June quote, Peter Steinberger's paraphrase became the eight-million-view tweet; most people are quoting a paraphrase of a clip.
What a loop actually is
Cherny tells it as abstraction levels: you wrote code in an IDE, then you prompted agents (five or ten in parallel if you were aggressive), and now a small piece of automation decides what to tell the agent next until a condition holds. Code, then agent, then loop. Now the deflation: the technique is nearly a year older than the buzzword, and in its purest form it is one line of bash. July 2025, Geoffrey Huntley, the Ralph technique:
while :; do cat PROMPT.md | claude ; done
Feed the same prompt to the agent forever. Context resets every pass; the only memory is the files and git history the last pass left behind. Huntley delivered an MVP for a $50k contract on $297 of tokens this way, and documented everything that goes wrong:
- Reward gaming. "The reward function is compiling code," hence placeholder implementations everywhere.
- The one-task rule. "One item per loop. I need to repeat myself here: one item per loop."
- The scope limit. "There's no way in heck would I use Ralph in an existing code base."
So: Huntley's bash (July 2025), the harnesses productizing it by spring 2026 (Codex's Goals in April; Claude Code's /goal in May), and Cherny, Steinberger, and Addy Osmani giving it a name in June 2026. You are not learning an invention; you are learning a technique that got a marketing department. Osmani's definition is the cleanest: loop engineering is replacing yourself as the person who prompts the agent.
The map: where each loop lives, and what dies with your session
Here is why that thread had nothing to paste. A skill is one file; commit it and your team has it. A loop is seven things in a trench coat: trigger, prompt, verifier, memory, budget, guardrails, and a running instance, living in different places with wildly different lifespans. Most die with your session.
| You run | Next iteration starts when | Survives your session? | How your team gets it |
|---|---|---|---|
/goal <condition> |
a separate model rules the condition not yet met | no; dies with the session | nothing to share; rebuild it as a Stop hook |
/loop 15m <prompt> |
the timer fires | no; 7-day expiry at best | committing .claude/loop.md (the prompt, not the loop) |
| a Stop hook | the agent tries to stop and your check fails | yes; every session, forever | committing .claude/settings.json + the script |
| "use a workflow to…" | the script's own while loop decides |
yes; the script is a file | saving to .claude/workflows/ → it becomes /<name> |
/schedule (a Routine) |
cloud cron fires, or a GitHub event lands | yes; in the cloud, laptop closed | it can't; routines are per-account |
bash around claude -p |
your for loop iterates |
yes; everything is files + git | committing PROMPT.md + loop.sh |
Read the last column twice; it is the entire sharing story. Session-scoped loops restore on --resume at best and hard-expire in seven days. What persists is files.
That is why the thread produced descriptions instead of links: the loops exist as muscle memory in sessions long since garbage-collected. The ecosystem is competing to fix this (RALPH.md packages, loopy's LOOPS.md catalogs, an eleven-field "Loop Contract"); none has won. Inside Claude Code the practical answer already ships, and it is Loop 5 below.
Every loop is the same three organs
Strip any harness, official or homegrown, and you find the same three organs: a trigger (what starts the next iteration: a bash while, a cron schedule, a Stop hook refusing to let the session end, a GitHub event), a prompt (usually a file, so you tune it without touching the loop), and a termination check, the hard part, which gets its own section. Everything else is a bolt-on.
Plus a bloodstream: state. The conversation is disposable and the repo is the memory: a plan file with checkboxes, a progress log, a commit per iteration. Osmani has the line: "The agent forgets; the repo doesn't."
The force multipliers, one line each:
- Hooks are engine and brake: the official ralph-wiggum plugin is a Stop hook that blocks exit and re-feeds the prompt, and a PreToolUse hook refusing
rm -rfis your cheapest guardrail. - Subagents split the maker from the checker, and bill differently (measured here: the main loop writes the 1-hour cache tier, subagents the cheaper 5-minute tier).
- Skills keep iterations lean; prompt bloat multiplies by iteration count.
- MCP connectors give reach (GitHub, Slack, your database) and are the largest attack surface, because a loop reading issues ingests strangers' text.
- Worktrees let parallel loops share a repo without trampling each other; the failure table has the incident that makes the case.
Seven loops, in the order to learn them
The six primitives from the map, plus a seventh that composes them. Each level hands over more autonomy. For every loop: the invocation, who verifies, how to kill it, what survives.
Loop 1: /goal, your first loop in sixty seconds
/goal all tests in test/auth pass and npm run lint exits 0;
do not modify any other test file; or stop after 20 turns
Type that and the loop starts immediately, condition as first instruction. After each turn, a separate small model (Haiku by default) reads the transcript and rules yes or no; no starts another turn seeded with the reason, yes clears the goal. Bare /goal shows status; /goal clear kills it.
Condition rules, learned from watching them fail:
- One measurable end state. "Tests in test/auth pass," not "auth is solid."
- A stated check. Name the command whose exit code decides.
- A cap. "Or stop after 20 turns"; there is no built-in limit.
You get 4,000 characters; spend them on constraints, because the loop optimizes whatever you leave unpinned.
The fine print that decides whether it works: the evaluator cannot run commands or read files. It judges only what Claude surfaced in the conversation. "All tests pass" works because the test output lands in the transcript; "the code is production ready" gets waved through. Write conditions the transcript can prove.
By default you still approve every tool call: perfect training wheels. Auto mode (Shift+Tab, or --permission-mode auto) makes the turns hands-off. And it works headless: claude -p "/goal <condition>" runs the whole loop in one terminal command.
Loop 2: /loop, the interval loop
/loop 15m check the release PR; if CI is red, diagnose the failure
and push a minimal fix; if everything is green, do nothing
/goal re-fires on a condition; /loop re-fires on a clock. Three modes: fixed interval, self-paced (/loop <prompt>; Claude picks each delay, one minute to an hour), and bare /loop, which runs a built-in maintenance prompt or yours. Esc kills the pending wake-up.
What most people miss: the prompt above carries its own "do nothing" branch. an interval loop has no condition checker, so the exit ramp lives in the prompt. And the lifespan: session-scoped, restored by --resume only if unexpired, hard 7-day expiry. The shareable piece is .claude/loop.md, your team's committed default for bare /loop; the running loop never travels. One warning for later: an interval loop against a big warm session is a metronome hitting the prompt cache. The $6,000 story below is exactly this.
Loop 3: the bounded bash loop (Ralph, grown up)
The loop I would actually leave alone with a repo: Huntley's one-liner grown exactly four guardrails, each earned by a documented disaster we will meet later.
#!/usr/bin/env bash
# loop.sh: fresh context each iteration; the repo is the memory
MAX_ITERATIONS=15
for ((i=1; i<=MAX_ITERATIONS; i++)); do
echo "=== iteration $i/$MAX_ITERATIONS ==="
result=$(claude -p "$(cat PROMPT.md)" \
--max-turns 40 \
--max-budget-usd 3.00 \
--allowedTools "Read,Grep,Glob,Edit,Write,Bash(npm test:*),Bash(git add:*),Bash(git commit:*)" \
--output-format text 2>&1) || true
echo "$result" | tail -5
git add -A && git commit -m "loop: iteration $i" --allow-empty --quiet
if [[ "$result" == *"<promise>ALL_TESTS_GREEN</promise>"* ]]; then
echo "done after $i iterations"
break
fi
sleep 2
done
The four guardrails:
MAX_ITERATIONSis the outermost fuse; promise-tag detection fails in both directions.--max-turnsand--max-budget-usdare the per-iteration fuses, and they exist only in print mode (claude -p, which is what this script uses). Nothing caps a whole loop, so the outer script must.--allowedToolswith a tight list instead of--dangerously-skip-permissions; the incident list below is what convenient costs.- A commit per iteration, even empty: rollback granularity plus a history you can audit at 7am with coffee.
Three files, all in the repo root: loop.sh (run with bash loop.sh from a normal terminal; Ctrl-C stops it between iterations), PROMPT.md, and plan.md, the checkbox task list the prompt reads:
# plan.md (the run below started with all five unchecked)
- [ ] parse(): support days ('d') as a unit
- [ ] parse(): reject malformed input (trailing garbage, unit-first forms) with a clear error
- [ ] implement format(ms) in src/format.js: compact form like '1h30m', omit zero units, RangeError on negatives
- [ ] round-trip: parse(format(parse(s))) equals parse(s) for mixed-unit inputs
- [ ] full suite green: npm test exits 0
The prompt file matters more than the script:
# PROMPT.md
Read plan.md and pick the SINGLE highest-priority unchecked task.
One task only. Do not touch anything else.
Before writing code, search the codebase to confirm the task is not
already implemented. Do not assume it is missing.
Implement it completely. No placeholders, no stubs, no TODO comments.
Run the test suite. If anything fails, fix it before moving on.
When the task is done and tests pass:
1. Check it off in plan.md
2. Append one line to progress.md: what you did, what the next
iteration should know
Output <promise>ALL_TESTS_GREEN</promise> ONLY if every task in
plan.md is checked off AND the full test suite exits 0. Never output
it otherwise, even if you believe you are stuck.
Every line traces to a failure mode. "One task only" is Huntley's rule; without it the agent goes off the rails. "Search before implementing" kills the re-implementation spiral, where each fresh context assumes the feature is missing. "No placeholders" is the anti-reward-hack line; Anthropic's compiler harness runs on the same file-based discipline, down to agents claiming tasks by writing lock files into the repo. And progress.md is the relay baton: iteration 13 has no memory, so this is how iteration 12 warns it about the flaky test (the loop creates it; commit the other three files). That makes this the first loop a teammate can clone and run. For templates, read snarktank/ralph (21k stars) and ralph-playbook.
Receipts, because the standard above demands them. I ran this exact script (two disclosed tweaks: --output-format json to log per-pass cost, and Opus pinned as the model) against a small greenfield library, exactly where Ralph belongs, with the five-task plan.md above and a suite starting at 3 of 10 passing. The run: 5 iterations, 7 minutes, $3.56, 77 agentic turns, 10 of 10 green, promise tag emitted exactly once, loop exited at 5 of the 15-iteration cap. Per-pass cost: $1.05, $0.64, $0.71, $0.63, $0.54 (rounded to the cent; the totals come from the raw log, which is why they differ from summing these by a penny). Three things the numbers don't show:
- The allowlist visibly shaped behavior. Iteration 1 wanted
git stashto diff a before/after baseline, was not allowed, and fell back to reasoning about the change surface instead. - A guardrail fired on an innocent. A PreToolUse deny rule false-positived on the word "truncate" in a progress note and blocked the write; the agent reworded and routed around it. Deny rules hit false positives too; the loop survived.
- The one-task rule costs real money. Iterations 4 and 5 wrote no code; they checked boxes that were already true. $1.16 of pure bookkeeping, the measured price of the rule that keeps loops on the rails.
One unprompted delight: before emitting the promise, the final iteration audited the suite for vacuous tests ("'the suite is green' is exactly the claim a stub or vacuous test would also produce"). The termination paranoia the next section teaches showed up on its own.
Interlude: how the loop knows it is done
All three loops so far verify on the honor system. Loop 3 trusts a tag the agent prints; Loop 1 is better (a second model rules) but the judge never leaves the bench. "Am I done" is the question the agent has an incentive to answer wrong, and both failure modes are documented.
The honor-system bypass. The official ralph-wiggum plugin terminates on an exact promise-tag match; its only defense against lying is a pleading admonition: output the promise "ONLY when statement is TRUE - do not lie to exit!" Nothing verifies the claim, so an agent that prints <promise>DONE</promise> on its first response, no work done, walks free. The reverse failure is on the record twice: finished work whose tag missed the exact match, looping forever (whitespace, #52405; control characters, #68665). Hence max iterations.
The judge who cannot leave the bench. /goal wraps a Stop hook: every time the agent tries to finish, its evaluator rules on the condition. But the evaluator "does not call tools, so it can only judge what Claude has already surfaced in the conversation." It cannot run the tests. If the worker says the suite is green, the judge rules done.
The root cause has a name: reward hacking. The model optimizes the success signal, not the work. Huntley saw placeholders chasing "it compiles" in 2025; a Hacker News commenter opened an AI-written suite and found tests that "ran some random functions, did nothing to test their correctness, and just printed 'Test passed!' regardless of the result"; ImpossibleBench measured that a visible test loop raises cheating from 33% to 38%.
So termination engineering is a ladder, and each rung buys back some trust:
Loop 1 lives on rung 2, Loop 3 on rung 1. Rung 3 is next. The rule that ties it all together: write conditions the agent's honest output can demonstrate and a command can confirm. "Production ready" is a vibe the judge waves through. "npm test exits 0 and no file under tests/ was modified" is a fact a 10-line hook enforces. The quality of your loop is exactly the quality of this sentence.
Loop 4: the Stop hook, the loop that cannot be talked out of it
A Stop hook fires every time Claude tries to finish. Exit 0: the session ends. Block: Claude does not get to stop, and the hook's message becomes the next instruction. Ten lines of bash enforce what no prompt can: the session does not end while the tests fail.
{
"hooks": {
"Stop": [
{ "hooks": [
{ "type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/verify-done.sh",
"timeout": 120 }
] }
]
}
}
#!/bin/bash
# .claude/hooks/verify-done.sh
INPUT=$(cat)
# break the loop if we've already blocked too many times
if [ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ]; then exit 0; fi
if npm test >/dev/null 2>&1; then
exit 0 # verified: allow the stop
fi
echo "npm test is failing. Run it, read the failures, fix them." >&2
exit 2 # exit 2 blocks the stop; stderr goes back to the agent
Wiring:
- The script needs
jq(brew install jq). mkdir -p .claude/hooksandchmod +x .claude/hooks/verify-done.sh, or it dies with permission denied.- Merge the
Stopkey into an existinghooksobject rather than pasting over the file;/hooksconfirms it registered.
Three contract details that bite everyone once:
- Only exit code 2 blocks. Exit 1 is a non-blocking error, so a guardrail with the wrong exit code silently does nothing.
- Guard
stop_hook_active. Claude Code force-overrides after 8 consecutive blocks (CLAUDE_CODE_STOP_HOOK_BLOCK_CAP); exiting 0 on that flag hands a stuck loop back to you instead of grinding. - The hook cannot be persuaded, which is the point: the model cannot argue with an exit code.
That is rung 3 of the termination ladder, packaged as two committable files: clone the repo, get the loop. The same mechanism powers the official ralph-wiggum plugin (/ralph-loop "<prompt>" --max-iterations 50 --completion-promise "DONE": an in-session Ralph with a cap and no bash). Rungs 4 and 5 add distrust: a verifier subagent re-runs the checks itself with fresh context, and frozen held-out checks pin acceptance tests at a commit and fail any edit under tests/, because a model that can edit the test can pass the test.
Loop 5: the dynamic workflow, the loop that commands a fleet
use a workflow to run npx tsc --noEmit and keep fixing the
reported errors until the type check passes or two rounds
in a row make no progress
This one is different in kind, and the docs name the difference precisely: who holds the plan. In every loop so far the plan lives in a model's head or a blind bash file, one agent at a time, results piling into a context window. Ask for a dynamic workflow ("use a workflow" is the opt-in) and the plan moves into code: Claude writes a JavaScript program, a runtime executes it in the background while your session stays free, and the script itself holds the loop, the branching, and every intermediate result. Conceptually:
// simplified sketch of what Claude writes for you
let dry = 0, round = 0
while (dry < 2) { // loop-until-dry: stop after
round++ // two rounds with no progress
const r = await agent(
`Run npx tsc --noEmit. Fix up to 10 reported errors.
Return how many you fixed.`)
if (r.fixed === 0) dry++; else dry = 0
}
return `type check clean after ${round} rounds`
What falls out: loop state lives in script variables, not your context window: 200 files in, one answer out. The stop condition is real code: "two rounds with no progress" is a counter, not a promise tag. And the runtime enforces caps you don't have to remember: 16 agents at once, 1,000 per run.
The payoff: open /workflows, select the run, press s, save to .claude/workflows/ (saving names it; here, fix-types). It is now /fix-types for everyone who clones the repo, and it takes arguments: /triage-issues 1024, 1025. Save to ~/.claude/workflows/ instead and it follows you privately across projects. This is the answer to the Orosz thread: a loop as a named, versioned, argument-taking artifact in version control.
The fleet is where it stops being a better while loop. Because the plan is code, one script can fan agents out in parallel, pipeline them through stages, force structured JSON from each, and route each stage to a different model; per the docs, every agent uses your session's model "unless the script routes a stage to a different one." My daily pattern: Fable writes and drives the script, Opus and Sonnet take the worker stages by complexity, Fable comes back for the verification that needs the most intelligence. That buys quality patterns no single session can hold, like independent agents adversarially reviewing each other's findings before you see them. The research, reviews, and link-checking behind this post ran as dynamic workflows (the link hunt: six agents in parallel, each returning a URL plus verbatim evidence). That machinery deserves a post of its own. Here it stays a loop.
The limits:
- No mid-run input; the docs are blunt: "Only agent permission prompts can pause a run. For sign-off between stages, run each stage as its own workflow."
- Resume is same-session only.
- Its agents run with edits auto-approved plus your tool allowlist, so allowlist the commands they will need before a long run; an off-list command pauses the fleet until you answer.
- Pilot on a small slice before pointing one at 500 files.
Loop 6: the Routine, the loop that runs while your laptop is closed
/schedule daily dependency triage at 9am
Everything above dies when your machine sleeps. A Routine is a saved configuration (prompt, repository, connectors) that runs as a full Claude Code session on Anthropic's cloud: cron (minimum interval one hour) or, from the web console, GitHub events like pull_request.opened. Cherny's "loop babysitting my PRs" is the latter: a subscription to the work queue, not a timer.
Know what you are signing. Each run is a fresh clone of the default branch with no permission prompts mid-run and your identity on every commit. Keep the default restriction that it can only push to claude/-prefixed branches, write the prompt to open draft PRs rather than merge, and read the transcript afterward: a green run status means the session exited cleanly, not that the work is right. Manage with /schedule list, update, run. The asymmetry: this is the one durable loop you cannot commit; routines are per-account, so teammates rebuild from your prompt text.
Loop 7: the stack, the full machine
The primitives compose because each answers a question the others don't:
- A Routine fires on schedule or on
pull_request.opened, laptop closed. - Its prompt says "use a workflow", so each firing launches a script that holds the loop and fans out.
- The workflow pipelines subagents, each with
isolation: worktree, so parallel agents edit one repo without collisions. - Stages split maker / checker: one stage implements, the next reviews with fresh context and gates.
- A committed Stop hook enforces "tests pass before you stop" inside every agent; results land as draft PRs on
claude/branches for a human merge.
Two worktree footnotes that save an evening: fresh worktrees branch from origin/HEAD, not your local uncommitted state, and they skip gitignored files like .env unless listed in .worktreeinclude. And don't feel obligated to run all five layers: /loop 20m /fix-types is an interval firing a saved workflow; a bash Ralph around claude -p "/goal …" is fresh context plus a real condition. Small stacks, well verified, beat cathedrals.
Adding and removing the human
Notice what never changed as we climbed: the loop engine and the human's place in it are independent choices.
Keep a human in:
- Run
/goalwithout auto mode: every tool call crosses your desk while the loop drives the turns. - Split workflows into stages; inspect between launches.
- A PreToolUse hook that answers "ask" for risky actions, and a Notification hook that pings you when the loop needs a decision.
- Loops open draft PRs; humans land them.
Take the human out:
- Bake the whole stop condition into the launch:
claude -p "/goal … or stop after 20 turns". - Pre-allowlist the tools so nothing pauses to ask.
- Accept that there is no mid-run conscience to appeal to; the guardrails below stop being advice and become load-bearing.
The one gate you never remove, in either mode, is the merge.
Steal these loops
Don't invent your first real loop. Forward-Future's Loop Library catalogs 85 with named authors and one-click copy. Four worth stealing, lightly trimmed; watch where the words go:
- The repository maintainer (Peter Steinberger): "While repository maintenance is active, wake every five minutes. Triage repositories, assign each one's highest-value bounded task within granted permissions… Require tests, live proof, autoreview, and green CI before work can land. Escalate access, security, or irreversible decisions." Stops when every item is landed, decision-ready, blocked, or has no work.
- The production error sweep (Matthew Berman): "Review our production logs for errors. If you find an actionable issue, trace it to its root cause, fix it, verify the fix, and open a pull request. If no actionable errors are present, stop without making changes." Stops when no actionable errors remain; the verifier is the log itself.
- The coverage loop (Berman, in its entirety): "Add tests until we have 100% test coverage." One sentence, because the verifier, a coverage number, does all the work.
- The test stabilizer (hungtv27): run the suite N times, fix the most frequent flake at its root cause, "never with a blind sleep or retry," rerun. Stops when N consecutive full-suite runs pass, progress stalls, or approval is required.
The pattern across all 85: the best loops spend most of their words defining when to stop. Triggers get a clause, actions get two, and the stop condition with its "do not touch" constraints gets paragraphs. That ratio is the tell of someone who has run loops rather than tweeted about them.
What it costs: anatomy of the $6,000 loop
In May, r/ClaudeAI produced the number: "I accidentally burned $6,000 of Claude usage" (~1,300 upvotes). The setup was mundane: a /loop checking PRs every 30 minutes, forgotten overnight next to a long-open analytics session. 46 runs over 26 hours, none individually wrong. The poster's own turn data shows the money: turn 1 sent a few hundred tokens; turn 46 sent roughly 800,000, the whole session history re-bought at cache-write rates.
If you read Anatomy of a $5 "Good Morning", you know the mechanism: a loop is my $5.18 good morning automated. Every message re-sends the session. While the cache is warm, reads bill at 0.1x and each read refreshes the timer; past the window, writes bill at 1.25 to 2x and everything is re-bought. My transcripts: the same throwaway message into a ~500K-token session cost $0.04 to $0.35 inside the hour, $4.75 to $5.31 past it. A loop turns that dice roll into a schedule.
The trap is not long gaps (obviously cold) or short ones (safely warm). It is intervals hovering around the cache window. Iterations run long, wake-ups drift, the session grows, and a mid-session change can invalidate the prefix outright (I have a $4.10 receipt for 6 seconds of idle). Each late wake-up re-buys a history bigger than last time. That compounding is how 46 boring iterations become $6,000 without one of them looking wrong.
The design rules that fall out, none of which appear in the essays:
- Tight loops, tight intervals. Watching something that changes every few minutes? Wake every few minutes; the cache stays warm. Waking more often can cost less than waking near the window.
- Long gaps get fresh sessions. Spawn a minimal
claude -pwith only the context the task needs. A cold start on 5,000 tokens beats a rewrite of 800,000. (This is why Loops 3 and 6 are built on fresh contexts.) - Keep loop sessions small. The CI babysitter does not need your whole day's conversation behind it. Context is the multiplicand in every bill.
- Know your fuses.
--max-budget-usdand--max-turnsexist only in print mode; interactive/loophas the 7-day expiry (the 50-scheduled-task cap bounds how many a session holds, not one runaway loop). There is no per-loop spend cap, and the $6,000 poster reported the usage dashboard lagging days behind. You are the circuit breaker.
For scale: Anthropic ran 16 Opus agents in a permissions-off while-loop for two weeks to build a C compiler. Roughly 2,000 sessions, just under $20,000, and a 100,000-line Rust compiler that builds Linux 6.9. $20,000 bought a shipped compiler; the danger is spend that nobody meters and nothing verifies. On subscriptions the same mechanics burn your weekly quota, which is why Anthropic's usage limits explicitly target running Claude "continuously in the background, 24/7."
How loops fail
Cost is the gentle failure mode. The taxonomy, worst first; incidents and vote counts as reported in their public posts, the priced ones linked in References:
| Failure | Real incident | The guardrail it demands |
|---|---|---|
| Destructive actions, unattended | A cleanup command ended in rm -rf against $HOME and took a home directory, with the permission system on (issue #75859). Agents deleting production databases while debugging with live credentials is a postmortem genre of its own. |
Container or VM, never bare host. Prod credentials nowhere in reach. |
| Runaway recursion / retries | A recursive subagent bug burned 4M tokens in under 5 minutes with zero recoverable output. | Iteration caps and budget caps, held outside the loop's reach. |
| Fake-done | Tests that print "Test passed!" unconditionally; promise tags emitted on turn one; goals declared met because the transcript said so. | The termination ladder: verification that actually runs the checks. |
| Slop compounding | A developer inherited a 3-month-old loop-built repo and rewrote it in a week (7.3k upvotes): "barely any architecture, tests that covered who knows what." An HN commenter, on a coworker's Windsurf-generated suite, put it sharper: "awful tests that were unmaintainable and next to useless... testing that the code 'works the way it was written.'" Each iteration adds a small defense, a redundant check, a single-use abstraction, until the system collapses on its complexity. | One task per iteration, review diffs daily, and a periodic human pass that deletes. |
| Self-sabotage | In Anthropic's own compiler run, agents overwrote each other's fixes until git task-locking was invented mid-run, and one agent ran pkill -9 bash and killed its own loop. |
Worktrees for parallelism; the loop process owned by something the agent cannot reach. |
Notice what is absent: model stupidity. Almost every disaster is an authorization failure or a verification failure. The loop did what it was allowed to do, and nobody was watching. Which is why the fix is structural, not "prompt better."
Running a loop without getting popped
This is the section the incident table has been building toward. Everyone quotes Huntley's whimsy; fewer quote his threat model: "It's not if it gets popped, it's when it gets popped. And what is the blast radius?"
An unattended loop is an agent with your credentials, no human in the approval path, ingesting text written by strangers. A loop that triages GitHub issues is one malicious issue title away from executing someone else's instructions. Cloud Routines run with "no permission-mode picker and no approval prompts during a run," your identity on every commit, and connected MCP tools writable by default. Counting on the auto-mode safety classifier? Anthropic's own evaluation measured a 17% false-negative rate on real overeager actions. One in six slips through: a useful layer, not a boundary.
Also: --dangerously-skip-permissions "offers no protection against prompt injection or unintended actions" (the docs' own words). And the default sandbox blocks writes outside your project but can read your entire disk, ~/.ssh and ~/.aws/credentials included, unless you write deny rules. Defaults protect your repo, not your secrets.
The checklist, ordered so each line survives even if every line above it fails:
- Contain it. Unattended loops run in a container, VM, or cloud sandbox. Anthropic's compiler writeup says it in parentheses like it is obvious: "(Run this in a container, not your actual machine)." People still skip it.
- Scope the credentials. A dedicated token (
claude setup-token), repo-scoped git credentials, no~/.sshor cloud credential files mounted, prod secrets absent. The loop cannot leak what it cannot read. - Pin the egress. Default-deny outbound with an allowlist (registries, GitHub, the API). Injection that cannot phone home is a much smaller problem. Filtering is by hostname; a broad entry is a tunnel.
- Write deny rules that hold in every mode.
permissions.denyfor.envand credential paths, ask rules forgit push, a PreToolUse hook refusingrm -rf. Deny beats ask beats allow, including in the dangerous mode. - Cap the spend. Budget and turn caps per iteration, an iteration cap on the loop, a workspace-level monthly cap per API key. There is no official per-loop budget; you are the circuit breaker.
- Treat inbound text as hostile. Issues, PRs, tickets, CI logs are instructions from strangers. That loop gets read-only tools where possible, and never the same loop that holds write access to your infrastructure.
- Human gate at the end. The loop opens a PR; it does not merge one. Review is where slop and sabotage both die. This is the one gate no serious harness skips.
If you adopt only one line, make it the first. Inside a container with scoped credentials, every incident in the failure table becomes an anecdote instead of a disaster.
When to write a loop, and when not to
The skeptics are half right, and theirs is the sharpest engineering critique. A Hacker News comment on Ronacher's essay describes teams splitting into an "agent goes brrr" camp shipping code it does not understand and reviewers "holding the line on quality, and just exhausted." Another commenter puts the economics bluntly: the bottleneck is human verification and accountability, and parallel agents cannot fix that. Armin Ronacher's is the most precise: loop output is too defensive, too complex, too local; "if each iteration adds another small defense, the system slowly becomes less understandable while appearing more robust."
The practitioners' rebuttal: move the human work upstream and make verification mechanical. Write the spec you could hand a junior, loop against tests that automate your eyes, review the diff like a stranger wrote it. Both camps describe the same system; the difference is whether the verification was engineered or vibed.
The honest decision test. A task is loop-shaped when:
- Success is mechanically checkable. Tests pass, types check, the screenshot matches. If done is a judgment call, the loop makes the call in its own favor.
- It decomposes into small, independent items. Migrations, dependency updates, coverage backfill, CI babysitting. One item per loop.
- Iterations are cheap and reversible. A branch, a commit, a rollback. Never auth, payments, or production state; a loop's worst day should be no bigger than a revert.
- The spec exists. A loop amplifies the prompt file. An ambiguous prompt, amplified 40 times, is the inherited-repo story.
Fail two and you want a supervised session; fail three and you want to do it yourself. The strongest advocates agree more than the discourse suggests: Huntley calls Ralph greenfield-only, and Cherny's loops babysit PRs rather than architect systems. Output got cheap; judgment did not.
That is the thesis this guide has been circling. Point a loop at a mechanical keep-or-revert signal and capability compounds; point it at a signal the agent grades itself on and slop compounds at the same rate. Every loop question (when do I stop it, how do I stop it lying, why did it cost $6,000, is the code any good) is one question in different clothes: who verifies, with what tools, at what cost? Answer that and the rest is mechanical. Now run Loop 1. Literally this, in your next session: /goal all tests pass and lint exits 0; or stop after 20 turns. Sixty seconds, and unlike 181 of the first 182 people in that thread, you will have receipts.
Method and caveats
- Quotes: verified against the YouTube captions of the three source videos; the canonical Cherny quote is from Acquired Unplugged (June 2, 2026, 11:42), not the Sequoia talk most citations point to.
- The thread: 182 replies, ~30 on topic, one linked runnable artifact (a
config.tsin a repo), from my reading of the full thread on July 13-14, 2026. One-line/loopprompts quoted inside replies count as descriptions, not artifacts. The count has kept growing since. - Docs: loop mechanics from the official Claude Code docs (goal, scheduled tasks, workflows, routines, hooks, headless mode, permission modes, sandboxing, worktrees) as of mid-July 2026, and from harness source: the ralph-wiggum plugin, Huntley's scripts, snarktank/ralph. Version gates matter:
/goalneeds v2.1.139+, workflows v2.1.154+; the 8-block Stop hook cap, the 7-day loop expiry, print-mode-only budget flags, and the evaluator's no-tools limit can change in any release. - My runs: cost mechanics are my own transcript data from the previous post, priced at published API list rates. The Loop 3 receipts are from my run of the script in this post (July 16, 2026: a small greenfield repo, five tasks, per-pass costs from the CLI's
total_cost_usd; run log and repo history preserved). Read time is prose words (excluding code, tables, and references) divided by 250, rounded down. - Reported, not independently confirmed: the $6,000 and $20,000 figures link to their sources (self-reported and first-party respectively); failure-table incidents and the tweet view count are as reported in their public posts, vote counts as displayed at reading time. Loop Library prompts are lightly trimmed, authorship as listed.
- Not done: I have not run a multi-day loop against a production codebase; the rest collects what is verifiable so you can run yours with fewer surprises. Several harness repos ship without a license, so the loop, prompt, and hook here were written from scratch; use them freely. Corrections welcome, especially receipts that contradict mine.
References
- Anatomy of a $5 "Good Morning" and Prompt Caching Doesn't Cache Prompts, the cost mechanics this post builds on
- Boris Cherny at Acquired Unplugged (the canonical quote, 10:53-11:55) · Sequoia AI Ascent talk (the /loop walkthrough) · Anthropic: Reflecting on a year of Claude Code (the third recording checked)
- The Orosz thread ("can you share 'loops' you regularly use?")
- Geoffrey Huntley: Ralph Wiggum as a software engineer · snarktank/ralph · ralph-playbook
- Addy Osmani: Loop Engineering · Simon Willison: Designing agentic loops · Armin Ronacher: The Coming Loop
- Anthropic's official guide: Getting started with loops · Orosz's follow-up: What is "loop engineering?"
- Claude Code docs: /goal · scheduled tasks and /loop · dynamic workflows · routines · hooks · worktrees · sandboxing
- Forward-Future Loop Library (85 loops, with authors) · ralphloops.io (the RALPH.md format) · awesome-loop-engineering (the Loop Contract)
- Anthropic: Building a C compiler with 16 parallel agents (~$20k) · Anthropic: the auto-mode classifier evaluation (17% FNR)
- The $6,000 forgotten loop · the 4M-tokens-in-5-minutes recursion issue
- ImpossibleBench (visible test loops raise cheating from 33% to 38%)
- Anthropic's official ralph-wiggum plugin