merkle
Merkle tree operations for batch integrity and inclusion proofs.
Hidden from --help. merkle is implemented, tested, and shipped -- proof generation, offline verification, and checkpoint status. Hidden from the top-level list as a UX choice, not because it's incomplete.
Treeship maintains a local Merkle tree over all artifacts. Checkpoints seal a signed root, and inclusion proofs let anyone verify that a specific artifact was part of the tree at a given point in time.
Why Merkle proofs
- Batch integrity. A single signed root covers all artifacts. Tampering with any artifact invalidates the root.
- Compact proofs. An inclusion proof is O(log N) hashes, not the full tree. A tree with 1 million artifacts produces a proof under 1KB.
- Tamper detection. If an artifact is modified or removed after checkpointing, the proof fails.
- Privacy-preserving audit. Share a proof for one artifact without revealing any other artifacts in the tree.
Commands
treeship checkpoint
Seal a signed Merkle root over all current artifacts. The checkpoint is stored locally and can be published to the Hub.
treeship checkpoint
treeship checkpoint --publish--publish pushes the sealed checkpoint to the attached hub in the same command; a failed push exits nonzero (the checkpoint itself is still on disk). A checkpoint is signed by the ship that seals it. The hub verifies and stores it and signs nothing of its own, so a published checkpoint is this ship's signed assertion about its log, not an outside witness to it.
On a schedule
Off by default: nothing leaves the machine without an explicit setting. To keep the hub's latest checkpoint fresh, set an interval in .treeship/config.yaml and run the daemon:
checkpoint:
every: 6h # 30d, 12h, 45m; anything under 5m is treated as 5mThe daemon then seals a checkpoint and publishes it to the attached hub whenever the newest local checkpoint is older than the interval, and writes one line to .treeship/daemon.log per publish or failure. treeship doctor reports the cadence only as it actually runs: as set when the daemon is running and a hub is attached, and as a warning when either is missing, because then nothing publishes. The hub's GET /v1/merkle/checkpoint/latest returns age_seconds so a monitor can alert when the latest checkpoint is older than it should be.
→ sealing checkpoint over 47 artifacts...
[pass] checkpoint created
root: sha256:e3b0c44298fc1c14...
height: 6
artifacts: 47
signed at: 2026-03-31T14:25:00Z
→ treeship merkle statustreeship merkle proof <id>
Generate an inclusion proof for a specific artifact. Exports a .proof.json file.
treeship merkle proof art_f8e2a1b3c4d5e6f7→ generating inclusion proof...
[pass] proof generated
artifact: art_f8e2a1b3c4d5e6f7
root: sha256:e3b0c44298fc1c14...
path depth: 6
file: art_f8e2a1b3c4d5e6f7.proof.json
→ treeship merkle verify art_f8e2a1b3c4d5e6f7.proof.jsonThe proof file contains:
{
"artifact_id": "art_f8e2a1b3c4d5e6f7",
"root": "sha256:e3b0c44298fc1c14...",
"leaf_hash": "sha256:a1b2c3d4...",
"path": [
{ "hash": "sha256:...", "position": "left" },
{ "hash": "sha256:...", "position": "right" },
{ "hash": "sha256:...", "position": "left" }
],
"checkpoint_signature": "base64url(...)",
"signed_at": "2026-03-31T14:25:00Z"
}treeship merkle verify <proof.json>
Verify an inclusion proof offline. Walks the hash path step by step and checks the root signature.
treeship merkle verify art_f8e2a1b3c4d5e6f7.proof.json→ verifying inclusion proof...
step 1: sha256:a1b2... + sha256:c3d4... = sha256:e5f6...
step 2: sha256:e5f6... + sha256:a7b8... = sha256:c9d0...
step 3: sha256:1234... + sha256:c9d0... = sha256:e3b0c442...
[pass] root matches checkpoint
[pass] checkpoint signature valid
→ artifact art_f8e2a1b3c4d5e6f7 is in the treetreeship merkle status
Show tree state, checkpoints, and how many artifacts have been added since the last checkpoint.
treeship merkle statusMerkle tree:
total artifacts: 47
tree height: 6
checkpoints: 3
last checkpoint: 2026-03-31T14:25:00Z (root: sha256:e3b0c442...)
uncheckpointed: 0treeship merkle publish
Push the latest checkpoint and all associated proofs to the Hub.
treeship merkle publish→ publishing checkpoint to hub...
[pass] checkpoint pushed
[pass] 47 proofs pushed
hub url: https://treeship.dev/merkle/chk_a1b2c3d4
→ treeship hub statusWeb verification
Visit treeship.dev/merkle to verify a proof in the browser. Paste the contents of a .proof.json file and the WASM verifier checks the hash path and root signature client-side. No data leaves your browser.
Checkpoints are additive. Each new checkpoint covers all artifacts, including those covered by previous checkpoints. You can checkpoint as often as you like.