Skip to content
Development
Skill

/signed-audit-trails-recipe

Step-by-step cookbook for setting up cryptographically signed audit trails on Claude Code tool calls. Use when explaining, evaluating, or demonstrating the pattern before committing to the protect-mcp runtime hooks. Covers Cedar policy, Ed25519 receipts, offline verification,

From plugin
agents
42k185 skills137 agents93 commands

Claude Code

$ npx -y skills add wshobson/agents --skill signed-audit-trails-recipe --agent claude-code

SKILL.md

signed-audit-trails-recipe.SKILL.md
name: signed-audit-trails-recipe
description: Step-by-step cookbook for setting up cryptographically signed audit trails on Claude Code tool calls. Use when explaining, evaluating, or demonstrating the pattern before committing to the protect-mcp runtime hooks. Covers Cedar policy, Ed25519 receipts, offline verification, tamper detection, CI/CD integration, and SLSA composition.

Signed Audit Trails for Claude Code Tool Calls

Cookbook-style walkthrough for cryptographically signed receipts on every Claude Code tool call. This is the teaching skill. For the runtime implementation, install the [`protect-mcp`](../../../protect-mcp/) plugin.

What this gives you

Every tool call (`Bash`, `Edit`, `Write`, `WebFetch`) is:

1. **Evaluated against a Cedar policy** before execution. If the policy denies the call, the tool does not run. 2. **Signed as an Ed25519 receipt** after execution. Receipts are JCS-canonical and verifiable offline by anyone with the public key.

An auditor, regulator, or counterparty can verify every receipt later (Step 5). No network call, no vendor lookup, no trust in the operator.

When to use the pattern

  • **Regulated environments** (finance, healthcare, critical infrastructure)

where you need tamper-evident evidence of agent behavior

  • **CI/CD pipelines** where you want to prove that a policy gate held for

every automated build step

  • **Multi-party collaboration** where a counterparty wants to verify your

agent's behavior without trusting your operator

  • **Compliance contexts** (EU AI Act Article 12, SLSA provenance for

agent-built software) where standard logging is not sufficient

Step 1: Install the hook configuration

Install the `protect-mcp` plugin with `/plugin install protect-mcp`. Its hooks run `evaluate.sh` before each tool call and `sign.sh` after it. Both scripts read the hook event from stdin, because Claude Code sets no `TOOL_NAME` or `TOOL_INPUT` variables. See [`references/hook-wiring.md`](references/hook-wiring.md) for the hook configuration and what each script passes to protect-mcp.

protect-mcp 0.7.4 does not create the signing key, and without a key the receipts are unsigned. Create `./protect-mcp.key` once. The command never replaces an existing key:

if [ ! -e ./protect-mcp.key ]; then
  d=$(mktemp -d) && npx protect-mcp@0.32.4 init --dir "$d" && mv "$d/keys/gateway.json" ./protect-mcp.key
fi
chmod 600 ./protect-mcp.key

Give auditors the `publicKey` value from that file. Do not commit the file, because it also holds the private key.

Add the private key and receipt directory to `.gitignore`:

echo "/protect-mcp.key" >> .gitignore
echo "/receipts/" >> .gitignore

Step 2: Write a Cedar policy

Create `./protect.cedar` from the example in [`references/cedar-policy.md`](references/cedar-policy.md). It allows read-only tools and a short list of Bash commands, denies shell chaining and destructive commands, and limits writes to the project with `..` segments denied.

Step 3: Use Claude Code normally

Start Claude Code. Every tool call goes through both hooks:

You: Please read the README and summarize it.

Claude: I will read README.md.
  [PreToolUse: Read ./README.md -> allow]
  [Tool: Read executes]
  [PostToolUse: receipt rcpt-a8f3c9d2 signed to ./receipts/]

... summary of README ...

A session of 20 tool calls appends 20 receipts to `./receipts/receipts.jsonl`.

Step 4: Inspect a receipt

