Command line
zikaron offers the same ledger operations as the window, one subcommand per action. It is built for scripts: the output is a single JSON value, and the verdict is in the exit code. The full output shapes, exit codes, refusal reasons and flags are in CLI-SCHEMA.md in the source.
Where it is
- Installed from the dmg
/Applications/ZIKARON.app/Contents/MacOS/zikaron- Installed from the pkg
/usr/local/bin/zikaron- Built from source
target/release/zikaron
Three conventions
- Standard output is one canonical JSON value
- Each call prints one value, ending at the value’s last character. The byte format follows law §3.4: compact, members sorted by bytes.
- Misuse leaves standard output empty
- For wrong arguments or an unreadable path, the exit code is 2, standard output has zero bytes, and the first line of standard error reads
<reason> <subject>, as inE_UNREADABLE /nowhere/at/all. Whether standard output holds any bytes tells a caller an answer from a misuse. - Status words pass through unchanged
GREEN,PARTIAL,FAIL,COMPLETE,GAPSand the like are written by the cores and passed on by the command line as they are.
Files are written one way: --out first writes a whole temporary file alongside, syncs it to disk, then renames it into place; when a file of that name already exists, the write stops and the existing file keeps every byte.
Exit codes
| Code | Meaning | Example |
|---|---|---|
| 0 | Answered, affirmative | GREEN, COMPLETE |
| 1 | Answered, negative | The entry was refused, or the verdict is FAIL, BROKEN_CHAIN or NO_LABEL |
| 2 | Misuse | Wrong arguments or an unreadable path; standard output is empty |
| 3 | Answered, in between | PARTIAL, GAPS, UNAVAILABLE |
| 4 | Answer absent | Node unreachable, nodes disagreeing, scan refused |
The weight of this table is that 3 and 4 each have a code of their own. Fold “not yet on chain” into 0, and a buyer takes an unanchored grant as cleared; fold it into 1, and a passing “not yet known” reads as “forged”. Fold “node unreachable” into 1, and a network fault reads as “this chain is fake”. A failed scan is an absent answer, and the caller retries or changes nodes.
Twenty-one subcommands
| Subcommand | What it does |
|---|---|
keygen | Generate a key and print its address and private key |
init | Write the ledger’s creation entry into an empty ledger |
history | Append an anchored record |
grant | Sign a grant and write it to the ledger |
revoke | Sign a revocation and write it to the ledger (ruling file digest optional) |
adopt | Write an adoption entry |
attest | Produce a co-signature with an outside key |
succeed | Write a key change or handover entry |
annotate | Write a note |
retract | Write a deletion entry (the target must be a record in this ledger that is still undeleted) |
anchor | Anchor a hash on chain, through the registry contract or as a bare self-transfer |
scan | Scan for anchors using the chain settings |
audit | Audit a ledger against scan results and print a report and verdict |
check-grant | Run the six checks on a grant |
chain-check | Check a sublicense chain hop by hop (--hop <grant file>[=<audit input file>], repeatable) |
depth | Depth readings for a record |
fpm-sign | Sign a fingerprint manifest |
ack-sign | Sign an acknowledgement |
badge | Encode or decode a credential (exactly one of --encode and --decode) |
kit-export | Export a record kit, written once it passes its self-check |
show | Show an entry’s author, ID, type, previous entry, sequence and content |
Any other first word counts as misuse, with exit code 2.
Flags
All fifty-three flags are long flags, and each takes a value; every subcommand has its own table of flags, and a flag outside it counts as misuse. Members the law requires in an entry’s body may all be left off the command line; the core then refuses the entry under the law, and the command line checks the few items it needs for its own work. That way each rule of judgment exists once, in the core.
Example
Generate a key, create a ledger, record a file, anchor it, audit:
zikaron keygen
# {"address":"0x…","ok":true,"privkey":"0x…"}
zikaron init --ledger ./ledger --key <private key> --statement "Records of my work"
zikaron history --ledger ./ledger --key <private key> \
--content 0x$(shasum -a 256 manuscript.pdf | cut -d' ' -f1) \
--mark bytes-sha256/1 \
--toolchain 0xb7f3c4a226684d6da684b0ac82d36ed5bcba7bb61d09c955bff9437f84a52a4d
# {"entryId":"0x…","ledger":"…","ok":true,"seq":1,"written":true}
zikaron anchor --key <private key> --endpoint <chain-id>=<node> \
--form registry --registry <contract address> --hash <entryId>
zikaron scan --endpoint <chain-id>=<node one> --endpoint <chain-id>=<node two> \
--basis basis.json > fragment.json
zikaron audit --ledger ./ledger --fragment fragment.json
echo $?The value of --toolchain is the SHA-256 of the literal bytes-sha256/1, meaning “the content fingerprint is the SHA-256 of a run of bytes”. The command line’s chain layer accepts node addresses of the form http://host:port alone, so point it at a local node or a local proxy; anchor takes exactly one --endpoint. basis.json states the scan range: which chains, which registry contract, which senders, and the start and end blocks; the format is in law §9.4.
Time is injected by the caller
Deadlines and periods are judged by chain time and the moment injected with --now; when --now is left off, chain time alone applies. Every moment comes from the caller, so the same input always reaches the same verdict.
Reading the app’s own ledger
A ledger in ZIKARON Desk’s data folder is encrypted and the passcode lives in the app, so the command line refuses to read one, with exit code 2 and this line on standard error (“locked: this is ZIKARON Desk’s sealed local data; the command line does not read it”):
E_UNREADABLE 已锁定:这是 ZIKARON Desk 封存的本机数据,命令行不读To hand a ledger to the command line, export a “Ledger mirror” in the app first: each file in the mirror’s entries/ is one entry’s bytes, named with exactly its 64 hexadecimal digits. A single entry can be read by file with show --path; to use them as a --ledger folder, copy the files into an empty folder and add .entry to each file name.