Verifiable evidence for AI-assisted engineering
Project description
agentwitness
Record what your coding agent did, under whose authority, with what scope, and produce signed evidence anyone can verify offline. Useful for PR review, incident response, security questionnaires, and AI governance audits.
$ agentwitness summary
manifest: 7c6adca6eae24556f8215314cdb74094aa31fe3c747a508d3ef16fe60205a608
issued: 2026-05-23 17:32:57
expires: 2027-05-23 17:32:57
sessions (2):
sess_d3cf2597d1b39167aa6e3a 3 events 2026-05-23 17:32:57 → 17:32:57 (claude-vis-test)
sess_c23db027e0ddf6e57bf9b7 18 events 2026-05-23 14:14:23 → 14:48:01 (claude-session-2)
$ agentwitness blame src/auth.ts
events touching src/auth.ts:
2026-05-23 14:18:42 tool.requested Edit sess_c23db027e0ddf6e (ok)
2026-05-23 14:18:43 tool.completed Edit sess_c23db027e0ddf6e (ok)
$ agentwitness export -o ./evidence
Bundle written to ./evidence
Verify with: agentwitness verify ./evidence
$ agentwitness verify ./evidence
agentwitness verify: OK (./evidence)
events verified: 18
sessions seen: 1
Status
v0.1.0, alpha. First functional release: record via Claude Code hooks, export a bundle, verify it. POSIX only (Linux and macOS); Windows support pending a cross-platform writer lock. API may shift before v0.2 — see the changelog for the v0.1 feature set and known limitations.
Quickstart
# Install with pipx (recommended) or pip
pipx install agentwitness
# One-time setup: generates an Ed25519 keypair in your OS keychain,
# writes a default manifest, and adds hook entries to ~/.claude/settings.json
# A .bak of any existing settings.json is written first.
agentwitness install
# Use Claude Code normally. Each PreToolUse, PostToolUse,
# PostToolUseFailure, UserPromptSubmit, SessionStart, and SessionEnd
# fires a hook that records a signed event into <state>/sessions/.
# See what was recorded
agentwitness summary
agentwitness blame src/path/to/file
# Build an evidence bundle from the most recent session
agentwitness export -o ./evidence
# Confirm the bundle is internally consistent
agentwitness verify ./evidence
# Uninstall (conservative — keeps keychain and recorded sessions)
agentwitness uninstall
Any Python 3.10, 3.11, or 3.12 works. The install is idempotent: running it twice reuses the existing key and refreshes the hook entries without duplicating them.
Upgrade and recovery
Upgrade in place:
pipx upgrade agentwitness # or: pip install -U agentwitness
agentwitness install # re-runs idempotently; refreshes hook entries
If agentwitness install aborts partway through, the operation is safe
to retry. The .bak of any pre-existing ~/.claude/settings.json is
written before any modification, the keychain entry may already have
been created (and will be reused on the next run), and re-running
install is the supported recovery path. If you want a clean reset,
run agentwitness uninstall --purge-keys --purge-state first.
What this proves — and what it doesn't
A bundle that passes agentwitness verify proves that the captured
events were not modified after capture and that each one was signed by
the key declared in the manifest.
It does not prove:
- Completeness. A hostile local environment can disable hooks, delete files, or run tools outside the instrumented path. The bundle records what was captured, not what existed.
- External identity. The bundle proves a key signed it — not that the key belongs to a particular person, machine, or organisation. That binding is a separate concern (pin the public key in a registry, post it on a known site, use Sigstore-style OIDC, etc.).
- Semantic intent. "The agent edited
auth.py" is in the record. Whether that edit was malicious, careless, or in scope is a human judgment the bundle supports but does not make.
Full enumeration in THREAT_MODEL.md.
Architecture
Three pieces, all small:
- Recorder. A Claude Code hook entry point (
agentwitness hook) reads the hook payload, builds an event, signs it with the Ed25519 key from the OS keychain, and appends it toevents.jsonlplussignatures.jsonlinside a session directory. - Verifier. Reads a bundle, recomputes every event id, checks every signature, evaluates each tool action against the manifest's scopes, and re-checks the chain checkpoint. Errors are accumulated and reported with stable error codes.
- Spec.
spec/v0.1.mddefines the on-disk format both sides agree on — canonical serialisation (RFC 8785 JCS), the event schema, the signing envelope, the manifest, and the bundle layout. The spec is the source of truth; if the code and spec disagree, the spec wins.
Configuration
State lives under:
| OS | Path |
|---|---|
| macOS | ~/Library/Application Support/agentwitness/ |
| Linux | $XDG_DATA_HOME/agentwitness/ or ~/.local/share/agentwitness/ |
| Windows | %APPDATA%/agentwitness/ (not yet supported in v0.1) |
Override either path for testing:
AGENTWITNESS_STATE_DIR— overrides the state root.AGENTWITNESS_CLAUDE_SETTINGS— overrides the path to Claude Code'ssettings.jsonthat the install command patches.
The signing key never leaves the OS keychain except as a working copy
in the recorder process. To rotate keys, run agentwitness uninstall --purge-keys and then agentwitness install again. Old bundles still
verify against the old public key recorded in their manifest.
Uninstall
# Default — strips hook entries, keeps keychain and recorded sessions
agentwitness uninstall
# Restore ~/.claude/settings.json from the .bak written at install time
agentwitness uninstall --restore-from-backup
# Also delete the keychain entry. Old bundles still verify (their
# manifest contains the public key) but you can no longer sign new events
# under that label.
agentwitness uninstall --purge-keys
# Also delete the state directory. Removes the manifest and every
# recorded session.
agentwitness uninstall --purge-state
# Shorthand for --purge-keys + --purge-state
agentwitness uninstall --purge-all
Roadmap
Deferred to post-v0.1:
- Multi-hop delegation chains (subagent → tool token flow)
- ECDSA P-256 signing for interop with IETF AAT
- The optional
attestations/bundle directory (RFC 3161 timestamps, Sigstore certificates, transparency-log inclusion proofs, remote witnesses) — reserved in the spec, no concrete formats yet - DSSE envelope adoption
- TOML manifest authoring with a JSON canonical export
- Windows-compatible writer lock
- Multi-machine session merging
- Tarball bundle packaging
- Hosted dashboard / Cowork plugin (the Python API at
Recorder.bootstrapis the integration surface)
See the open questions in spec/v0.1.md §14.
Contributing
See CONTRIBUTING.md for the local setup, test
commands, commit conventions, and review flow.
Bug reports and design discussion belong in
GitHub issues.
Security issues: see SECURITY.md.
License
Apache License 2.0 for the code.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentwitness-0.1.0.tar.gz.
File metadata
- Download URL: agentwitness-0.1.0.tar.gz
- Upload date:
- Size: 111.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a4ef804e50b7219067d143b90a6bd6dcce607dfb5cddfa01f85837052dd46ac
|
|
| MD5 |
2057505f1330439523d909a67a6ca54f
|
|
| BLAKE2b-256 |
41e08c5cf1b99dd586538c8ef1e1c206ab0d8bc054dec7ee4eabcdecfa81dc4f
|
File details
Details for the file agentwitness-0.1.0-py3-none-any.whl.
File metadata
- Download URL: agentwitness-0.1.0-py3-none-any.whl
- Upload date:
- Size: 48.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
20783841a684e491fd4d1cabd86007c4a4a6bbc416387fd9084035ad2eb77720
|
|
| MD5 |
e0f62abde9745b184d3cf4d63698cf09
|
|
| BLAKE2b-256 |
8fbb9f71a0f3692ee97437fc69c8ed1109456748c02f8024606b251763a49146
|