Content
# ShipReceipt
**A receipt for every “done.”** ShipReceipt turns a delivery claim into fresh, machine-checkable local evidence: the claim, safe deterministic probes, captured output, exit codes, relevant file hashes, and a portable report.
Tests tell you what ran. ShipReceipt tells a reviewer which exact completion claim those tests support—and when later changes mean that proof is no longer fresh.
[](https://github.com/WXBR/shipreceipt/actions/workflows/ci.yml)
[](https://shipreceipt.vercel.app)
[](https://youtu.be/3KCSkylMyxw)

[](https://shipreceipt.vercel.app)
## Why it exists
Coding agents are good at confident summaries. Reviewers need a tighter contract:
```text
“The release marker is valid.”
↓
claim + files + executable argv + captured evidence + file hashes
↓
verified / contradicted / unverified / stale
```
If a relevant file changes after a probe runs, ShipReceipt marks the claim **stale**. It does not leave yesterday’s green check pretending to prove today’s tree.
## Quickstart
Requires Node 20+ and npm.
```sh
npm install
npm run build
# Create a receipt in the current repository
node packages/cli/dist/index.js init
# Record a narrow claim. Everything after -- is executable plus argv, never a shell string.
node packages/cli/dist/index.js claim "The unit suite passes." \
--file packages/core/src/core.ts -- node --test
# Direct CLI execution needs an explicit approval flag; previously allowlisted contracts can re-run without it.
node packages/cli/dist/index.js run clm_yourclaim --approve
node packages/cli/dist/index.js status
node packages/cli/dist/index.js export --format html --out shipreceipt-report.html
```
### See the full state machine in 10 seconds
```sh
npm run smoke
```
The smoke fixture creates a passing claim, a failing claim, then modifies the passing claim’s tracked file. Its final status contains `stale` and `contradicted`; it also exports a static HTML report.
For the browser demo:
```sh
npm run build --workspace=@shipreceipt/web
npx serve packages/web/dist -l 4173
```
The dashboard’s buttons run an in-browser fixture only. To use the same UI against a real local receipt, start its local-only reader after building:
```sh
npm run live --workspace=@shipreceipt/web -- --root /path/to/repository
```
It serves `packages/web/dist` and a local `/receipt.json` status endpoint; it never executes probes. The hosted static demo never executes commands or reads a visitor’s filesystem.
## CLI
| Command | Purpose |
| --- | --- |
| `init [--root path]` | Create `.shipreceipt/receipt.json`. |
| `claim "text" --file path -- executable argv` | Add a claim and a deterministic probe. |
| `allow <id>` | Allowlist a claim’s full probe contract for later local re-runs. |
| `run <id> --approve` | Execute its probes with limits and capture evidence. |
| `status` | Print the current state for every claim. |
| `export --format json|html --out file` | Write a portable receipt. |
| `demo [--root path]` | Build the bundled contradiction/staleness scenario. |
`--root` is supported on every command. A probe’s command is stored as an executable and argv array. There is no shell interpolation or `shell: true` path. `run` needs an explicit `--approve`, unless the full probe contract (argv, cwd, timeout, expected exit, files, and allowed environment names) was previously recorded with `allow`.
## Receipt states
| State | Meaning |
| --- | --- |
| `unverified` | No complete probe evidence exists. |
| `verified` | Every probe exited with its expected code and current file hashes match evidence. |
| `contradicted` | A probe failed, timed out, or exited unexpectedly. |
| `stale` | Relevant file hashes no longer match those recorded at probe time. |
## Codex plugin and MCP
The repository includes a repo-local marketplace at `.agents/plugins/marketplace.json` and an installable plugin in `plugins/shipreceipt`.
Build first, then add the repository marketplace and install the plugin:
```sh
codex plugin marketplace add /path/to/shipreceipt
codex plugin add shipreceipt@shipreceipt-marketplace
```
The plugin carries a self-contained bundled stdio MCP server and exposes five deterministic tools:
- `shipreceipt_init`
- `shipreceipt_claim`
- `shipreceipt_run` (runs only contracts already allowlisted through the local CLI)
- `shipreceipt_status`
- `shipreceipt_report`
The skill at `plugins/shipreceipt/skills/shipreceipt/SKILL.md` instructs Codex to use narrow claims, explain intended execution, and cite a receipt ID/status rather than claim success from prose. MCP callers cannot self-approve execution: after a claim is recorded, the user must inspect and allowlist its full probe contract through the local `shipreceipt allow <id>` CLI command before `shipreceipt_run` can execute it. `npm run build` refreshes the plugin-local MCP bundle before installation.

You can smoke the server directly using newline-delimited JSON-RPC:
```sh
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize"}' | node packages/mcp/dist/index.js
```
## Architecture
```text
Codex skill / CLI / MCP
│
▼
@shipreceipt/core
schemas · safe runner · hash snapshots · receipt store
│
▼
.shipreceipt/receipt.json ──► status / HTML report / local dashboard
```
The core library owns schemas, hashing, persistence, status calculation, redaction, and command execution. The CLI and MCP server are thin adapters. The web dashboard is static and uses a bundled demo state; it can be hosted without credentials. See [architecture notes](docs/architecture.md) and [decisions](docs/decisions.md).
## Safety and threat model
ShipReceipt is local-first, but running a probe is still code execution. The runner:
- requires explicit approval in the CLI and MCP interface;
- stores commands as executable plus argv and sets `shell: false`;
- restricts probe working directories to the receipt root;
- uses a default 30-second timeout capped at two minutes;
- caps each stdout/stderr stream at 64 KiB;
- forwards no environment variables unless named in the probe allowlist, except the minimal inherited `PATH` needed to locate an executable;
- applies best-effort redaction to common token/key, authorization, cookie, URL-credential, cloud-key, and private-key forms before storing output.
The receipt’s hashes and chain are **tamper-evident only within a documented threat model**. Before status, export, or execution, ShipReceipt verifies event linkage, every current claim/evidence binding, evidence hashes, and probe contracts; an integrity failure fails closed rather than reporting a green claim. Someone who can rewrite the receipt and all local files can still rewrite its history. Hashes prove consistency of what ShipReceipt recorded; they do not establish identity, remote provenance, or a secure audit trail. Do not put secrets in commands, claims, or files. See [security notes](docs/security.md).
## Deployment
`vercel.json` builds and serves `packages/web/dist` as a static site. It has no server code and no command-execution endpoint. For another static host, run `npm run build --workspace=@shipreceipt/web` and publish that same directory.
## Development and verification
```sh
npm install
npm run lint
npm run typecheck
npm test
npm run build
npm run smoke
npm run plugin:check
```
## Build Week / Codex disclosure
This is an OpenAI Build Week 2026 submission. GPT-5.6 in a persistent Codex session accelerated implementation: workspace setup, TypeScript core/CLI/MCP/dashboard code, tests, fixture, documentation drafts, and verification iteration. Human product decisions defined the problem, local-first evidence model, safety boundaries, visual direction, project scope, and final review criteria. No OpenAI API key is required: GPT-5.6 runs in the authenticated Codex host, while ShipReceipt itself is deterministic local tooling. See the public [Codex build trace](docs/build-trace.md).
## License
MIT. See [LICENSE](LICENSE).
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
everything-claude-code
Complete Claude Code configuration collection - agents, skills, hooks,...
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
cc-switch
All-in-One Assistant for Claude Code, Codex & Gemini CLI across platforms.
servers
Model Context Protocol Servers
servers
Model Context Protocol Servers
Time
A Model Context Protocol server for time and timezone conversions.