Trust, but verify. A zero-dependency evidence ledger that stops AI coding agents from claiming "done" until they can prove it.
Quickstart · How it works · Agent Skill · CI gate
Coding agents are confident. They will look you in the eye and say:
"All tests pass. The build is green. The bug is fixed. You're good to merge."
…and they never ran the tests. Or they ran them before the last edit. Or the command failed and they summarized the failure as a success. You find out at 2am when production is on fire.
receipts fixes this with one rule:
No claim without evidence. Every "tests pass" must be backed by a receipt — a captured, tamper-evident record of the command that was actually run, its real exit code, its real output, and a fingerprint of the source tree at that exact moment.
If the code changes after the evidence was captured, the receipt goes stale and the
gate fails until the agent re-runs the proof. An agent cannot talk its way past
receipts check.
re·ceipts (noun, plural): the evidence you produce when someone says "prove it." Ask any agent that claims it's done.
- Zero dependencies. One Python file, stdlib only, Python 3.8+. Runs on Linux, macOS, Windows, Termux.
- Tamper-evident. Output SHA-256 + source-tree fingerprint. Edit the code, old evidence auto-invalidates.
- Agent-native. Ships as an Agent Skill for Claude Code, Codex, Cursor, and any Skills host.
- CI-ready.
receipts checkexits non-zero on any unverified claim — a real merge gate.
# 1. Point your agent at the skill, or symlink the CLI onto PATH:
ln -s /path/to/receipts/bin/receipts ~/.local/bin/receipts
# 2. In your project, initialize the evidence ledger:
receipts init
# 3. Back every claim with the command that proves it:
receipts add "the test suite passes" -- python3 -m pytest -q
receipts add "the build succeeds" -- npm run build
# 4. Pass the gate before saying "done":
receipts check
# 5. Show your work:
receipts reportA real session (captured from this repo's own demo, not a mockup):
$ receipts init
receipts: initialized evidence ledger at /home/demo/.receipts
$ receipts add "the test suite passes" -- python3 -m unittest discover -s .
receipts: [rcpt-0001] PASS exit=0 0.19s python3 -m unittest discover -s .
$ receipts add "calc.py compiles clean" -- python3 -m py_compile calc.py
receipts: [rcpt-0002] PASS exit=0 0.18s python3 -m py_compile calc.py
$ receipts check
receipts: PASS [rcpt-0001] 'the test suite passes'
receipts: PASS [rcpt-0002] 'calc.py compiles clean'
receipts: VERDICT PASS — all 2 claims backed by fresh evidence.Now change the source and try to coast on old evidence:
$ echo "def sub(a,b): return a-b" >> calc.py && git commit -am "add sub()"
$ receipts check
receipts: STALE [rcpt-0001] 'the test suite passes' — source changed after evidence was captured. Re-run it.
receipts: STALE [rcpt-0002] 'calc.py compiles clean' — source changed after evidence was captured. Re-run it.
receipts: VERDICT FAIL — 2/2 claims not verified. Do not ship.
$ receipts verify # re-run every recorded command, refresh evidence
receipts: re-run [rcpt-0001] PASS exit=0 0.21s python3 -m unittest discover -s .
receipts: re-run [rcpt-0002] PASS exit=0 0.19s python3 -m py_compile calc.py
receipts: VERIFY PASS — all 2 commands still pass.
$ receipts check
receipts: VERDICT PASS — all 2 claims backed by fresh evidence.Every receipt is one of three states. receipts check only passes when all are pass.
| State | Meaning | Gate |
|---|---|---|
| pass | Command exited 0 and the tree hasn't changed since. |
✅ |
| fail | Command exited non-zero. The claim is false. | ❌ |
| stale | It passed, but the source changed after capture. Old proof ≠ current code. | ❌ |
Staleness is the whole point. A test that passed before your last edit tells you nothing
about the code you're about to ship. receipts fingerprints the tree (git HEAD + meaningful
dirty state, or an mtime/size walk for non-git projects) and re-checks it on every check.
Build artifacts (
__pycache__,.pytest_cache,node_modules,dist, …) are filtered out of the fingerprint, so running your tests doesn't stale its own receipt.
| Command | What it does | Exit 0 when |
|---|---|---|
receipts init |
Create .receipts/ ledger + .gitignore entry |
always (idempotent) |
receipts add "<claim>" -- <cmd> |
Run <cmd>, capture output/exit/fingerprint as a receipt |
the command passed |
receipts check |
Verify every claim is fresh + passing | all receipts pass |
receipts verify |
Re-run every recorded command now, refresh evidence | all re-runs pass |
receipts report [--out F.md] |
Emit a Markdown verification report | verdict is PASS |
receipts list |
List all receipts | always |
receipts show <id> |
Dump one receipt as JSON | id exists |
Every command accepts --dir <path> to operate on a project elsewhere. add and verify
accept --timeout <seconds> (default 600).
The ledger lives at .receipts/ledger.json and is git-ignored by default — evidence is
machine-local and regenerated by re-running, never committed. Do not hand-edit it.
Evidence you can tamper with is not evidence.
receipts ships with a SKILL.md, so any Skills-aware agent can load the discipline
directly. Install it for your agent:
# Claude Code (plugin marketplace)
/plugin marketplace add Kaiser0733/receipts
/plugin install receipts
# Any Skills host via the skills CLI
npx skills add Kaiser0733/receiptsOr just drop SKILL.md + bin/receipts into your agent's skills directory. Once loaded,
the agent is instructed to:
- run proof commands through
receipts add(never bare), - pass
receipts checkbefore claiming completion, - re-record on STALE instead of hand-waving,
- paste
receipts reportso a human can audit every claim.
See SKILL.md for the full rule set the agent is held to.
Make verification a merge requirement, not a vibe:
# .github/workflows/verify.yml
name: verify
on: [pull_request]
jobs:
receipts:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: "3.12" }
- name: Verification gate
run: |
python3 bin/receipts init
python3 bin/receipts add "the test suite passes" -- python3 -m pytest -q
python3 bin/receipts checkThis repository dogfoods its own medicine: ci.yml runs the
test suite across Python 3.9 / 3.12 / 3.14, then initializes a ledger, records receipts,
and gates on receipts check — uploading the report as an artifact.
Each receipt stores:
- the claim and the exact command run
- the exit code, duration, and UTC timestamp
- a truncated stdout/stderr tail (16 KB) and a SHA-256 of the full output
- a tree fingerprint — git
HEAD+ meaningful dirty state (or an mtime/size file walk for non-git projects)
check recomputes the current fingerprint and compares. Any drift → STALE. Any non-zero
exit → FAIL. The ledger is append-only through the CLI; there is no delete command on
purpose.
Does this run my whole test suite again? receipts add runs the command once and stores
the result. receipts verify re-runs everything. receipts check re-runs nothing — it only
compares fingerprints, so it's instant.
What counts as "the tree changed"? Any change git would report (tracked edits, staged changes, new untracked source files), excluding common build/cache artifacts. In non-git projects, any change to file sizes or mtimes.
Can the agent just lie about the receipt? It could edit ledger.json, but that's a
deliberate act of sabotage a human can spot in a diff — the skill's rules forbid it, and the
SHA-256 + fingerprint make a forged receipt trivially detectable against a re-run.
Why not just use a test runner? You still do — receipts wraps it. A test runner tells you what happened when you ran it. receipts is the audit trail that the agent actually ran it, on the exact code it's claiming to ship, and didn't touch anything after. "Trust me bro" is not a verification strategy.
-
receipts diff— compare two ledgers across branches - signed receipts (ed25519) for supply-chain attestation
-
receipts watch— auto-re-verify on file change - first-class JetBrains / VS Code extension
Ideas and PRs welcome — read CONTRIBUTING.md first.
Run the tests before you open a PR (and yes, record them as receipts):
python3 -m unittest discover -s tests -vMIT © Kaiser0733