for people who already have a coding agent
Leave it running.
Keep only what
holds up.
Your agent writes the code — it is good at that. looply decides what it works on, refuses the paths you named, runs your checks, and has a second agent prove the change before a line of it is kept.
works with the agent you already use · your code never leaves your machine
001 run.started
looply does not write your code
Claude Code, or whichever agent you already use, does that — and it is good at it. What it is not good at is deciding what to work on next, stopping at the edge of your schema, or telling you honestly whether the change it just made does what was asked.
looply is the harness around it. It holds the queue, the rails, the checks, the second opinion and the record. The agent reports its progress back through the same CLI you use, so what you read on your phone is what actually happened, not a summary of it.
the agent
- reads the codebase
- writes the change
- writes the test
- reports what it did
looply
- picks the task, and proves the premise still holds
- holds the rails and refuses the paths you named
- runs your checks, then a second agent over the diff
- keeps or discards, and records why
you
- set the rails once
- answer the few real questions
- approve what ships
002 round.picked
What one round is
The unit of work, and the only thing that produces a commit. Step through it.
who does this · looply
The top item whose premise still holds. If the code moved since the item was written, it goes back through verification before anything is spent on it — an item describing a bug somebody already fixed is worse than no item at all.
serve() turns every fs.readFile failure into a bare 404
who does this · the agent
Your coding agent does this part, and looply does not help. It starts at the file and line the item already located, which is most of what the verification pass pays for. One concern, a test with it, and no git — the runner owns branching and discarding.
serve() turns every fs.readFile failure into a bare 404
who does this · looply
Your own checks, in the order you wrote them, cheapest first and stopping at the first failure. This is the first of the two keys. On its own it proves the change compiles and the suite still passes — which is not the same as proving the change did what was asked.
serve() turns every fs.readFile failure into a bare 404
2/2 checkswho does this · the agent
A second agent reads the diff against the item. It did not write the code and it is never shown the first agent’s account of what it did — that exclusion is enforced in the code, because a prover shown the story grades the story. It answers proven, rejected or partial.
serve() turns every fs.readFile failure into a bare 404
2/2 checkswho does this · looply
Both keys turned, so the work is committed to the run branch with a trailer recording which checks actually ran. Had either failed, the tree would be thrown away and the item requeued carrying the reason — so the next attempt starts knowing what went wrong with the last one.
May I edit src/html.ts, once, for this item?
If you say nothing it will deny at 06:31.
moved on to itm_92f1 while the question waits
003 proof.result
the part that matters
A passing build is not proof
Anything can make the tests go green. Every change looply keeps has been read by a second agent that did not write it, shown the task and the diff but not the reasoning behind them, and asked one question: does this do what was asked?
Key one · your checks
Typecheck, tests, build — yours, in the order you wrote them, cheapest first. This proves the change compiles and the suite still passes.
Key two · a second agent
A different agent reads the diff against the task. It did not write the code and never sees the first agent’s account of it. It answers proven, rejected or partial.
block() has no default case, so an unknown kind renders nothing
2/2 checksboth checks green, rejected anyway — that is the job
Both have to agree. The checks pass and the reader says yes, or the work is thrown away and the task goes back in the queue carrying the reason it failed. That is why the number of changes rejected is worth reading — a prover that never rejects anything is not checking.
004 run.ended
Where the design came from
An earlier version of this harness ran three unattended sessions against a production codebase — 166 rounds, about fourteen hours. Every round shipped a test, no dependencies were added, and no forbidden path was ever touched.
It also went 166 for 166. Nothing was ever rejected, because nothing could be: the checks it ran were the same checks the agent had already run before finishing. That is the hole the second reader exists to close, and it is why looply counts proven rounds rather than green ones.
005 round.phase
What the harness actually does
Your code never leaves your machine
The agent runs where your code already is. The server carries task titles, file paths and events — not source, not diffs, not credentials, not even where the repository sits on disk. If it disappears, the loop keeps working and says it lost the connection rather than going quiet.
Rails you set, and a door only you open
Name the paths the agent must never touch: schema, migrations, auth, anything that moves money. looply reports what it finds there and refuses the edit. A task that genuinely needs one becomes a question, for that one file, once.
It asks instead of guessing
When the loop reaches something only you can settle, the question carries a default and a deadline — and it moves to another task while it waits rather than idling on your money.
The agent reports through the CLI
Progress, findings and blockers all go through the same commands you use, so the ledger is the agent’s own account of its work, timestamped and append-only, not something reconstructed afterwards.
Nothing ships without you
Work lands on a branch, grouped for review rather than as a hundred loose commits. Undoing a change files a new task describing what was wrong with it, so the objection is never lost.
The queue is the product
No task is picked until it has been confirmed against the code as it stands — an item describing a bug somebody already fixed is worse than no item at all. When the loop writes its own tasks it caps how many near-identical chores it may queue.
006 alert
What it is not
Four things worth knowing before you install it.
- a coding agent. It drives the one you already use, and is worth nothing without it.
- a replacement for review. It narrows what you review and shows its working; you still decide what ships.
- free. Every round is agent time, and a check that rejects work has still been paid for.
- a fit for a codebase with no tests. Without checks of your own there is nothing for the first key to turn.
007 question.asked
Get looply
The CLI is the product. The app is how you watch it from somewhere else.
the CLI
the app
Neither badge is live yet — the app is in review. looply runs without it: pairing a phone is optional, and everything the loop does happens on your machine either way.
block() has no default case, so an unknown kind renders nothing