Treeship
CLI reference

verify

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

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

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

Options

OptionDescription
--certificate <path-or-url>Cross-verify against an Agent Certificate (.agent package or URL)
--no-chainVerify 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.
--fullShow full chain timeline with box-drawn cards. Artifact-ID form only.
--format jsonGlobal flag. Machine-readable output for CI pipelines.
--quietGlobal flag. Exit code only, no output.

Exit codes

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

Examples

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.

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.

treeship verify ./researcher.agent

Loads the certificate from researcher.agent/certificate.json, verifies the embedded Ed25519 signature, and prints the certificate metadata.

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.

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.

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.

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 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 for the full semantics.

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.

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.

RowWhat it provesAvailable when
replay-package-localNo duplicate uses inside this packageAlways
replay-local-journalThe 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-checkpointAn embedded JournalCheckpoint's record_digest recomputes — record range wasn't tampered after sealingPackage carries one or more checkpoints
replay-hub-orgA signed Hub checkpoint validates global single-use across machinesPackage 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:

RowWhat it proves
approval-use-record-digestEvery embedded use record's record_digest recomputes from canonical form
approval-use-nonce-bindingEach use's nonce_digest equals sha256(grant.nonce) for a content-addressed grant in the package
approval-use-action-bindingEach 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-continuityEmbedded 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

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:

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 and Approval Authority.