The Etchd CLI

The etchd command stamps files, text and digests, upgrades the proofs and checks them against Ethereum Classic, and a shell script or an agent calls it the same way a person does. It hashes on your machine and never prompts. Piped, it prints JSON. Every run ends with one of seven fixed exit codes.

Install

The CLI lives in packages/cli and needs Node 22.18 or later. Each cli-v* release on GitHub carries etchd-cli.tgz, the CLI bundled into one file with no dependencies, and its SHA-256 in etchd-cli.tgz.sha256. It is not on npm. The link answers 404 until we push the first cli-v* tag.

Install
npm i -g https://github.com/classix-dev/etchd/releases/latest/download/etchd-cli.tgz

npx runs it once without installing. It keeps the first copy it fetched for that URL, and moving to a newer release takes npm i -g.

Run once
npx https://github.com/classix-dev/etchd/releases/latest/download/etchd-cli.tgz stamp report.pdf
Build it from a clone
git clone https://github.com/classix-dev/etchd
cd etchd
pnpm install
pnpm cli:pack
npm i -g ./packages/cli/dist/etchd-cli.tgz

Without a calendar set, the CLI stamps on ours at https://a.etc.calendar.etchd.app, and ETCHD_CALENDAR picks another one, such as the local dev Worker from pnpm dev.

Use the local dev calendar
export ETCHD_CALENDAR=http://127.0.0.1:8787

Stamp, Upgrade, Verify

Diagram. Three terminal commands in a row. etchd stamp writes a pending report.pdf.ots, etchd upgrade adds the Ethereum Classic path, and etchd verify exits 0 once the anchor block has a confirmation. etchd stamp writes a pending proof next to the file. etchd upgrade adds the path to the ETC transaction, and etchd verify exits 0 once two RPCs agree on the anchor block. Pass --min-confirmations to ask for more blocks on top.

etchd stamp hashes each input locally, gives each digest a random 16-byte nonce and folds them into one Merkle tree, and only the root goes to the calendar, in a single request, while each input still gets its own .ots file. A second run skips inputs that already have a proof. --force stamps them again. Use --text to stamp a string, or --digest with --alg for a hash you computed yourself, BLAKE3 included.

Stamp
etchd stamp report.pdf                  # writes report.pdf.ots
etchd stamp dist/* --out proofs         # one submission for every file
etchd stamp --text "release 1.2.0"      # writes <sha256>.ots

A fresh proof is pending. Once the tick's anchor transaction is mined, usually a minute or two after the stamp, etchd upgrade asks the calendar named in the proof for the rest of the path. Until then it exits 2 or, with --wait, keeps polling for up to --timeout seconds. A run a few hours later usually merges the Bitcoin branch too.

Upgrade
etchd upgrade report.pdf.ots --wait --timeout 600

etchd verify replays the proof on the original and looks up the anchor transaction on ETC, with the checks set out in Verifying. It exits 0 from one confirmation and prints the count, and --min-confirmations asks for more. Two or more RPCs have to return the same block. To use your own node, pass --etc-rpc and add --min-sources 1 to accept that one source. The verifier also matches the sender against the calendar's signer list. Only --require-known-signer makes that match change the result.

Verify
etchd verify report.pdf.ots
etchd verify report.pdf.ots --etc-rpc http://127.0.0.1:8545 --min-sources 1
etchd verify report.pdf.ots --min-confirmations 400
etchd verify report.pdf.ots --signers https://etchd.app/v1/signers --require-known-signer

Inspecting Proofs and the Calendar

etchd info lists what a .ots file holds and works offline. etchd status shows calendar health. To see what a tick committed, down to one chain's leaf and its Merkle path, use etchd tick latest and etchd beacon <n> [chain]. etchd chains lists the chains the beacon follows, and with --local it reads the registry built into the CLI without the network. etchd mirror copies the daily exports and checks each one before it stores it, as set up on Mirrors.

Output for Scripts

In a terminal the CLI prints text for people, and when its output goes to a pipe it prints one JSON object, with --json asking for JSON anywhere. --ndjson prints one object per item followed by a result line. --human forces text, and -q prints nothing. Every JSON result carries ok, command and exitCode, and a failure adds error.code and error.message. etchd schema stamp prints the JSON Schema for a command's output.

Exit Codes

CodeMeaningWhat to do
0Done, or the proof verified with at least --min-confirmations confirmations, 1 by defaultNothing
1Bad arguments, or the original file is missingFix the command. etchd <command> --help lists every option
2Pending, or anchored with fewer confirmations than --min-confirmations asks forRun upgrade or verify again later
3The proof or the original does not match, or there is no attestation Etchd can checkStop and report it, a retry changes nothing
4A calendar, an RPC or a mirror target could not be reachedRetry later or pass other URLs
5An internal error in the CLIReport the error message
6The anchor transaction is no longer at the block and index the proof names, after a reorg or in a wrong proofRun etchd upgrade on the proof, then verify again

With --require-known-signer, an anchor sent by a key outside the signer list also exits 3, and one whose list could not be fetched exits 4.

Environment Variables

ETCHD_CALENDAR holds the calendar URLs used when -c is not given. ETCHD_ETC_RPC holds the ETC RPC URLs used when --etc-rpc is not given, and without either the CLI falls back to three public RPCs. Both variables take a comma-separated list. etchd mirror reads a pinning service token from the variable that --token-env names, which keeps the token off the command line.

The Agent Skill

skills/etchd/SKILL.md teaches an agent the same commands, how to read each status and which exit codes to retry, and to install it you copy the skills/etchd directory into your agent's skills folder, which for Claude Code is ~/.claude/skills/etchd.