| name | agent-loop |
| description | Use whenever the user wants Claude to keep working on its own until a goal holds: "run a loop", "loop until the tests pass", "keep going until the build is green", "fix all of these until the suite is clean", "babysit this until it's done", "run this autonomously", "set up a self-verifying loop", "iterate until X", or references agent loops / loop engineering / Boris Cherny's "I write loops" methodology. Trigger even when the user never says the word "loop" โ any "keep doing X until condition Y holds, then stop" request is a loop. Also use for a large multi-stage objective โ "create user manuals", "break this objective into steps", "turn this into a pipeline of loops", or any deliverable whose stages fan out over many items (one loop per page, screen, or endpoint). Also use when the user asks which loop type or primitive fits a task โ "/goal or /loop?", "should this be a schedule/routine?", "do I even need a loop for this?". |
Agent Loop
Turn a goal into a loop that runs itself. Instead of prompting turn by turn, you
define a goal with a real verification gate and let Claude run act โ verify โ
re-prompt until the gate passes or a budget ceiling stops it. This is the
practical companion to the loop-engineering knowledge base (see end of file).
The one rule: verification is the engine
A loop without a real verification gate is just repeated guessing. The model will
happily declare victory while the build is red. What makes a loop trustworthy is a
gate that lets reality โ a test suite, a build, the app actually running โ decide
whether a pass made progress. Cherny's line: a verification feedback loop "2-3x"
the quality of the result. So the first question is never "what should the agent
do" โ it's "how will the loop know it's done?"
If the project has no way to verify the goal (no tests, no build, no runnable
check), stop and say so. Propose adding a check first. Looping without one is the
single most common way these go wrong.
A gate proves only what it asserts โ so validate the gate, don't just run it.
Two traps hide here: a gate green for the wrong reason (a typo'd test path, a check
that never exercises the bug โ 100% coverage with mocks has shipped real auth bugs
past review), and a gate too shallow to catch a behavioral break. Two habits close
both: prove it red-first โ run the gate on the unfixed code and confirm it fails
for the right reason before looping (verify-loop.sh does this by default and
refuses a green start unless --allow-green-start); and for correctness- or
security-critical goals make the gate behavioral / live-data (drive the real
endpoint, assert the real contract), not coverage.
When tests can't see the bug, put a judge in the gate. Even a behavioral,
red-first test only checks what it asserts โ it can't catch a requirement wired in one
place but missed at another call-site, a scope/permission leak, or a loop that quietly
weakened its own tests. For non-trivial or correctness-/security-critical stages, make
the gate script AND judge: the objective tests PLUS an independent reviewer
(scripts/judge-check.sh) that adversarially reads the diff against a rubric and fails
with feedback the loop then acts on. Drop a rubric.md into the stage folder and the
scaffolded verify.sh runs it automatically (run-tests && judge-check.sh --rubric rubric.md); the judge only fires once the tests pass, so it costs ~one model call per
green attempt. It MUST be a separate run from the one that wrote the code โ the author
judges its own work poorly. (Real case: a loop's tests passed but it billed the wrong
API key on one un-tested code path; only an independent review caught it.)
Visual / subjective deliverables โ render, then let the judge SEE it. Have the gate
render the result to a PNG and point the rubric at the image โ judge-check.sh's reviewer
uses Read, which VIEWS images, so it can rule on look-and-feel. Fold the project's OWN
conventions (lint, file-size cap, type-check) into the gate, and give judge stages a
higher effort than mechanical ones. Full recipe + evidence: references/gates.md.
Before you loop โ the 60-second setup
Walk these five with the user (or infer and state your assumptions). Don't start
the loop until the gate and ceiling exist.
- Goal โ a checkable condition, not a vibe. "All tests in
api/ pass and
ruff is clean," not "make the API better." Then name the goal's forks โ
the readings you'd otherwise resolve silently ("fix the failing tests": fix the
code, or fix wrong tests? "migrate": exact behavior, or clean up too?). State
the 1โ2 forks that change what the loop builds, pick a default, and bake it
into the goal prompt โ an unattended loop resolves ambiguity alone, one
iteration at a time.
- Verify command โ the shell command whose exit code is the gate. Discover it:
inspect
package.json scripts, Makefile, pyproject.toml/pytest, gradlew,
go test, cargo test, or the CI workflow. Prefer "can the agent actually run
the thing" (tests, a smoke run, a headless browser) over lint-only โ lint passing
says nothing about whether the code works.
- Budget ceiling โ a max iteration count and, for unattended runs, a dollar
cap (
verify-loop.sh --max-cost USD sums each iteration's reported cost).
This is what makes a loop safe to leave unattended. No ceiling, no unattended loop.
- Isolation โ if the loop runs alongside other work, give it its own git
worktree so parallel changes don't collide (
claude --worktree <name>).
- Supervision โ attended (watch it) or background (notify on done/stuck).
Decide up front; it changes which primitive you pick. If background: also
decide what the loop may do alone โ scope
--allowedTools/permissions to the
minimum the goal needs (an overnight loop rarely needs push, network, or rm).
Pick the loop type, then the primitive
Decide which piece of the work you're handing off โ that picks the loop type,
and the primitive follows. If the work doesn't recur and one attempt โ with the
gate run once at the end โ would plausibly reach the goal, don't build a loop:
run the turn, run the gate, hand back the result. Reach for the bundled /verify
skill (v2.1.145+) or a project verification skill that encodes the manual check โ
not loop machinery.
| You hand off | Type | Use | Why |
|---|
| The stop condition | Goal-based | /goal <condition>, stop after N tries | Claude loops turn after turn until a small fast model confirms the condition; takes an explicit turn cap. Works headless too. Start here. |
| โฆ with your own control flow | Goal-based | scripts/verify-loop.sh (a claude -p while-loop with a verify gate) | You own the ceiling, stall/reset/escalation handling โ headless / CI. |
| โฆ with custom stop logic | Goal-based | Stop hook (command hook: exit 2 blocks the stop; prompt/agent hook: return {"ok": false}) | The same mechanism /goal wraps. |
| The trigger | Time-based | /loop <interval> (session-scoped) or a cloud routine via /schedule (survives your machine being off) | "Every 30m, draft fix PRs for new bug issues." Polls or schedules instead of running once. |
| The prompt itself | Proactive | Compose: /schedule trigger + /goal per-run done + skills to verify + workflows for fan-out | A recurring stream of well-defined work (reports, triage, migrations) with no human in real time. |
| A step with NO objective check | any | scripts/judge-loop.sh (LLM-judge gate) | A separate Claude scores the result against a rubric โ independent verification when no shell command can decide. Orthogonal to loop type. |
Read references/choosing.md for the full taxonomy (trigger, stop criteria, and
token levers per type) and references/primitives.md for the exact flags,
caveats, and doc links. Confirm flags against current Claude Code docs โ they
change between versions.
Run the loop
In-session (default): state the goal as a condition and hand it to /goal:
/goal all tests in test/auth pass and the lint step is clean, stop after 10 tries
Headless / scriptable: use the bundled script. It runs the verify command,
breaks the moment it exits zero, and otherwise feeds the failure back into a
resumed claude -p session until the ceiling:
scripts/verify-loop.sh \
--goal "Fix the failing auth tests. Find and fix the root cause, don't skip tests." \
--verify "npm test -- test/auth" \
--max 10 \
--tools "Read,Edit,Bash"
The cycle each iteration: act (Claude edits) โ verify (run the gate) โ
feed the result back โ check budget โ stop or continue. The verify command is
the brake and the steering wheel.
Safety flags worth knowing (--help lists all): --stall N bails after N no-progress
rounds (compared by normalized signature, not exact output, so it still catches a
loop that fails differently each round); --reset-every N drops the session for fresh
eyes when an approach entrenches; --escalate-model M makes a last-ditch stronger-model
attempt before a stall bail; --worktree PATH runs the loop on a throwaway branch;
--log DIR writes each iteration's verify output + diff as an audit trail;
--allow-green-start skips the red-first guard; --max-cost USD bails once the
summed per-iteration cost (claude's reported total_cost_usd) crosses the cap.
Stay in the judgment seat
The loop produces candidates, not merged truth. Your job doesn't disappear, it
moves up a level: review the diff or the PRs, kill runaway loops, and never let a
loop auto-merge work you haven't looked at. Cherny: "if the code sucks, we're not
gonna merge it." Set the gate, set the ceiling, then judge the output.
Make the loop hand you decisions, not just diffs: have the goal prompt say "log
anything you resolve that the goal doesn't specify, and why, to decisions.md". Review
that log first โ the judge-script edit (anti-patterns) was caught only by diff archaeology.
Compound โ make the loop smarter over time
The highest-leverage habit: every time the loop makes the same mistake twice,
don't just fix it in-session โ write the lesson into CLAUDE.md or turn it into a
skill. Each durable correction means the next loop starts smarter and can run
longer unattended. This is what lets a loop "just run forever" instead of needing a
babysitter. Treat recurring corrections as a signal to update memory, not to re-explain.
Anti-patterns (how loops go wrong)
- No verify gate โ looping on the model's self-assessment. It will lie to itself.
- Lint-only verification โ green lint, broken code. Run the actual thing.
- An expensive gate as the only instrument โ when the gate is a full pipeline
(end-to-end run, film take, deploy, batch job), every hypothesis costs the whole
pipeline. Split the instruments: a cheap probe (API call, shell query, unit-level
reproducer) falsifies "is the system right?" in minutes; the expensive gate confirms
"is the deliverable right?" once, at the end. Seen for real: six masked defects
peeled at ~35 min per iteration that a 2-minute probe could each have falsified.
- Misreading a correct gate โ the gate can be right while its reading is wrong:
a count with an unexpected filter, a status that lags aggregation, a log line whose
name promises more than it measures. When a confident fix "didn't work", re-derive
the failing signal's semantics at its source before iterating โ a misread signal
falsifies every fix the same way, and the loop thrashes on a phantom.
- No budget ceiling โ an unattended loop with no max burns the whole budget on a
stuck problem. Always cap iterations; consider bailing after N identical failures.
- A flaky gate โ a nondeterministic check makes the loop thrash, and worse, tempts
it to "fix" the symptom of a flake instead of a bug. Stabilize it first โ measure
the flake rate, split infra-flake from real bug; diagnosis playbook in
references/gates.md.
- Verifying with the context that wrote the code โ a fresh check (a separate run,
a Stop hook, a real command) catches what the author missed.
- A gate the loop can edit โ if the loop has write access to its own gate (the verify
script, the rubric, or a skill script referenced by absolute path), it can make a red
gate green by weakening the check instead of doing the work. Keep gate + skill scripts
OUTSIDE the loop's writable scope (read-only, or a path its tools can't reach), and diff
them after a run. Seen for real: a design loop whose judge gate gave false negatives
edited the judge script itself โ that time a legitimate fix, but the capability is the
risk, and you only know which by reviewing the diff.
Decompose a big objective into a loop chain
One loop fixes one thing. A big objective ("create user manuals", "migrate every
endpoint") needs several loops, some fanning out over many items. When that's the
case, build a loop chain instead of a single loop:
- Plan it โ restate the objective, then run an ultracode/Workflow pass to
decide the ordered stages, each with a goal, a verification gate, declared
inputs/outputs, and a
next. Mark stages that fan out (one sub-loop per page /
screen / endpoint), and mark non-trivial / correctness-critical stages to get a
rubric.md (a compound script+judge gate โ see "put a judge in the gate" above).
The planner fixes the stage skeleton; fan-out counts are discovered at runtime.
- Show the plan and get approval before building anything.
- Build it โ write
chain.json and instantiate the backbone from the
template library with scripts/scaffold-loop.sh.
- Run it โ
scripts/run-chain.sh <workspace> drives the chain (one loop at a
time via scripts/loop-engine.sh, whose gate can be script | judge |
human): linear stages self-verify, fan-out stages run their sub-loops in
parallel and join, and the terminal stage pauses for your sign-off. Resumable;
start mid-chain with --from <stage>.
Each loop lives in its own folder with its own files and is reusable; loops share
data only through state/. Read references/chains.md for the schemas, runtime,
planner procedure, and a worked user-manual example before building a chain.
Reference
references/choosing.md โ the four loop types (turn/goal/time/proactive): what you hand off, trigger, stop criteria, token levers.
references/gates.md โ gate hygiene: the visual-judge recipe + flaky-gate diagnosis playbook.
references/chains.md โ loop-chain schemas, runtime, planner procedure, example.
references/loop-chains-design.md โ the approved design spec for loop chains.
references/primitives.md โ the documented Claude Code primitives, with flags and caveats.
- Knowledge base (the "why" behind all of this):
/home/cocodedk/0-projects/loop-engineering
ยท online at https://cocodedk.github.io/loop-engineering/ ยท repo
https://github.com/cocodedk/loop-engineering. Start with docs/04-loop-anatomy.md,
docs/05-verification-and-memory.md, and docs/09-example-loops.md.