- The whole policy engine, 45 rules armed by default
- Day, session and total spend caps at the tool boundary
/guard-status,/guard-cardand the local decision journal- Signed, hash-chained receipts (
pr guard receipt) pr spend, andpr reconcileagainst a provider invoice- Both open-source verifiers, offline or in the browser
- One independent RFC 3161 timestamp, free, so you can see what an outside party's receipt looks like on your own run
- Community support
A hard limit on what coding agents may spawn
One session spawned 171 subagents to check one thing.
Provenrail asks you at the 21st.
Every subagent starts a fresh context that is billed and metered on top of the one you are already in, and nothing anywhere caps how many of them a session may start. Claude Code refuses at three levels deep; it has no opinion about width. Provenrail counts the spawns and asks you before the twenty-first, from one policy file that is enforced identically in Claude Code, Codex, Gemini CLI, Copilot and Cursor. Where there is no permission prompt to answer, an unattended run or CI, the question becomes a refusal.
Said plainly, because you are going to install this: only the Claude Code adapter is driven with a payload captured from the running CLI. The other four are written from each vendor's published hook contract and are not yet driven against a live install. The fixture for every host is in the repository and each one says which it is.
It starts by reading, not by blocking. pr report --fanout goes over the
transcripts already on your disk and tells you how wide your own sessions spread and
what their subagents cost, before you arm anything. Measured on the 915 sessions it was
built against: the widest spawned 93 times and spent $253 on subagents alone.
Free and MIT. No account, no server, and no network call in the decision path. Read every rule.
Honest scope: the policy sees the tool calls your agent routes through its hooks, and a
record is tamper-evident once it reaches a sink. Completeness is never claimed: a process
that never calls the hook will not appear. Anthropic documents that a hook's
permissionDecision is ignored in bypassPermissions mode, so
under --dangerously-skip-permissions Provenrail records and advises rather
than blocks. The full limits are below.
One command tells you
how wide your own sessions spread.
A guard only pays out on a day that has not happened yet. The transcripts of the
work your agents already did are sitting in ~/.claude/projects right
now. pr report reads them, offline, and says what they cost, what
they ran, what they touched, and which of their commands these rules would have
stopped.
uv tool install provenrail && pr report
Nothing to set up, no account, no config file, and no network call. It is useful
the first time you run it, which is the one thing no guard can be. Four flags:
--since for a window, --project to narrow by name,
--json for the versioned machine-readable document, and
--share for the version that is safe to post, which drops the root
path, replaces every project name with a short hash, and reduces each command to
its verb and flags so nothing left in it is an operand.
The dollar figure is estimated at API list price, and notional on Pro and Max flat-rate plans, where there is no per-token charge at all. It is also a floor. Over the 49 sessions in the run below where Claude Code had recorded its own total, this estimate came out about 12 per cent under it. Two known causes are not modelled because neither is visible in a transcript: fast mode bills Claude Opus 5 at $10/$50 per million tokens against the standard $5/$25, and web search bills $10 per 1,000 searches. No multiplier is guessed at to close that gap, so the number misses low rather than high.
pr report reads Claude Code transcripts. No other agent host is read.
$ pr report --share PROVENRAIL REPORT 942 sessions across 23 projects, over 31 days, ran 79,883 tool calls and spent an estimated $7,863.51. 517 of those would have been stopped: 23 refused, 494 sent to you to approve. 2,163 transcripts, 3.79 GB, 128.0s COST estimated total $7,863.51 model calls priced 69,573 by model claude-opus-5 $6,646.54 41,554 calls claude-sonnet-5 $600.45 15,412 calls claude-sonnet-4-6 $471.85 11,305 calls Claude Code recorded its own total for 49 of these sessions: $5,704.12, against $5,015.01 estimated here for the same ones. Spend is estimated at API list price, and notional on Pro and Max flat-rate plans. ACTIVITY tool calls 79,883 bash commands 51,494 files written or edited 7,027 distinct RISK replayed offline through these rules would have been refused 23 0.03% would have been sent to you 494 0.62% 138 ask production.deploy-command 119 ask access.disarm-the-guard 104 ask destructive.force-remove # One machine on 16 September 2026. This is a run, # not a benchmark. Run it, and the numbers are yours.
The classifier is part of auto mode.
Most unattended runs do not start in auto mode.
Quoted from Anthropic's own documentation, read 16 September 2026. Where the classifier is absent, hooks are still loaded, so a deterministic policy is what is left deciding.
| How the agent is started | Built-in starting permission mode | Anthropic's classifier | Provenrail's rules |
|---|---|---|---|
| Interactive session, Pro, Max or Team | auto mode | Runs | Runs |
claude -p, the headless and CI entry point |
Manual, on every plan | Not in this mode | Runs |
| The Agent SDK | default |
Not in this mode | Runs |
| Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry, Claude Platform on AWS | default |
Not in this mode | Runs |
Sources, quoted rather than paraphrased. Starting modes and the auto-mode behaviour:
code.claude.com/docs/en/permission-modes.
"For -p, the built-in starting permission mode is Manual on every plan" and
"Without --bare, a -p session runs the hooks in a project's
.claude/settings.json":
code.claude.com/docs/en/headless.
The Agent SDK runs settings-file hooks by default through setting_sources:
code.claude.com/docs/en/agent-sdk/hooks.
A starting mode is a starting point, and anyone can switch modes mid-session.
What auto mode already does, and does well
In an interactive session, Claude Code "runs git status itself before a
command that would discard uncommitted work, such as git reset --hard or
rm -rf", and it "never lets a permissions.allow rule or a
PreToolUse hook that returns 'allow' approve an rm or
rmdir command that targets a critical path". If an interactive session on
Pro, Max or Team is the only place you run agents, you already have most of what a
destructive-command guard sells, free, and did not have to install it.
What it is not is a cost control, and it is not present when the session did not start in auto mode. Those two gaps are what this product is for.
Limits, stated plainly
Anthropic's hooks documentation says the permissionDecision field on
PreToolUse and PermissionRequest hooks "is ignored in
bypassPermissions mode, when the classifier hasn't finished running
(indicated by pendingClassifier: true), or when the API has denied the
call". So under --dangerously-skip-permissions Provenrail journals the
decision and tells the agent, and does not stop it.
permissions.deny rules are a different mechanism and do block in every
mode; a hook is not one of those, and we will not imply otherwise.
A rule matches text. A command written to defeat a pattern, a delete hidden inside a script or a one-liner, is not caught. That is a property of every hook of this kind, this one included. What target resolution buys is precision on the commands agents actually emit, not immunity to one written to get past it.
A day cap the agent
cannot talk its way past.
No vendor stops an agent on a dollar figure. Claude Code reports
total_cost_usd at the end of a -p run, which is the
invoice, not a brake.
The hook payload already carries transcript_path. Provenrail reads that
transcript from where it last stopped, prices every new assistant message from its
reported model and token usage, adds the delta to a ledger that survives across hook
processes, and refuses the next tool call once the day is over budget.
pr guard budget 25
There is no default cap, because a cap you did not choose is a claim about your
money. Set one and pr guard status prints what has been spent against
it. Two things this page will never soften: the figure is estimated at API list
price and is notional on Pro and Max flat-rate plans, where there is no per-token
charge to cap; and the transcript is written asynchronously, so the cap stops the
agent within a turn rather than at the exact dollar.
# Arm a cap. Nothing is capped until you choose the number. $ pr guard budget 25 Spend cap: $25 per day, written to .provenrail.json # The session runs. The hook prices the transcript as it grows. > npm test denied budget.day estimated day spend is $25.5000, over the $25.0000 cap, so this tool call is refused. Stop here and tell the person what happened rather than working around it. Spend is estimated at API list price, and notional on Pro and Max flat-rate plans.
# One file at the repo root, reviewed in a pull request {"policy": {"use": ["git-worktree", "destructive", "secrets", "production"], "budgets": [{"scope": "day", "limit_usd": 25}]}} # A delete inside the project runs without a word > rm -rf ./build allowed # A delete that leaves it does not > rm -rf ~/Projects denied destructive.recursive-force-remove
It screens where a command points,
not what it is called.
Nobody has ever lost work to the letters rm -rf. They lost it to what
came after them. rm -rf .next comes back in twelve seconds.
rm -rf ~/ is the end of a laptop. A pattern cannot tell those apart,
because the difference is not in the text, it is in where the text points. So the
rules resolve the target against the working directory the host hands them.
We measured that against one frozen corpus: 36,977 Bash commands pulled from 1,247
real agent sessions, replayed offline in the directory each one actually ran in.
Verb matching interrupted 923 of them. Target resolution interrupts 222. On 40
commands taken from public data-loss reports, it stops 40 of 40. Run the same
measurement over your own transcripts with
python tools/measure_guard.py, which makes no network call.
The record
A rule name is not evidence.
When a model-based classifier stops something, what survives is a line in a chat log
and a label such as [Data Exfiltration]. Nothing a third party can
recompute. Every Provenrail decision is Ed25519 signed and hash-chained to the one
before it, so a client, an auditor or the other side of a dispute can check it without
trusting the agent, the server, or us. Below is a real record, verified live in your
browser. Flip one character and watch it break.
Runs entirely in your browser via the open-source verifier. Your data never leaves your device, not even to us.
Decide, record, check.
Three moving parts, because fewer parts to trust means less to audit.
The verdict is computed locally
The hook reads the tool call, resolves its target against your working directory, prices the transcript against your cap, and answers. No network call is in that path, so an unreachable server can never turn a refusal into an allow.
Each decision links to the last
Allowed, refused or escalated to a human, every decision is signed and carries a hash of the one before it. Reorder or delete one and the chain stops matching. pr guard receipt exports the lot as a portable bundle.
Anyone can check it without you
The open-source verifier reconstructs the chain offline. A Python implementation and a browser one are held to frozen public conformance vectors in CI, so verification never depends on running our code. An RFC 3161 anchor adds a public authority's time.
Two commands interactively.
The same file in CI.
The Claude Code plugin carries its own
dependency-free engine, so 45 rules are armed on the next tool call with no package,
no account and no config file. /guard-status shows what it has actually
stopped, and /guard-budget sets a cap without the CLI installed.
/plugin marketplace add pofky/provenrail
/plugin install provenrail-guard@provenrail
For headless and CI, pr guard install writes the same hooks into the
project's .claude/settings.json, preserving any hooks already there.
Anthropic's documentation states that "without --bare, a
-p session runs the hooks in a project's
.claude/settings.json", so that one file is the whole CI setup.
Installing the CLI on top signs the local history in place rather than starting a
new one.
uv tool install provenrail/npm install provenrail
Read the quickstart guide# 1. Install and wire the hooks (nothing leaves the box) $ uv tool install provenrail $ pr guard install && pr guard budget 25 # 2. Run the agent the way you already run it $ claude -p "upgrade the test suite" denied budget.day (the cap held, no classifier here) # 3. The decisions are signed. Check them yourself. $ pr guard receipt 1 DENIED budget.day $ pr verify guard-receipt.json RESULT: VERIFIED
Watch it work, end to end.
Real terminal sessions, no mockups. Every command and every output below is captured verbatim from a live run.
pr quickstart, pr demo, pr verify.
Everything that stops the agent is free.
One paid option, and it buys an artefact rather than a subscription to your own tooling.
- Unlimited
pr anchor-pushon your receipts - An RFC 3161 timestamp from a public authority on every anchor, so the date is not ours to assert and not yours either
- A public receipt page your client, your finance team or an auditor opens with no account, and checks offline with the open-source verifier
- You send a 32-byte fingerprint of your records and nothing else. You keep every record; there is no field one could arrive in
- Your licence key is the only credential, so buying it is the whole setup
- Email support
Nothing that refuses a tool call is behind a payment. The paid option adds an outside party's signature on the time, which is the one thing you cannot issue to yourself. We host no agent records. 14-day refund.
Common questions.
uv tool install provenrail then pr report. It reads the Claude Code transcripts already in ~/.claude/projects, prices every assistant message from the model and token usage the transcript records, and prints a total per model, per project and per day. It needs no account, no config and no network call. The figure is estimated at API list price, and notional on Pro and Max flat-rate plans, where there is no per-token charge at all, and it is a floor rather than an exact number: fast mode and web search bill extra and neither is visible in a transcript.pr report. Claude Code writes a transcript of every session, and the report reads them offline and says how many sessions ran, over how many projects and days, how many tool calls and bash commands they made, how many distinct files they wrote or edited, which tools they reached for most, and which of their commands the Provenrail rules would have refused or sent to you to approve. Add --share to get a version safe to post, with the root path gone, project names replaced by hashes and every command reduced to its verb and flags.git status itself before a command that would discard uncommitted work, and that it never lets a permissions.allow rule or a PreToolUse hook that returns "allow" approve an rm or rmdir command targeting a critical path. What that classifier does not do is run in claude -p, the Agent SDK, Amazon Bedrock, Google Cloud's Agent Platform or Microsoft Foundry, which start in the permissive default mode, and it does not cap spend anywhere. Hooks run in all of those places.PreToolUse payload carries transcript_path. Provenrail reads that transcript from where it last stopped, prices each new assistant message from its reported model and token usage, adds the delta to a local cross-process ledger, and refuses the next tool call once the day cap is crossed. Set one with pr guard budget 25. There is no default cap, because a cap you did not choose is a claim about your money.claude -p run prints total_cost_usd when it finishes, which is the invoice arriving after the spending. Provenrail adds the ceiling Claude Code does not take: pr guard budget 25 writes a $25 day cap into .provenrail.json, and the PreToolUse hook refuses the next tool call once the day is over it. The figure is estimated at API list price, it is notional on Pro and Max flat-rate plans where there is no per-token charge to cap, and because the transcript is written asynchronously the cap lands within a turn rather than at the exact dollar.claude -p, the Agent SDK, Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry and Claude Platform on AWS as starting in the permissive default mode, with no classifier in front of the tool call. Hooks do run in all of them: without --bare, a -p session runs the hooks in a project's .claude/settings.json, and the Agent SDK runs settings-file hooks by default. A deterministic policy in that hook is what is left deciding in CI and headless.permissionDecision field is ignored in bypassPermissions mode, when the classifier has not finished running, or when the API has denied the call, so under --dangerously-skip-permissions Provenrail records and advises but does not block. And a rule matches text, so a command written to defeat a pattern is not caught, which is a property of every hook of this kind.uv tool install provenrail (or pip install provenrail inside a virtualenv), export the decisions with pr guard receipt, then run pr verify guard-receipt.json. The tool recomputes the hash chain, every Ed25519 signature and every anchor locally, trusting neither the agent nor the sink. A second verifier written in JavaScript runs the same algorithm in the browser, and both are held to frozen public conformance vectors in CI.