NAME — loop engineering for AI agents. One file. Any agent. Until it's verified.
SYNOPSIS — runs Claude Code, Codex, Gemini CLI, Aider, or any agent CLI in a loop driven by one markdown file, with memory, verification, a critic, keep-or-revert, and brakes.
The most powerful way to use a coding agent is not a longer conversation. It is a loop: run the agent, check its work, run it again, until the job is done. People run this with a while true in bash. It works, and it is blind: no memory between runs, it believes the agent when it says "done", it never stops on its own, and it leaves no record. Worse, the agent can quietly edit the tests that judge it. loop is that loop, engineered.
A loop is a goal, a worker, a verifier, memory, and brakes, run until the verifier is satisfied or the brakes engage. A Loopfile is those five parts in YAML frontmatter, followed by the goal in markdown.
letter: trueEvery iteration is a fresh session with no memory. Before it ends, the agent writes a short letter to its next self: what it did, what to do next, what to avoid. It is the only memory that survives, and it turns a pile of amnesiac runs into one continuous worker.
until: [checklist, "npm test"]"Done" is a claim. until: lists what must actually hold: a test command exits 0, every checklist item is ticked, the agent says so, or all of them. A false claim is rejected, and the next iteration is told exactly why, with the failing output.
critic: codexAn independent reviewer in its own session before "done" is accepted. It reads the goal, the diff, the check results, and the worker's letter, then approves or rejects with numbered reasons. The worker never grades its own work.
metric: "node bench.js"A command that prints a number turns the loop into an experiment loop. If an iteration did not improve on the best so far, it is reverted with git and the history records what was tried. A warning is advice; a revert is a fact.
protect: ["test/**"]Globs the agent may not modify. Any protected file it touches is restored and the iteration rejected. Checklist rewordings are restored too. The verifier is not the agent's to edit.
rituals: [{at: 1, ...}]Alternate agents every iteration, and run a different instruction at fixed points: at: 1 to plan before building, every: 5 to review, at: last to wrap up. A ritual can run on a different agent.
max: 25 · max_cost: 20 · stall: 3Iteration, wall-clock and dollar limits; a timeout that kills a runaway agent; stall detection for iterations that change nothing; repeat detection for the same failure over and over. Ctrl-C once finishes the iteration cleanly so the letter gets written.
.loop/runs/…/journal.jsonlEvery prompt, output, changed file, check, metric, verdict, and critic review lands on disk. loop log is the timeline; loop report builds a single HTML page with the metric curve.
--- name: search-api agent: [claude, codex] # worker: two agents take turns until: [checklist, "npm test"] # every box ticked AND tests green critic: codex # independent review before "done" protect: ["test/**", "SPEC.md"] # the agent may not edit these memory: NOTES.md # durable notes, across loops max: 30 # brakes max_cost: 20 git: true # every kept iteration is a commit --- # Goal Add full-text search to GET /posts. See SPEC.md. # Checklist - [ ] Migration: tsvector column and GIN index - [ ] q= query param, ranked results - [ ] Tests: ranking, empty query, injection - [ ] README section with examples
# Humans read it, agents read it, and the loop re-reads it before every iteration. Everything the loop does is a key in that file, and every key can be deleted.
# agent: [claude, codex] alternates agents every iteration. model: and args: pass through; command: runs anything. sandbox: wraps it in a container.
<loop:done/>everything is complete; the loop verifies and asks the critic<loop:stuck>why</loop:stuck>stop; a human is needed. loop run continues later with the letter intact<loop:ask>question</loop:ask>in a terminal, you are asked right there; unattended, the loop parks itself until loop answer<loop:handoff>codex</loop:handoff>run the next iteration on a different installed agent<loop:sleep>10m</loop:sleep>wait before the next iteration<loop:note>text</loop:note>leave a note in the journal<loop:approve/>the critic accepts the work<loop:reject>reasons</loop:reject>the critic blocks "done"; the reasons go into the next prompt# a tag only counts at the start of a line, so the agent can talk about the protocol without triggering it
A prompt is a request. A loop is a process. "Done" is a claim — the loop verifies it, a critic can veto it, and anything that doesn't measurably win gets reverted. Files are the memory.
# requirements: Node 18+, one agent CLI on your PATH, git for revert/restore features. full docs: commands, reference, recipes, FAQ →