Verified, resumable engineering loops for Claude Code. A ratchet only turns forward. Every unit of work is gated by acceptance criteria and locked in as one atomic commit — the loop never slides back, never wanders off-spec, and never loses its place.
FAQ
ratchet is a Claude Code plugin with 5 hand-picked skills for development work, indexed on Flowy. Install it with the command on its page. It includes ratchet-audit, ratchet-backlog, ratchet-loop. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
> /plugin marketplace add afrizzal/ratchet> /plugin install ratchet@ratchet
Repo: afrizzal/ratchet
Verified, resumable engineering loops for Claude Code.
A ratchet only turns forward. Every unit of work is gated by acceptance criteria and locked in as one atomic commit — the loop never slides back, never wanders off-spec, and never loses its place.
Point it at a codebase → get a reviewable backlog → let the loop work through it, one verified commit at a time. Walk away. Come back to a ledger of what shipped, what's blocked, and what needs you.
Agentic coding is great at bursts and terrible at campaigns:
Ratchet's answer is one structural move: the loop's entire state lives in a markdown file — BACKLOG.md — that is git-tracked, human-readable, and human-editable. The agent is stateless; the file is the state.
That one move buys everything else:
| Property | How |
|---|---|
| Resumable | Any new session reads the ledger + journal and continues where the last one died. Context resets are a non-event. |
| Verified | An item is done only when its acceptance criteria pass. The agent may not edit the criteria to make them pass — that's moving the goalposts, and it's banned. |
| Atomic | One item = one commit, containing the change and its ledger update. Every ratchet click is self-documenting and individually revertable. |
| Safe | Items tagged [USER-DECISION], [OPS], or [RISKY] are never executed — the loop parks them as needs-human and moves on. |
| Reviewable | The backlog is a file. It goes through PR review like any other code. No tracker, no API, no lock-in. |
| Parallel | Format v2 splits the state into one file per lane, so several agents run the same backlog at once without a merge conflict. |
flowchart TD
A[BACKLOG.md] --> B{next eligible item?}
B -- none left --> Z[report: backlog dry ✅]
B -- human-gated tag --> H[ledger: needs-human] --> B
B -- yes --> C[re-verify evidence in code]
C --> D[implement the Spec — nothing more]
D --> E{acceptance + global checks green?}
E -- red, attempts left --> F[diagnose, fix] --> E
E -- red, attempts exhausted --> G[revert item's changes<br/>ledger: blocked + journal why] --> B
E -- green --> I[atomic commit: code + ledger update<br/>🔒 the ratchet clicks] --> B
Three nested loops:
/loop) for standing "keep this repo healthy" automation.Install as a plugin (one command, updates included):
/plugin marketplace add afrizzal/ratchet
/plugin install ratchet@ratchet
Plugin installs namespace the commands:
/ratchet:ratchet-audit,/ratchet:ratchet-loop, … Prefer bare names? Copy the skills instead (they then work as/ratchet-auditetc.):git clone https://github.com/afrizzal/ratchet cp -r ratchet/skills/* ~/.claude/skills/ # macOS/Linux Copy-Item -Recurse ratchet/skills/* "$env:USERPROFILE\.claude\skills\" # Windows
Then, inside any project in Claude Code:
/ratchet-audit # deep multi-agent audit → ratchet/BACKLOG.md
# ...review & edit the backlog like code — delete items, adjust specs, add tags...
/ratchet-recommend # routed plan → ratchet/NEXT.md (what next + who does it)
/ratchet-loop --only SEC-01 --verify fresh # paste the wave commands NEXT.md prescribes
/ratchet-ship # preflight → push → watch CI → smoke checklist
(Installed as a plugin? Prefix each command: /ratchet:ratchet-audit, /ratchet:ratchet-loop, …)
NEXT.md is your plan — the loop reads it and refuses to silently downgrade its verification
routing, but you issue the wave commands. Bare /ratchet-loop is the no-routing shortcut:
file-order execution of everything eligible. Run the loop on a work branch — the loop offers to
create one, and /ratchet-ship opens the PR.
This is the core motion: the expensive model audits and routes; a cheap model executes.
/ratchet-audit and /ratchet-recommend with your strongest model (Opus/Fable)./model sonnet in the same session, or start a fresh one with claude --model sonnet.ratchet/NEXT.md. The loop makes the handoff safe by
construction: it loads its own executor-rules.md (13 do-this-exactly rules for smaller
models), honors NEXT.md's verify assignments, and hard-parks anything high-stakes that wasn't
explicitly routed to it.Don't want a full audit? Build a backlog from anything:
/ratchet-backlog create from TODO comments
/ratchet-backlog create from github issues
/ratchet-backlog add "rate-limit the /export endpoint"
A ratchet backlog is plain markdown with a tiny contract (full spec):
### SEC-01 — Scope item lookups by tenant [P0]
- Tags: —
- Evidence: api/items/[id]/route.ts:16 — GET/PATCH/DELETE filter by group only, not space
- Spec: add spaceId (from the session helper) to all three where-clauses; use updateMany/deleteMany
- Acceptance:
- [ ] `npx tsc --noEmit --incremental false` exits 0
- [ ] request against another space's item id returns 404
- [ ] existing save/delete flow in the UI still works
## Ledger
| ID | Status | Attempts | Commit | Note |
|---|---|---|---|---|
| SEC-01 | todo | 0 | — | — |
## Journal
- (the loop appends what it learned here — this is what makes resume cheap)
Spec and state are separated by design. Items are the immutable what; the Ledger + Journal are the mutable where are we. Humans edit items; the loop edits the ledger. Merge conflicts stay boring.
The format is agent-agnostic on purpose: these skills are the Claude Code implementation, but nothing stops a Cursor rule, a Codex prompt, or a bare script from executing the same file. Ports welcome — see CONTRIBUTING.
One file, one writer — which means one executor at a time. Format v2 (spec, worked example) relocates the mutable state so several agents can work the same backlog concurrently:
ratchet/
BACKLOG.md # human-owned: Global checks + Lanes + Items. Executors never write it.
lanes/core.md # default lane — shared paths, dependencies, integration fixes
lanes/api.md # ledger + journal for Lane: api ← one writer
lanes/ui.md # ledger + journal for Lane: ui ← one writer
Each item declares a Lane:; each lane owns a disjoint slice of the tree and runs in its own worktree on ratchet/<lane>. Two executors, two lane files, two source scopes — nothing to merge-conflict over.
/ratchet-loop --lane api --only SEC-02 --verify fresh # worktree A
/ratchet-loop --lane ui --only UI-07 --verify inline # worktree B, same time
gitGraph
commit id: "recommend → NEXT.md"
branch api
checkout main
branch ui
checkout api
commit id: "ratchet(api): run open"
checkout ui
commit id: "ratchet(ui): run open"
checkout api
commit id: "ratchet(SEC-02): scope by owner"
checkout ui
commit id: "ratchet(UI-07): empty state"
commit id: "ratchet: sync ledger"
checkout main
merge ui
checkout api
commit id: "ratchet: sync ledger"
checkout main
merge api
commit id: "npm test @ merge"
(The branches are really named ratchet/api and ratchet/ui.) Each lane opens with a committed marker, lands each item as one atomic commit — source change plus its own ledger row — and closes with ratchet: sync ledger. A human merges, then re-runs the Global checks. The worked example is this repo captured mid-wave, with both lanes open at once.
| v1 | v2 | |
|---|---|---|
| Executors at once | one | one per lane |
| Mutable state | one ## Ledger + ## Journal in BACKLOG.md | one file per lane, single writer |
| Coordination cost | none | one merge per lane, plus a barrier for shared paths |
| Ledger merge conflicts | n/a (one writer) | none — no two writers share a file |
| Source merge conflicts | n/a | none within the format's rules; the barrier lane exists because scopes alone can't cover shared files |
| Semantic conflicts | n/a | still possible — lanes green apart can be red together, which is why the Global checks re-run at the merge |
| When to use | the default | the backlog is large and the work genuinely partitions |
What keeps it honest — every one of these exists because the naive version breaks:
Run markers. A run opens its lane with a committed run started journal line and closes it with run ended. That is how a resuming agent tells crash debris (recover it) from a live parallel run (hands off), which a clean-tree check cannot do across worktrees.
The default lane is a barrier. Anything whose diff escapes every named scope — a new dependency and its lockfile, generated files, a post-merge integration fix — lives in the (rest) lane, which runs alone, with every other lane closed and merged. Lane assignment follows the diff, not the theme.
Scope binds the diff, not just the Spec. Before committing, the executor checks its diff's paths against its lane; a stray path parks the item rather than poisoning a merge.
Reads are global, writes are local. A lane run reads every lane's ledger and journal — lessons don't respect scope boundaries — and writes exactly one file.
Humans get a write window. Unparking, adding items, and grooming touch lane files only on the integration branch while that lane is closed. BACKLOG.md is frozen while any lane is open, so a Spec can't change under a done row that was earned against the old one.
Merging is a human step, merge-commit or fast-forward only. Squash and rebase-merge rewrite shas and orphan every Commit: cell in the ledger. Lanes green apart can be red together, so the Global checks run again at the merge.
Stop conditions are per lane. Two consecutive blocked items stop that lane's run; the sibling agent keeps going. A sick lane doesn't halt a healthy wave.
v1 is not deprecated and stays the default: one agent, one file, zero coordination. Reach for v2 when the backlog is big enough that parallelism beats simplicity and the work actually partitions — if every item touches src/core/, lanes buy you nothing. /ratchet-backlog migrate converts in one commit, preserving every ID, row, and journal line (migration guide); going back is just as cheap.
| Skill | What it does |
|---|---|
ratchet-audit | Fans out parallel subagents across your codebase (data layer, API/auth, business logic, tests/CI, frontend), verifies every finding down to file:line, and emits ratchet/AUDIT.md + a prioritized, acceptance-gated ratchet/BACKLOG.md. |
ratchet-backlog | Creates, validates, grooms, and migrates backlog files — from audits, TODO comments, GitHub issues, PRDs, or plain conversation. Enforces the invariant: no acceptance criteria, no item. Owns lane files in v2 (creation, rows, unparking). |
ratchet-recommend | The navigator. Read-only. Turns the backlog + ledger into a routed plan (ratchet/NEXT.md): what to do next, who does each item (autonomous cheap model / supervised / senior / human decision), in what order, with what verification. This is the layer that lets a cheaper model match a senior one — it inherits the routing instead of guessing it. |
ratchet-loop ⭐ | The executor. Picks the next eligible item, implements exactly its spec, runs acceptance until green (bounded), commits atomically, updates the ledger, repeats. Stops cleanly; resumes for free. Ships with executor-rules.md — 13 binding rules that make the loop safe for smaller models. |
ratchet-ship | Release runbook: full preflight, diff & secret scan, push, watch CI to green, smoke checklist, rollback notes. |
Ratchet's workflow was extracted from a real engagement, not invented for this README. In its first field run on a production multi-tenant SaaS (40 tRPC routers, 76 database models, ~140k LOC), the audit surfaced two HIGH-severity authorization flaws that had survived months of feature work — one cross-tenant IDOR, one systemic permission-check gap — plus a prioritized backlog of 18 items with per-item acceptance criteria. The backlog was then executed item-by-item by a smaller model, every fix landing as its own verified commit, with human-gated items correctly parked for review.
The lesson that became Ratchet: the handoff artifact matters more than the model. A sharp backlog with checkable acceptance criteria lets a cheaper model execute safely what an expensive model discovered.
[USER-DECISION] / [OPS] / [RISKY] tags are hard gates. The loop reports; it does not improvise. Releasing a parked item is a documented human procedure (Human transitions): journal the decision, clear the tag, status back to todo.--only and --verify fresh is on. No model self-assessment — the flags decide.needs-human — the goalposts don't move.--verify fresh): a separate subagent that never saw the implementation re-runs the acceptance criteria independently — the implementer doesn't grade its own homework.in-progress marks and the ledger live in a git-tracked file; a resuming run recognizes its own debris, commits it as ratchet: recover state, resets orphaned items to todo, and continues.ratchet/<scope> work branch first; /ratchet-ship opens the PR.--no-verify, no amending history. Ever.When nobody is at the keyboard — cron, CI, the shipped ratchet-audit Action — "the agent was told not to" is not a control. Two things that look like boundaries aren't:
Bash(git push:*) never sees git -c protocol.version=2 push origin HEAD:main.actions/checkout leaves a push credential on disk by default. Any command in the job — including one the agent writes — can use it.So don't ask the agent to abstain. Take the credential away, and split the run in two:
| Job | Runs the model? | Token | Can it write? |
|---|---|---|---|
| audit | yes | contents: read, checkout with persist-credentials: false | no — there is no push credential in its shell |
| pr | no | contents: write | yes, and no model can reach it |
Two more mechanical details do the rest:
git commit -- ratchet/AUDIT.md ratchet/BACKLOG.md. A bare git commit -m commits the whole index, so a file the agent staged would ride along inside a PR that claims to hold only artifacts. (git add is not on any deny-list worth trusting.)Deny-lists still belong in the workflow — as a guardrail against an honest mistake, never as the boundary. The rule generalizes: an unattended agent should hold no credential that can do the thing you are promising it won't do.
Why not just use GitHub issues? Issues are great for humans coordinating. A backlog file is better for a loop: it travels with the branch, works offline, carries machine-checkable acceptance criteria, diffs in review, and costs zero API calls to read. Use /ratchet-backlog create from github issues to bridge.
What stops an infinite loop? Per-item attempt caps (default 3), the two-consecutive-blocks rule, an optional --max-items budget, and the fact that every state transition is written to the file — a stuck loop is visible and resumable, not mysterious.
Can several agents work one backlog at once? Yes, on format v2: each agent takes a lane, writes only that lane's state file, and works a disjoint slice of the tree in its own worktree. Everything shared is serialized through the default lane's barrier. Start on v1 — migrate when the backlog is big enough that coordination pays for itself.
Does it work unattended? Yes — that's the point of file-based state. Pair /ratchet-loop with Claude Code's /loop, a cron job, or a CI workflow for standing automation. A ready-made GitHub Action for the meta-loop (scheduled /ratchet-audit → PR with a fresh backlog, never a direct push) ships at .github/workflows/ratchet-audit.yml — copy it into any repo. Read the two-job rule before you wire up any agent that runs without you. Start attended until you trust your acceptance criteria.
My project isn't Node/TypeScript. Ratchet is stack-agnostic. The audit detects your toolchain and writes acceptance commands in it; the loop just runs whatever the criteria say.
anthropics/skills, obra/superpowers — give agents expertise: personas, domain knowledge, tool recipes. Ratchet gives agents a contract. They compose: load whatever expertise you like; Ratchet governs how the work lands.agent-harness (in the repo above): a manifest → plan → loop-controller state machine in Python + JSON. Ratchet takes the same discipline — bounded retries, escalation, never trust the agent's own claim of success (that's where --verify fresh comes from) — and bets on the opposite implementation: the smallest possible contract, one markdown file, zero runtime scripts, reviewable in a PR.loop-library documents which loops practitioners run. Ratchet is how one loop executes safely.audit → open PR with backlog) — .github/workflows/ratchet-audit.ymlMIT. If Ratchet saved you a night of babysitting an agent, a ⭐ is the thank-you that helps others find it.
.claude-plugin/
marketplace.json
plugin.json
.github/
workflows/
ratchet-audit.yml
.gitignore
CONTRIBUTING.md
docs/
backlog-format.md
sonnet-compatibility.md
examples/
BACKLOG.example.md
NEXT.example.md
v2/
BACKLOG.example.md
lanes/
api.example.md
core.example.md
ui.example.md
NEXT.example.md
README.md
LICENSE
README.md
skills/
ratchet-audit/
SKILL.md
ratchet-backlog/
SKILL.md
ratchet-loop/
executor-rules.md
SKILL.md
ratchet-recommend/
SKILL.md
ratchet-ship/
SKILL.md© 2026 Flowy · Free and open source
Built for Claude Code · Not affiliated with Anthropic