CLI — heso
Two command-line tools. The heso CLI ships with the Python package and handles scaffolding and local verify. The standalone heso-verify-cliis a Rust binary that verifies evidence bundles offline, with no HESO install on the verifier’s machine.
Use the heso CLI to set a project up and check receipts during development. Use heso-verify-cli when someone outside your stack needs to confirm a receipt bundle is genuine. Both run the same offline verify path as the SDK, so verdicts match everywhere.
Common tasks
- Scaffold a project and mint your identity — heso init
- See it work end to end — heso demo
- Verify a receipt in CI — heso verify
- Verify a bundle on a machine with no HESO install — heso-verify-cli
A receipt proves you authorized an action under your policy. It does not prove the action succeeded downstream.
The heso CLI
Installed with pip install heso (Python 3.10+). It bundles the Rust core as the in-process heso._core wheel, so scaffolding, minting, and verify all run in your process with no subprocess. For the full Python surface — heso.init(), the decorators, and the proxy — see the Python SDK reference.
heso init
heso initcommand
Scaffold a HESO project: write heso.toml and the bootstrap module, gitignore the local data directory, and mint the operator identity in-process.
heso init [dir] [--require-passphrase]Parameters
- dirpath
- The directory to scaffold. Defaults to the current working directory. Created if it does not exist.
- --require-passphraseflag
- Strict custody: do not auto-generate a dev passphrase. The mint then fails unless
HESO_KEY_PASSPHRASEis set. Implied byHESO_ENV=productionand theHESO_REQUIRE_PASSPHRASEenv var.
Example
# scaffold the current directory
heso init
# or scaffold a named project directory
heso init my-agentWhat it writes:
heso.toml— a starter policy that allows model and tool calls and gates large payments and deletes to a human. Edit it to fit your controls; see writing policy.heso_bootstrap.py— a one-line module that callsheso.init(). See the bootstrap module below.- A
.gitignoreentry for the local data directory, which holds the minted key, the audit log, and the outbox queue. None of it is ever committed. - A dev key passphrase at
heso-local-data/DEV-ONLY.passphrase(mode0600), unless one exists or strict mode is on — see the dev key passphrase below.
A scaffolded project:
my-agent/
heso_bootstrap.py # import heso; heso.init()
heso.toml # starter policy, written by heso init
.gitignore # ignores the local data dir (minted key, audit log, outbox)heso init is safe to re-run. An existing key, heso.toml, and dev passphrase file are left as-is, so you will not overwrite a minted identity or a policy you have edited.
heso demo
heso democommand
Init the project if needed, mint one allowed and one redacted sample receipt through the real engine, and verify both offline.
heso demo [dir]Parameters
- dirpath
- The project directory. Defaults to the current working directory. If it is not yet scaffolded,
heso demorunsheso initfirst.
Example
# init if needed, then mint one allowed + one redacted receipt and verify both
heso demoThe two receipts are appended to heso-local-data/receipts.jsonl and verified in place, each reported with its PascalCase verdict and trust level:
minting your first receipts through the engine:
allow 7f3c91ab… -> Valid (L0)
redacted 2a8e04dd… -> Valid (L0)
receipts written to /path/to/your-agent/heso-local-data/receipts.jsonl
verify either yourself, offline:
heso verify 7f3c91ab…heso verify
heso verifycommand
Verify a single stored receipt or receipt file offline and print the verdict and trust level. Exit 0 only on Valid, 1 otherwise.
heso verify <path|hash>Parameters
- path | hashstring
- A path to a receipt
.jsonfile, or anaction_hash(full or a unique prefix) looked up inheso-local-data/receipts.jsonl. A prefix that matches more than one stored receipt is an error.
Example
# by action_hash (full or a unique prefix) from the local store…
heso verify 7f3c91ab
# …or a receipt JSON file straight off disk
heso verify ./receipt.json action 7f3c91ab…
Valid (L0)
(verified offline — re-ran BLAKE3 + Ed25519 locally, zero network)The verdict is the engine’s own PascalCase result — Valid, HashMismatch, WrongAlgorithm, and so on — followed by the trust level (L0 operator-signed, L1 human co-signed) for a valid receipt. The command exits 0 only on a Valid verdict and 1 on anything else, so it drops straight into a CI gate.
heso show
heso showcommand
Pretty-print a stored receipt's full signed JSON, looked up by action_hash (or a path to a receipt file).
heso show <hash>Parameters
- hashstring
- The receipt’s
action_hash(full or a unique prefix), or a path to a receipt JSON file. Resolved the same way asheso verify.
Example
heso show 7f3c91abIt prints the receipt indented and key-sorted — the same signed envelope documented field by field in the receipt schema.
The bootstrap module
heso init writes heso_bootstrap.py. It is one call: heso.init() resolves and installs your config, which every decorator and the proxy read from.
import heso
heso.init()Import it once at process start, at the top of your entrypoint, so the config is in place before the first gated call:
# import the bootstrap once, at the very top of your entrypoint
import heso_bootstrap # noqa: F401
from my_agent import run
run()The dev key passphrase
The operator key is encrypted at rest, and every key loader reads its passphrase from HESO_KEY_PASSPHRASE. To keep a fresh machine from hard-failing at heso init, when that variable is unset the CLI auto-generates a dev passphrase into heso-local-data/DEV-ONLY.passphrase and heso.init() loads it back, so the in-process lifecycle works with zero setup.
The dev passphrase file sits next to the key it unlocks, so it adds no real protection. An explicit HESO_KEY_PASSPHRASE always wins and the dev file is never consulted. For production, set a real HESO_KEY_PASSPHRASE from your secrets manager and delete the dev file. Running under HESO_ENV=production hard-blocks the dev file; heso init --require-passphrase opts into that strict posture in any environment.
# production: set a real passphrase and refuse the dev file
export HESO_KEY_PASSPHRASE="…from your secrets manager…"
export HESO_ENV=production # hard-blocks the DEV-ONLY.passphrase fallback
# or opt into strict custody in any environment
heso init --require-passphraseheso-verify-cli
A standalone Rust binary that verifies an evidence bundle offline with no HESO install on the machine running it. It reads a chained receipts.jsonland the pinned operator public key, runs the same verify path as the SDK, and reports a verdict with a Unix exit code. It is the same verifier an offline-verifiable bundle’s VERIFY.sh invokes — see offline verification.
heso-verify-clicommand
Verify a receipts bundle against a pinned operator public key. Add --json for a compact machine-readable result.
heso-verify-cli [--json] <receipts.jsonl> <public_key_file>Parameters
- --jsonflag
- Emit a compact JSON result instead of the human-readable line.
- receipts.jsonlpath
- The chained receipts file to verify.
- public_key_filepath
- The pinned operator public key the bundle is checked against.
Example
# verify a receipt bundle offline, no heso install needed
heso-verify-cli receipts.jsonl operator.pub
# machine-readable verdict
heso-verify-cli --json receipts.jsonl operator.pubExit codes:
| Code | Meaning |
|---|---|
0 | VALID |
1 | INVALID |
2 | WRONG ALG/HASH |
64 | USAGE |
With --json it emits a compact JSON result you can parse in a pipeline:
{"status":"VALID","exit":0,"count":2}