---
title: verify
description: Verify a receipt by URL, file path, or local artifact ID. Optionally cross-verify against an Agent Certificate.
---

import { Callout } from 'fumadocs-ui/components/callout';
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';

`treeship verify` accepts three target shapes and one optional cross-check:

- a **URL** to a receipt JSON document served by the Hub
- a **file path** to a local `.treeship` or `.agent` package directory
- an **artifact ID** from local storage (the original v0.1 path; chain walk + signature checks)

Pair any of those with `--certificate` to also confirm the session stayed inside the envelope of an Agent Certificate.

## Usage

```bash
treeship verify <url-or-path-or-artifact-id> [OPTIONS]
```

## Options

| Option | Description |
|--------|-------------|
| `--certificate <path-or-url>` | Cross-verify against an Agent Certificate (`.agent` package or URL) |
| `--no-chain` | Verify only this artifact, do not walk the parent chain. Artifact-ID form only. |
| `--max-depth <N>` | Maximum chain depth to walk (default 20). Artifact-ID form only. |
| `--full` | Show full chain timeline with box-drawn cards. Artifact-ID form only. |
| `--format json` | Global flag. Machine-readable output for CI pipelines. |
| `--quiet` | Global flag. Exit code only, no output. |

## Exit codes

| Code | Meaning |
|------|---------|
| `0` | Verified |
| `1` | Verification failed (signature, Merkle, inclusion proof, determinism) |
| `2` | Cross-verification failed (cert mismatch, unauthorized tool call, expired cert) |
| `3` | Network or filesystem error (could not fetch URL or read file) |

## Examples

<Tabs items={['URL', 'File path', '.agent', 'Cross-verify', 'Artifact ID', 'JSON for CI']}>
<Tab value="URL">
```bash
treeship verify https://api.treeship.dev/v1/receipt/ssn_abc123
```

```
  ✓  Downloaded receipt
  ✓  Merkle root verified
  ✓  2/2 inclusion proofs passed
  ✓  Leaf count matches artifact count
  ✓  Timeline ordering verified
  ✓  Chain linkage intact

Verified. This receipt is authentic.

  Session:   ssn_abc123
  Ship:      ship_demo
  Agent:     researcher
  Duration:  4m 22s
  Actions:   28
```

The human-readable mirror at `treeship.dev/receipt/...` is also accepted; the CLI rewrites `/receipt/` to `/v1/receipt/` automatically.
</Tab>
<Tab value="File path">
```bash
treeship verify .treeship/sessions/ssn_abc123.treeship
```

Loads the on-disk package, runs the full bag of checks (determinism, Merkle root, inclusion proofs, leaf count, timeline ordering), and prints the same checkmark output as the URL form.
</Tab>
<Tab value=".agent">
```bash
treeship verify ./researcher.agent
```

Loads the certificate from `researcher.agent/certificate.json`, verifies the embedded Ed25519 signature, and prints the certificate metadata.
</Tab>
<Tab value="Cross-verify">
```bash
treeship verify https://api.treeship.dev/v1/receipt/ssn_abc123 \
  --certificate ./researcher.agent
```

Verifies the receipt, then runs cross-verification:

```
  ✓  Certificate verified
  ✓  Ship IDs match
  ✓  All 12 tool calls authorized by certificate

Complete trust loop verified.
```

Fails with exit code `2` if the receipt's `ship_id` does not match the certificate's `identity.ship_id`, the certificate is expired or not yet valid at the verify time, or any tool the session called is missing from the certificate's `capabilities.tools`.
</Tab>
<Tab value="Artifact ID">
```bash
treeship verify art_f7e6d5c4 --full
```

The original local-artifact path. Walks the parent chain, verifies every Ed25519 signature, checks approval nonce binding, and prints a box-drawn timeline.
</Tab>
<Tab value="JSON for CI">
```bash
treeship verify $RECEIPT_URL --format json --certificate $CERT_PATH \
  | jq -e '.cross_verify.ok == true'
```

The JSON object includes `outcome`, per-check status, and (when `--certificate` is used) a `cross_verify` block with `ship_id_status`, `certificate_status`, the three tool-call lists, and a roll-up `ok` boolean. Pipe it to `jq -e` for a clean pass/fail gate.
</Tab>
</Tabs>

## What the verifier checks

