rabadon
catches your agent’s mistakes.
Checks commands before they run. Reviews finished work against your request.
Hands the evidence back to the same agent.
install
npm i -g rabadon@0.2.5Published command gate. Initialize your project, then enable enforcement.
setup instructions ↗Opt-in preview for Claude Code. macOS 15+ on Apple Silicon.
download & verify the preview ↗
>
>><
>>@<<
>>>><<<
>>>>><@@<
>>>>>><<<<<
>>**@>@<<<<o<
>>>>o>*><@<o<<<
>>>>>>>o><<**<@<<
>*>>>>>>>><<<<<<o<<
>>o>>o>>>>>o<<<<<<<<<
>>@o>>>>>*>>*<<<@<*<<<<
>o>>>>>>o>>@>@<<o<o<<<o<<
>oo>>>>>>>>>>><**<<**<<<<o<
>>>>>>>*>>>>>>><<<<*<<<<<<<o<
>>>>>@>>>>@*>>>><<<<<<<<<<<<<<<
>>>@>>>>>>>>>@>>><@<<<<<<<<*<<<o<
>>>>>>>o>>*>o*>o>><<<<<<<<*<<<<<<<<
>>>>>>>>>>>*>>>*>>><<o<<<<<<<*<@<<<<<
>>>>*>>>>>@>>>>@>>>><*<<<<<<<<<<o<<<<<<
>>>o>>>>>>>>>>>>>@>>><<<<<<*<<<<<<<<<<<<<
>>>>>>>>@>o>>*>>>>>>o><<<<o<<@<<<<<<<<<<<<<
>>>>>*>>>>>>o>>*>>>>>>@<o<<<o<o<<<<<<o<*@<<@<
>>>>>>>>o>>>>@>>>>@>o>>><<@<o<<<<<<<<<<<@<<<<<<
| | |
| | |
_ _ _ _|_|_|_ _ _ _
Recorded field refusals and controlled tests; different measurements. sources & limits ↗
catches/rules/blind spots/changelog[ installation & detailed evidence ]
Get started
One project. One task. See what happens.
Use a project where you can describe the intended result and check whether it happened. Start with one bounded task: a bug fix, an import flow, or a feature with clear requirements. Rabadon stays with the same Claude Code session.
Completion-review preview · macOS 15+ / Apple Silicon · Node 18+ · authenticated Claude Code
01Install the previewDownload, verify, check setup+
Preview build: macOS 15 or later on Apple Silicon only. Requires Node 18+ and an installed, authenticated Claude Code CLI. Other platforms are not part of this preview’s verified installation path.
Preview 0.2.6-preview.20261017.4. Start in a personal project. Download both packages, the native core and its CLI, check them against the SHA-256 sums below, then install the files you checked. This preview is separate from the stable npm release.
| file | SHA-256 |
|---|---|
| rabadon-darwin-arm64-0.2.6-preview.20261017.4.tgz | b05653424009dbacd31d24410fc2b8b0fc5056de2c4e487bebdb619a87491a80 |
| rabadon-0.2.6-preview.20261017.4.tgz | 88367afa34525d53751684d5c5a9f62707177a8aa816fa981f558b0fdae709b5 |
Both sums are in SHA256SUMS.
Any line other than OK means the file is not the published one;
do not install it. npm 11 may warn that it skipped the CLI’s postinstall
script; that script only compiles the core when no prebuilt package is
installed, so it is not needed here. doctor checks the installed
binaries and setup.
These installation checks do not establish autonomous task success or cost savings.
02Start a supervised taskInitialize and open your session+
Initialization installs the hooks and baseline rules without a model call. Existing settings are preserved. The launcher checks the hooks, names the session, explains model use, and opens Claude Code with completion review enabled. Give Claude your task normally; later instructions can refine it.
A fresh project starts the command gate in watch mode.
Completion review can still ask the agent to continue. Use rabadon on
separately if you want rule violations to block commands.
03Read the resultReview status, evidence, and limits+
At completion, a reviewer compares the recorded request with bounded session
evidence and file changes. A grounded gap can send the same agent back to work.
When you exit Claude, the launcher prints the result for that exact session:
the reviewer’s reason, any unresolved correction, and recorded review cost.
rabadon usage --brief --session <id> prints it again.
Printed by the .4 binary from a test ledger. A session the
reviewer passes opens with rabadon: on track — the reviewer found no gap
between your request and the work.
on track
The reviewer found no grounded gap in the evidence it saw. Run your own acceptance checks before relying on the result.
correction pending or unverified
A requested fix may remain open, or the review could not finish. The reason stays visible; missing evidence is not reported as successful completion.
The preview launcher starts new sessions. To continue the same work, keep that session open and give the next instruction before exiting. The launcher does not enable review in your shell or change other Claude sessions.
04Stay in controlModel use, cost, and switching off+
Keep control
Exit the reviewed session to end its review opt-in. rabadon off
returns command enforcement to watch mode; it does not turn off review inside
a session you already launched. rabadon remove removes the project’s
Rabadon hooks while preserving unrelated hooks.
What the review sees and costs
The preview sends your recorded messages, selected agent/tool output and a bounded diff of changed files through your Claude account. Session transcripts must remain readable; the launcher rejects disabled persistence.
There are at most two review calls per user turn, each with a 30-second timeout and a configured $0.25 CLI budget. That budget is a soft limit, not an invoice guarantee. A timeout, missing evidence or exhausted review budget leaves the result unverified. Long-task reliability and net savings are still being evaluated.
Only want the published command gate?
npm 0.2.5 is the published release. It does not include the preview launcher and recent completion-review work described above.
Use rabadon usage to inspect its recorded gate
activity and rabadon off to return to watch mode.
The evidence
Measured, with the limits attached.
The figures below describe their linked datasets and test conditions. Gate refusals, detector precision and runtime cost are separate measurements; none is a success rate for autonomous task completion.
Explore all recorded measurements
Preview 0.2.6-preview.20261017.4 · 17 October 2026
Preview .4: results, changes, and what didn’t improve
- The reviewer caught 15 of 15 dropped requirements it could see, with 0 false alarms on 6 correct solutions. 24 seeded cases on 6 fresh tasks, through the real Stop review, opus at $0.051 per call. Sonnet caught 6 of 18, so opus stays the reviewer. Seeded mechanism test, not field data.
- Dropped code visible to the reviewer: 18 of 18, was 15 of 18. A large diff used to be clipped from its start; .4 rebuilds it without context lines in the same 16 KiB budget (mean packet 21,896 → 21,570 bytes). Held-out set: 41 of 41 visible, was 39 of 41. The 3 drops that had been hidden were caught 3 of 3; the 2 held-out drops that became visible, 1 of 2.
- Reviewer calls cost 47% less. Same 21,191-token packet: $0.1658 → $0.0877, because the one-shot review no longer pays for a prompt-cache write it never reads. In the field, same task: $0.136 → $0.075 per call.
- The supervised agent’s session-start text: 1,467 → 141 bytes in the real installed run (1,975 → 263 on a project with a test suite). The
guard’s blind-spot list goes to you only. A refusal hands the override to you
and tells the agent to ask, instead of offering it
rabadon off. - 31 of 31 steps installed end to end from this site’s HTTPS downloads, on
.4 (and on .3), with a real Claude agent and the real reviewer: install, init, on,
review, the same-session result, the reviewer-auth-failure message, off,
ordinary
claude(not reviewed), remove (your own hook and permission kept), uninstall. The operator’s settings were byte-identical afterwards. - 137/137 native suites, 39/39 node tests; CI green on Linux and macOS.
Review did not save money on short tasks
Pre-registered A/B on 5 fresh tasks with 10–12 requirements each (the sixth was skipped by the protocol’s futility stop). Plain Claude and reviewed Claude were fully right on the first try in all 10 runs, so review found nothing to fix and added $0.075 per turn: $0.252 → $0.330 per correct result (+31%). On short tasks review is insurance, not savings. Long unattended jobs: not measured yet.
inside rabadon
rules
What the gate checks, and why each rule exists.
catches
Real command refusals. A record you can inspect.
benchmarks
Measurements, reproducible evidence, explicit limits.
commands
Commands, hooks, and the pieces that fit together.
blind spots
Known blind spots. Because trust needs boundaries.
changelog
Release history and the changes behind the project.
the gate, on the cases it was built against
34 cases lifted out of real sessions, eleven of them genuinely destructive, and the gate refuses all eleven and nothing else. This measures the command gate on its existing fixture, not completion-review accuracy.
Those eleven are not hypotheticals. They are commands that were typed during real work, by an agent, in a repository that mattered.
The other 23 are the harder half. Every one of them looks dangerous and is not, and a gate that refuses those is a gate you turn off in a week. That is why the floor was recall, and why precision had to climb to meet it rather than the other way around.
Nothing in the fixture was written for the fixture. It was lifted out of sessions that had already happened.
what it found, project by project
31 defects across 8 open-source projects, mined out of 545 commits of their own history. None were invented. Each is a real fix a maintainer shipped, with the test that caught it written by the same engineer in the same commit, and only the source half rolled back. The test cannot look away, because the reason it exists is the defect.
| project | defects | commits | lines | what was wrong with the code |
|---|---|---|---|---|
| expressjs/express | 4 | 46 | 6.5 | a view root read one character short, and an etag guard that stopped being applied |
| tj/commander.js | 4 | 31 | 6.5 | an excess-argument count compared with the wrong operator, and a dropped port guard |
| lodash/lodash | 4 | 218 | 10.5 | a strict index scan starting one place late, and a guard dropped out of word splitting |
| ajv-validator/ajv | 3 | 110 | 5.0 | a maximum treated as exclusive, and a leap second given the wrong timezone sign |
| pallets/click | 4 | 48 | 6.5 | option parsing that lost a boundary case, and a separator handled on only one side |
| pallets/jinja | 4 | 35 | 8.0 | template escaping that let one shape through, and a filter that read past its input |
| pallets/markupsafe | 4 | 30 | 4.5 | escaping that missed a character class, and a comparison that answered in reverse |
| yaml/pyyaml | 4 | 27 | 1.0 | single-line defects in the loader, the smallest of them one character wide |
| total | 31 | 545 | 6.0 | 28 changed behaviour, 3 deletions only |
The smallest defect is one source line, the largest 33. At least one test falls, at most ten. All 31 are deterministic: the red run was repeated three times and the same tests fell every time.
show the two it repaired for real, in express
Not a corpus case. A live run against expressjs/express at commit a3714473, with the arbiter being that project's own mocha suite. Two real source defects, an off-by-one in request handling and a reversed comparison in the response path.
| repairs held | 2 | on a foreign repository, live |
| tree edits | 0 | the working tree was never touched |
| test files locked | 91 | sha256 of the pristine copy |
| suite | 1,260 | tests, the project's own |
| a proposer that skipped tests | REJECTED | test-tamper |
show how a defect was proven real, not invented
| 1 | green | the fix commit, the project's own suite |
| 2 | revert | source half only, test files untouched |
| 3 | red | same suite, three runs, same tests fall |
| cases | 31 | mined out of eight projects' own history |
| deterministic | 31 | of 31 |
| median source | 6 | lines |
| median falling | 1 | test |
the laws are compiled in, not configured
A guard that lives in a config file is a guard the agent can edit. These live in the binary, and the parser that reads the command is the same one the laws are written against, so a new spelling of an old danger does not open a door.
show every rule, and the case each one must let through
| rule | must block | must not block | |
|---|---|---|---|
| ok | baseline-force-push | 1 | 0 |
| ok | baseline-rm-rf-outside | 1 | 2 |
| ok | no-force-push-main | 3 | 10 |
| ok | no-hard-reset-main | 1 | 1 |
| ok | no-rm-rf-outside | 1 | 0 |
| ok | no-rm-rf-outside-project | 1 | 9 |
| ok | no-wrangler-deploy | 3 | 1 |
Canaries intact after judging 34 commands. Every law that blocks something carries a case it must let through, on the same row.
Every law that blocks something carries a case it must let through, on the same line. A rule that only ever says no is a rule nobody keeps switched on.
a repair is accepted only when the proof could not be bought
When a check goes red, rabadon proposes a fix in an isolated copy and then judges it. The judge is the project's own test suite, and the cheapest way to cheat a test suite is to change it. So the suite is hash-locked before the proposer starts, and so is the machinery that decides which tests run at all.
a proposal that neutered the test
a proposal that touched only the source
Locking the test files is only half of it. A proposal can leave every test byte-identical and still buy its green by moving the harness that chooses which tests run, so the harness is locked too, and a file appearing where none existed counts as a change.
show the eight ways of buying a green, and what happens to each
| case | verdict | exit | suite |
|---|---|---|---|
| pytest-ini-added | harness-tamper | exit 2 | ./native/harness_lock_test.sh |
| root-conftest-added | harness-tamper | exit 2 | ./native/harness_lock_test.sh |
| package-test-script | harness-tamper | exit 2 | ./native/harness_lock_test.sh |
| honest-source-fix | verified | exit 0 | ./native/harness_lock_test.sh |
| honest-source-fix-node | verified | exit 0 | ./native/harness_lock_test.sh |
| test-file-edited | test-tamper | exit 2 | ./native/harness_lock_test.sh |
| special-case-sha256 | heldout | exit 2 | ./native/heldout_test.sh |
| special-case-raw-literal | heldout | exit 2 | ./native/heldout_test.sh |
| special-case-length | heldout | exit 2 | ./native/heldout_test.sh |
| comparison-override | heldout | exit 2 | ./native/heldout_test.sh |
| honest-source-fix | verified | exit 0 | ./native/heldout_test.sh |
| honest-fix-with-long-literal | verified | exit 0 | ./native/heldout_test.sh |
| honest-fix-touching-existing-eq | verified | exit 0 | ./native/heldout_test.sh |
| honest-fix-with-short-guard | verified | exit 0 | ./native/heldout_test.sh |
The same six cases against the previous binary come back three pass and three fail, and all three failures are the product printing VERIFIED over a fix that repaired nothing. Both honest repairs still certify, because a lock that refuses real work is not a lock, it is an outage.
what it did while somebody was working
The ledger had been recording since 25 July and nothing had ever surfaced it, so the evidence sat on disk where the engineer who wrote the engine could not see it either. It ran in watch mode almost the whole time, recording a verdict and letting the command through, which is the honest way to read what follows: not saves, but what arming it would have cost, measured before arming it.
Most of it was three laws: 207 ctest-tail-hides-verdict; 205 red-base; 161 red-suite-test-write. the nine days, rule by rule, with every published record behind it
the ledger
Every number here comes from one machine that runs this all day, which is the only honest place a reliability tool gets proven first.
every command it refused, rule by rule, with the raw entry behind each count
| 124 | destructive actions refused before they happened |
| 66,404 | actions handed to the gate to be judged |
| 0 | repairs held after the proof survived the judge |
| 2,937 | refusals recorded in watch mode, where nothing is blocked |
This is the binary’s count for the last 30 days at build time. The headline comes from a separately recorded field measurement. Their collection times and rehearsal filters differ, so the counts are not directly comparable. Reconciling them onto one definition is open work.
everything it has been run through so far
46 days, one machine, one engineer. These are totals, not a sample, and each of them opens onto the thing that produced it.
Guardrails for AI coding agents: where to start
Rabadon checks supported commands against project rules and keeps a local record of its decisions. Use the command gate when an agent can run shell commands in your repository and you need to inspect what was allowed or refused.
Check destructive commands
Start with the recorded command refusals to see the situations covered. Watch mode records decisions; enforcement must be enabled before a refusal blocks execution. Command matching does not cover every way an agent or subprocess can change a file.
Review the evidence behind an agent run
Read the benchmarks and their limits, then compare them with the implementation changes. A command gate does not establish that every code change is correct.
Connect it to your coding workflow
The installation and first-task flow separates the Claude Code completion-review preview from the published command gate. Agent integrations have different hook capabilities; completion-review equivalence outside Claude Code has not been established.