Skip to main content

receipt

Run a command. Get a receipt for what it actually touched — not just what it was asked to do.

An AI agent (or a script, or a CI job) says it's going to fix a bug in one file. Nothing checks whether that's what it actually did until someone reviews the diff by hand, if they do at all. receipt snapshots the working directory before and after, and reports pass, fail, or unverified — same three-status shape as invariant, firedrill, and carabiner.

$ receipt run --task "fix the auth bug" --declare app/auth.py \
    -- python fix_auth.py
[FAIL] touched 1 undeclared file(s): app/payments.py
receipt written to receipts/20260908T121251Z-4f2c9a1b.json

Three statuses, one of them meaning something different here

pass — touched only what was declared. fail — touched something outside the declared scope, named exactly. unverified — no scope was declared for this run at all.

That third one is a deliberate difference from invariant/firedrill/ carabiner, where unverified means "a check that should have run, didn't." Here it means "no promise was made this time" — plain audit logging is a normal, legitimate use of this tool, not a degraded one. So unverified does not fail the build; only a broken declared promise (fail) does.

What it actually does

  1. Hashes and permission-bits every file under the watched directory (sha256
    • mode, skipping .git, __pycache__, etc.). Only regular files are hashed — a FIFO, socket, or device node is skipped rather than opened, since open() on a FIFO with no writer on the other end blocks forever (a real bug, found and fixed: a --dir /tmp scope check hung two CI runs for a full 6 hours each before this guard existed).
  2. Runs the given command, captures stdout/stderr/exit code/timing, and redacts secret-shaped text (env-var-style API_KEY=... assignments, credentialed URLs, well-known token prefixes, PEM key blocks) before any of it is stored — see "What redaction doesn't mean" below. A command that never launches at all (bad --dir, missing binary) still produces a receipt — fail, with the launch error as the detail — instead of a Python traceback and no evidence.
  3. Snapshots the directory again, diffs the two. A removed path and an added path with identical content are reported as one renamed pair, not an unrelated delete-plus-create; a path whose content is byte-identical but whose permission bits changed is reported as mode_changed — see "What touched means" below.
  4. If a scope was declared (exact paths, or glob patterns like app/*.py), checks the diff against it.
  5. Writes the whole thing — command, task, diff, declared scope, verdict — to receipts/<timestamp>-<random>.json alongside a sha256 of the receipt itself, same evidence-bundle idiom as invariant's --evidence.

Zero dependencies — stdlib only (hashlib, subprocess, argparse, fnmatch).

Install

pip install receipt-evidence        # the command it installs is `receipt`

Or from a checkout, for development:

pip install -e .

Use

receipt run --task "what this is supposed to do" \
  --declare path/one.py,app/*.py \
  --dir . --out receipts/ \
  -- your-command --with --args

Omit --declare to just log what happened without a scope to check it against (unverified, still a written receipt, still exit 0).

Test

python tests/test_receipt.py

What touched means

touched is the union of every file that was added, removed, had its content modified, was renamed (a removed path and an added path sharing a content hash), or had its permission bits changed with content otherwise identical. A rename or a chmod on a path outside the declared scope is a real fail, named clearly — sneaky.txt (renamed from output.txt), or secret.env (permissions changed, content unchanged) — not silently folded into "nothing happened" the way a plain content-hash diff would.

What pass doesn't mean

pass only means "touched nothing outside the declared scope within --dir." A write anywhere outside that tree — /tmp, ~, a sibling directory, an absolute path elsewhere in a monorepo — is invisible to receipt and won't affect the verdict. Point --dir at the smallest tree that actually bounds what the task could legitimately touch; don't read pass as "touched nothing on the filesystem."

What redaction doesn't mean

Captured stdout/stderr and the command's own argv are swept for secret-shaped text (receipt/redact.py) before a receipt is written — this closes a real gap found during review: a wrapped command that echoed API_KEY=sk-... landed that value verbatim in the receipt JSON. The sweep is a regex net for common shapes, not a guarantee. It will not catch a secret with no recognizable shape (e.g. a bare 40-character hex string with no key name attached, split across two log lines, or base64-wrapped). If a command's output might contain something sensitive in an unusual shape, don't assume the receipt is safe to share as-is — read it first.

What's deliberately not here yet

No network/API-call capture — only filesystem diffing. "What did this agent touch" is answerable this way; "what did this agent call" isn't, without hooking into a specific agent framework's own trace or intercepting traffic, which is a real, separate, much bigger project.

No policy evaluation or rule composition beyond a flat declared-scope check — that's deliberately a different tool's job. receipt stays the evidence producer; invariant is where richer policy (is this evidence actually OK, across multiple runs, with other checks composed in) belongs.

MIT licensed.

Release files for receipt-evidence 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for receipt-evidence 0.1.2
File Size Uploaded
receipt_evidence-0.1.2.tar.gz 20.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for receipt-evidence 0.1.2
File Interpreter ABI Platform
receipt_evidence-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 34.3 kB

Release files / receipt_evidence-0.1.2.tar.gz

Download URL receipt_evidence-0.1.2.tar.gz
Size 20.3 kB
Tags Source
SHA-256 checksum
How to use checksums
0688b9a1bcc5f449ac3cb79a1482c7eb2d2406a988a3129776fdbbe89ad1b9ef
BLAKE2b-256 checksum
How to use checksums
d7f2e0c88e4e86c947d97636633f7a1cbc8636059fcf6a2ed1c3ec63f4dc8360
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / receipt_evidence-0.1.2-py3-none-any.whl

Download URL receipt_evidence-0.1.2-py3-none-any.whl
Size 14.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6c5990a97b741a962e8090f57601848a7efa23616b58e82aa4e1fab25267df42
BLAKE2b-256 checksum
How to use checksums
3aa7a03fe00e239abc3dbaf1ad4a15cffd46238fde7f3bdcca093fa73cc76741
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

2 release files

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page