The exact set of checks depends on what's available at the target:

- **URL mode** runs every check that's derivable from the receipt JSON alone: Merkle root recomputation, inclusion proofs, leaf count, timeline ordering, chain linkage. Per-artifact Ed25519 signature checks need the original envelope bytes, which only the local-storage and `.treeship` package paths have.
- **`.treeship` package mode** runs everything URL mode runs plus determinism (the on-disk `receipt.json` round-trips byte-identical) and any signature checks the package preserves.
- **`.agent` package mode** verifies the certificate's Ed25519 signature against the public key embedded in the certificate. It does NOT chain to a trusted issuer; trust chaining is out of scope for v0.9.0.
- **Artifact-ID mode** is the original local-storage path: walks the parent chain, verifies every signature, enforces nonce binding on approvals, checks expiry. See [the chain-verification guide](/docs/concepts/artifacts) for full semantics.

The cross-verification path additionally verifies that the receipt's `session.ship_id` matches the certificate's `identity.ship_id`, the certificate was valid at verify time (`issued_at <= now <= valid_until`), and every tool the session called is present in the certificate's `capabilities.tools` list. See the [cross-verification concept](/docs/concepts/cross-verification) for the full semantics.

<Callout type="info">
Pre-v0.9.0 receipts (before `schema_version` and `session.ship_id` were added) verify cleanly under the URL and package paths but cannot complete cross-verification because the receipt has no `ship_id`. The CLI reports `Receipt has no ship_id (legacy receipt; cannot cross-verify)` and exits `2`.
</Callout>

## Approval Authority replay rows (v0.9.10)

When the package contains evidence of consumed `ApprovalUse` records, `verify` emits one row per replay level — each row pinned to a specific invariant. The strongest level the package's evidence supports wins; nothing silently downgrades.

| Row | What it proves | Available when |
|---|---|---|
| `replay-package-local` | No duplicate uses inside this package | Always |
| `replay-local-journal` | The workspace's local journal has not exceeded `max_uses` for the recorded `(grant_id, nonce_digest)` | Verifier has Treeship workspace (`treeship package verify` from a workspace) |
| `replay-included-checkpoint` | An embedded `JournalCheckpoint`'s `record_digest` recomputes — record range wasn't tampered after sealing | Package carries one or more checkpoints |
| `replay-hub-org` | A signed Hub checkpoint validates global single-use across machines | Package carries a `kind: hub-org` checkpoint that signature-verifies AND covers every embedded `use_id`. The Hub server itself is out of scope for v0.9.9-v0.9.10. |

Plus four bundle-level integrity rows added in v0.9.10:

| Row | What it proves |
|---|---|
| `approval-use-record-digest` | Every embedded use record's `record_digest` recomputes from canonical form |
| `approval-use-nonce-binding` | Each use's `nonce_digest` equals `sha256(grant.nonce)` for a content-addressed grant in the package |
| `approval-use-action-binding` | Each consuming action's `meta.approval_use_id` resolves to a use in the package, and the action's `approval_nonce` hashes to that use's `nonce_digest`. The action envelope is content-addressed against its filename — substituted/forged envelopes fail this row. |
| `approval-use-chain-continuity` | Embedded uses + checkpoints form a single connected linked list from one genesis: no forks, cycles, or disconnected subchains. |

### The honesty rule

A row reports `✓` only when the matching evidence is present and verified. `✗` only when the evidence is present and a check failed. `-` (or absent) when the evidence isn't in the package at all — never silent pass. Treeship will physically refuse to print "global single-use enforced" or "replay-hub-org passed" without a real Hub-signed checkpoint that verifies cleanly AND covers every use_id.

### Strict mode

```bash
treeship package verify --strict <pkg>
```

Promotes every approval-evidence warning to a hard failure. `replay-*`, `approval-use-record-digest`, `approval-use-nonce-binding`, `approval-use-action-binding`, and `approval-use-chain-continuity` all participate. Existing receipt-determinism / event-log warnings stay warnings.

Useful in CI:

```bash
treeship package verify --strict ./session.treeship
echo "exit code: $?"   # non-zero on any approval anomaly
```

For the full ladder and the v0.9.10 bypass paths the binding rows close, see [Replay levels](/guides/replay-levels) and [Approval Authority](/concepts/approval-authority).
