overview / commands / rabadon usage
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.
maturity: stable — shipping and tested
Flags: --days N (window, default 7) · --project P (one project only: its name, or its directory such as "$PWD", ./app or ., labelled by basename exactly as the gate labels a session's working directory) · --full (list every catch with timestamp and detail) · --json (machine output) · --explain (the session-close counter, re-derived; below).
Exit: 0 when the ledger rendered — including a genuinely empty ledger, which is a real answer and comes with the onboarding block. 1 when --project P matched nothing: the message names P (and, for a directory, the label it was read as), the spool and the window it searched, lists the projects that ARE in the window, and stdout stays empty on all three renderers, so a script asking "how many catches for P this week" can tell a wrong name apart from a clean week. 2 on an unknown flag, or on a --days that is negative — a window cannot end before it starts.
--brief, development build)rabadon usage --brief is the end-of-session result for the latest recorded session-close in the selected window. Its first line says what happened in plain words, then the facts the ledger recorded for that close:
The first line is one of on track, correction pending, unknown (the reviewer could not tell), unverified — <reason> or not reviewed — <reason>. Corrections are the ones the gate sent back to the same agent; "a later review found no gap" is printed only when a review recorded after the last correction did. Use --project (a name or the project's directory) to avoid selecting another project's session; --full prints whole reasons and the exact cost.
Use rabadon usage --brief --session ID for an exact recorded session; it is then called "this session", not the latest. A missing close returns exit 1 with no completion judgment instead of borrowing another session. If the ID occurs in multiple projects, add --project. --session requires --brief and a nonempty ID; otherwise it returns exit 2.
An unreviewed or unknown latest close never falls back to an older successful review. A missing reviewer cost stays unknown. An on_track review is explicitly not independent proof that the task is complete. --brief cannot be combined with --json, --md, --explain or --signals; incompatible combinations exit 2. This option is not in the published stable npm package.
--explainWhen a session closes (SessionEnd, or Stop), the gate computes one line once, never on the hot path, writes it to the ledger as a COUNTER event and prints it:
rabadon usage --explain re-derives every digit of it from the ledger and names the ledger lines; usage --json carries the same data under .counter. The formula is in native/counter.h:
chains_cut: repeat, oscillation or root-migration sequences in this session that ended on an INJECT or a STOP. A refusal that ended no flagged sequence (a protected path, a budget cap) is not a chain cut.fixed_instantly: of the chains an injection cut, the ones where, in the 3 moves after it that reported an outcome, the same error signature did not come back and no suite was red. Edits do not fill the window, a chain a refusal cut is never counted as fixed, and the agent saying it fixed something is not evidence.median(uncut_chain_lengths): measured on the move rings of this project's other sessions on this machine that were never cut (no INJECT, no STOP). Fewer than 3 (MIN_HISTORY) and no dollar figure is printed; there is no fallback coefficient.avg_call_usd: this session's cost over its assistant calls, from the agent's own local transcript. Nothing goes to the network.inject_usd: rabadon's injected text, charged at the upper bound: 400 characters per injection, 4 characters per token, at the input price.repair_usd: the repair arm's own tokens, off its COST lines.Prices come from a snapshot of the LiteLLM table written once to $RABADON_DIR/prices.json (.counter.prices.cached) and never fetched again. Input, output, cache write and cache read are priced separately: most of a long session is cache read at a tenth of the input price, and folding it into input inflates the figure. rabadon cannot see the billing plan, so the basis is the API list price (basis: API list price (api_list) in --explain); on a subscription the figure is theoretical.
When the counter does not know, it says so instead of printing a figure:
| situation | printed |
|---|---|
| no session transcript | the chain counts, oturum kaydı bulunamadı, tahmini tutar hesaplanamadı |
| the model's price does not resolve | the chain counts, model fiyatı çözülemedi, tahmini tutar hesaplanamadı |
| fewer than 3 measured uncut chains | the chain counts, tahmini tutar için ölçüm birikiyor |
| a net negative | the negative, and rabadon bu oturumda kendi masrafını çıkarmadı |
| no intervention | rabadon: bu oturumda müdahale yok. |
--signals — a different source, not a different rendering--signals reads the per-session move rings under $RABADON_DIR/sessions instead of the refusal ledger, and replays the five R2 detectors (repeat, oscillation, root_migration, scope_drift, green_redefined) over every surviving move. Those detectors are silent: on 2026-08-26 none of them refused anything and none of them reached a decision, and the screen says so in its second line. It is read-only — measured the same day, the file and mtime set of $RABADON_DIR hashes the same before and after the run (reports/kosu/RAPOR/f2-2-readonly.out).
Three things the screen prints that a reader has to be able to place:
LOSS: block with the count and the ring file behind it. Every number under it is over the moves that survived, not over the moves that happened. On the frozen corpus of 2026-08-26 that was 527 moves on disk against a header count of 654 — 127 gone, all of them from one long session's overflowed ring.NOT MEASURED (n=0). A detector with no samples renders as this plus the corpus fact behind its zero (how long the longest identical run was, how many times the most-edited file was edited, and so on). Zero samples is not a result and is not rendered as one; four of the five detectors read that way on the frozen corpus.n with the session file behind it. A detector that did fire prints a raw count and the count of those samples a human has labelled. With no labels there is no rate, and the screen prints no rate: raw counts only.Nothing on this screen is a counterfactual. It reports what rabadon wrote, not what would have happened without it.
Exit: 0 when the screen rendered, including an empty corpus, which prints that it could not measure rather than printing zeros. 2 when --signals is combined with a renderer flag such as --json, which is refused rather than silently ignored — there is no JSON form of this screen.
Locked by native/signals_screen_test.sh (38 assertions), which drives the binary against a synthetic ring that overflows on purpose, so a screen that hides a loss falls red.
rabadon on | off | status | toggle · rabadon export
How much disk does the ledger use?