Skip to content

End-to-End Walkthrough (TypeScript)

This walkthrough takes you through the complete receipt lifecycle: emit a receipt event from a TypeScript agent, list the stored chain, and verify its integrity from the CLI. By the end you will have seen the full loop that makes receipts meaningful — not just that a receipt was written, but that it can be independently verified later.

Prerequisites: the daemon is installed and running. If not, complete Daemon Setup first.

Fresh chain assumed: sequence numbers below (1, 2) are correct when the default chain has no prior receipts. If you have already emitted receipts, run agent-receipts list to find the current tail and substitute the actual sequence numbers.


Terminal window
npm install @agnt-rcpt/sdk-ts

Create emit.ts:

import { DaemonEmitter } from '@agnt-rcpt/sdk-ts';
async function main() {
const emitter = new DaemonEmitter();
try {
const err = await emitter.emit({
channel: 'walkthrough',
tool: { name: 'fs.write_file' },
decision: 'allowed',
});
if (err) throw err;
console.log('Receipt emitted.');
} finally {
emitter.close();
}
}
main().catch(console.error);

Run it:

Terminal window
npx tsx emit.ts

The daemon receives the event over its Unix socket, signs it with its Ed25519 key, chains it to any previous receipt in the same chain, and persists it to the SQLite store. The emitter itself never touches the key.

channel is the integration namespace for this emitter — it becomes the prefix of the action type stored in the receipt (walkthrough.fs.write_file here). Use a stable, descriptive identifier for your integration: mcp, claude-code, my-agent, and so on.

emit() returns null on success or an Error on failure — an EmitTransportError when the daemon is unreachable, a plain Error for caller bugs such as a missing tool name or invalid decision. close() is synchronous and releases the socket.


Terminal window
agent-receipts list

You should see one row: sequence 1, tool fs.write_file, chain default.

To inspect the full receipt:

Terminal window
agent-receipts show 1 --chain-id default

This prints a human-readable table of the receipt's fields. To see the full W3C Verifiable Credential JSON — including the proof block with the Ed25519 signature — pass --json:

Terminal window
agent-receipts show 1 --chain-id default --json

In the JSON output, credentialSubject.chain.previous_receipt_hash is null for the first receipt in a chain — it has no predecessor. The hash linkage becomes visible once there is a second receipt to point back at it.


Terminal window
agent-receipts verify

Example output (on a fresh chain):

Chain default: VALID (1 receipt)

The verifier re-derives the hash of each receipt, checks the signature against the daemon's public key, and confirms the previous_receipt_hash in each receipt matches the hash of its predecessor. A broken hash link or bad signature produces a non-zero exit and a description of the failure.

The receipt DB and public key are self-contained. Copy them anywhere and verify without a running daemon:

Terminal window
agent-receipts verify \
--db ~/.local/share/agent-receipts/receipts.db \
--public-key ~/.local/share/agent-receipts/signing.key.pub

Rerun emit.ts:

Terminal window
npx tsx emit.ts
agent-receipts verify

Example output (count is one higher than after the first emit):

Chain default: VALID (2 receipts)

Run agent-receipts show 2 --chain-id default (or substitute the sequence of your second receipt from agent-receipts list) — unlike receipt 1 (the chain head), this receipt has a Previous hash: field containing the hash of receipt 1. That linkage is what makes the chain tamper-evident: altering receipt 1 changes its hash, invalidates receipt 2's back-pointer, and verification catches it immediately.


StepWhat happened
EmitSDK sent an event to the daemon over a Unix socket; daemon signed and stored the receipt
ListCLI read the persisted chain from the SQLite store
VerifyCLI re-derived hashes, checked signatures, and confirmed chain linkage — all without the daemon being involved

The daemon is the only process that ever holds the signing key. The agent, the CLI, and any downstream auditor only ever see signed receipts and the public key.