rabadon

overview / commands

every verb of the rabadon CLI

Every verb of the rabadon CLI. The CLI is a thin dispatcher (native/rabadon-cli.sh): recognized verbs go straight to a native binary, lifecycle verbs (init/remove/doctor) go to hooks/manage.mjs.

every verb

commandwhat it does
rabadon init [dir] [--no-llm] [--global]Author a guard, lint it, and merge the gate hooks into .claude/settings.json.
rabadon on | off | status | toggleSwitch supervision mode. The mode is one file (~/.rabadon/mode: enforce, watch or silent) the gate reads, so it is deterministic in any shell.
rabadon lens [transcript.jsonl | dir] [--days N]Alias: rabadon cost. Sessions, tokens and cost, read straight off the transcripts Claude Code already writes to disk. Zero instrumentation: nothing has to be wrapped, no key is needed, and no model is called to produce any number here — the metering is byte-exact arithmetic over files that are already on your machine.
rabadon usage [--days N] [--project P] [--full] [--json] [--explain] [--signals]Alias: rabadon stats. The ledger. Refusals grouped by rule id with each rule's reason, plus headline totals. Drills and self-tests are excluded from every number. rabadon on, off and wrong stay on the chained ledger, but they run outside any project, so they are never listed as one.
rabadon report [--days N]The same numbers as usage, rendered as Markdown on stdout with a methodology footer (source spool, drill exclusion, reproduce command). For pasting into a PR or a README.
rabadon drillFire one tagged synthetic dangerous command (git push --force origin main) through the real gate so you see the refusal text in about 30 seconds. The event is tagged at emit and excluded from the ledger.
rabadon trace [run] [--days N] [--last]One run, step by step: which step was caught, what the check said, whether the repair was accepted or the fake fix refused, and what the repair cost. Reads the spool only — nothing here calls a model, and every number printed is already in the ledger.
rabadon audit [--days N]Verify the hash-chained spool. Every event carries prev = the seal of the previous line in its day file (HMAC-SHA256 under $RABADON_DIR/chain.key, or plain SHA-256 on a day opened without a key). This re-walks the chain and answers one question: was the ledger edited after the fact? A broken link is named by file and line.
rabadon replay [--days N]Render the verified session timeline event by event, with a chain mark per line (a check mark before the first break, a cross from there on). The "what happened" view with the tamper check inline. (Implemented as audit --replay.)
rabadon exec -- <cmd>Run <cmd> under a kernel sandbox compiled from guard.json: each protectedPaths entry becomes a read-only fence, and "network":"deny" cuts the network. A forbidden write fails with EPERM even if the hook was bypassed.
rabadon repair [dir] [--cmd "<check>"]Close the repair loop. A caught red check -> claude -p proposes a fix in an isolated copy -> the same check re-runs there. Green with test files hash-unchanged -> the verified patch is held at .rabadon/repair-<ts>.patch (never auto-applied). Fake or test-weakening fixes are rejected.
rabadon export --otlp [--days N]Emit the ledger as OpenTelemetry OTLP/JSON traces on stdout: one trace per session, one row per tool call, refusals as ERROR spans, GenAI semantic-convention token attributes where token counts exist. Drop it into Jaeger, Grafana Tempo, Honeycomb, or Langfuse's OTLP endpoint.
rabadon lint [dir]Validate guard.json and refuse to certify a rule the gate will ignore. Run this before trusting a hand-edited guard. (init runs it for you.)
rabadon remove [dir] [--purge] [--global]Alias: rabadon uninstall. Strip exactly rabadon's hooks (and a rabadon-owned statusLine) from settings.json, leaving everything else in place. Backs up before it edits.
rabadon doctorHealth check: native binaries built, binary/package version lockstep, kernel sandbox backend, global hook health (every hook command in the user settings file Claude Code reads — $CLAUDE_CONFIG_DIR/settings.json when that is set, else ~/.claude/settings.json — points at a file that exists and belongs to this install), claude CLI presence, spool size and retention.
Environmentrabadon is deterministic by default: no variable below needs to be set for any law to hold, and with none of them set nothing calls a model.

conventions

Maturity tags: [stable] = shipping and tested on this machine. [building] = code exists, not yet complete — do not rely on it.

Common exit-code convention: 0 success, 1 an error or a failed check, 2 a refusal or bad usage, 3 a precondition missing (no backend, no proposer, no runnable check). Specific codes noted per verb.

Also dispatched, each with its own --help screen, reference section still to be written: budget (write the spend ceiling the gate halts at) · do (plan a task into steps and run them under the arbiter) · loop (run an existing plan) · verify (decide pass/fail on one contract) · net (run this repo's strongest check and record the verdict; the first check command seen for a project is trusted, and a changed one waits until rabadon init is run there again) · truth (what this repo already knows how to check) · drift (did the session wander off its promise) · serve (the team ledger). native/cli_test.sh holds every shipped binary to being reachable through this CLI and listed on the help screen, because installing rabadon puts exactly one file onto your PATH — the dispatcher — so a binary it does not name is a binary nobody can run.