protect-mcp 0.7.4 appends each receipt as one line of `./receipts/receipts.jsonl`. Print the newest one:

tail -n 1 ./receipts/receipts.jsonl | python3 -m json.tool

The receipt is a signed v2 envelope that names the tool, and it holds no public key. See [`references/receipt-format.md`](references/receipt-format.md) for a sample and the signed fields.

Step 5: Verify the receipts

Pass the `publicKey` value from `./protect-mcp.key` to the verifier:

PUB=$(node -p 'JSON.parse(require("fs").readFileSync("./protect-mcp.key")).publicKey')
npx @veritasacta/verify@0.9.2 --replay-chain ./receipts/receipts.jsonl --key "$PUB"

Exit codes:

| Code | Meaning | |------|---------| | `0` | Every receipt verified | | `1` | A receipt failed verification (tampered, wrong key, or malformed line) | | `2` | The receipts file could not be read |

Step 6: Demonstrate tamper detection

Change the newest receipt's `decision` from `allow` to `deny`:

python3 -c "
import json
path = './receipts/receipts.jsonl'
lines = open(path).read().splitlines()
r = json.loads(lines[-1])
r['payload']['decision'] = 'deny'
lines[-1] = json.dumps(r)
open(path, 'w').write('\n'.join(lines) + '\n')
"

npx @veritasacta/verify@0.9.2 --replay-chain ./receipts/receipts.jsonl --key "$PUB"

The verifier exits with code `1` and reports which line failed. The Ed25519 signature no longer matches the JCS-canonical bytes of the tampered payload.

Restore the field and verification passes again.

How the cryptography works

Two invariants make receipts verifiable offline across any conformant implementation:

1. **JCS canonicalization (RFC 8785)** before signing. Keys sorted by UTF-16 code units, whitespace minimized, strings not normalized. Two independent implementations produce byte-identical signing payloads for the same receipt content. 2. **Ed25519 signatures (RFC 8032)** over the canonical bytes. Deterministic, fixed-size, no nonce dependency.

protect-mcp 0.7.4 receipts carry no link to the previous receipt, so a deleted receipt goes undetected.

For the formal wire format see [draft-farley-acta-signed-receipts](https://datatracker.ietf.org/doc/draft-farley-acta-signed-receipts/).

Cross-implementation interop

The receipt format has four independent implementations today:

| Implementation | Language | Use case | |----------------|----------|----------| | [protect-mcp](https://www.npmjs.com/package/protect-mcp) | TypeScript | Claude Code, Cursor, MCP hosts | | [protect-mcp-

Read more
@wshobson
Ships withagents

Use one collection of plugins, agents, skills, and commands across Claude Code, OpenAI Codex CLI, Cursor, OpenCode, Antigravity CLI, GitHub Copilot, and Pi. A harness is the coding tool that loads and runs the components.

42k185 skills137 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
42.4k
Star history of wshobson/agents on GitHub, a chart by star-history.com

Other skills on agents.

screen-reader-testing

screen-reader-testing

Test web applications with screen readers including VoiceOver, NVDA, and JAWS. Use when validating screen reader compatibility,…

@wshobson@wshobsonInstall Skill
wcag-audit-patterns

wcag-audit-patterns

Conduct WCAG 2.2 accessibility audits with automated testing, manual verification, and remediation guidance. Use when auditing…

@wshobson@wshobsonInstall Skill
multi-reviewer-patterns

multi-reviewer-pattern…

Coordinate parallel code reviews across multiple quality dimensions with finding deduplication, severity calibration, and…

@wshobson@wshobsonInstall Skill
parallel-debugging

parallel-debugging

Debug complex issues using competing hypotheses with parallel investigation, evidence collection, and root cause arbitration. Use…

@wshobson@wshobsonInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills12d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react3d252k
@facebook@facebookInstall Skill

Questions about signed-audit-trails-recipe.

Which coding agents can use signed-audit-trails-recipe?
signed-audit-trails-recipe installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.