overview / commands
rabadon CLIEvery 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.
| command | what 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 | toggle | Switch 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 drill | Fire 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 doctor | Health 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. |
| Environment | rabadon 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. |
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.