CLI reference
Auth and identity
A principal — a human — owns the account. Agents act as scoped, short-lived credentials derived under it. Most of Heddle needs none of this: only eight commands in the whole CLI touch the network, and the core capture/commit loop is not among them.
What actually needs a server
Eight commands do network I/O: heddle clone, heddle pull, heddle push, heddle land, heddle thread approve, heddle thread revoke-approval, heddle auth login and heddle auth create-service-token. Everything else — capture, commit, ready, start, status, diff, the whole agent lease surface, review, context, discuss — is local.
Signing needs no setup either. A device-local ed25519 identity is minted on first use and signs every authored state. You do not generate a keypair to get attributed provenance; you generate one for the separate operator-key paths, like signing a redaction.
Logging in is a device-code flow
heddle auth login prints a verification URL and a short user
code, then polls until a human approves out of band. It is not a browser
redirect. --open-browser only additionally auto-launches a
browser at that URL; the code and URL are printed either way, and the
shape of the flow does not change. With no flags it resolves the
configured default server.
Interactive, on a machine with a human at it
bash$ heddle auth login --server heddle.sh$ heddle whoami --output json auth login is one of the nine commands with no JSON contract. Script heddle whoami or heddle auth status around it
when you need a machine-readable answer.
Headless: CI, containers, fresh machines
There is no token flag on auth login. The only path that
works from nothing is installing a pre-minted .hcred credential file, and there are two ways to use one:
heddle auth login --credential <path.hcred>- Installs a verified credential file into the keystore without a browser. The server is taken from the file.
HEDDLE_CREDENTIAL=<path.hcred>- Authoritative: it bypasses the keystore entirely and is re-read on
every hosted call. This is the right answer where the credential is
a mounted secret and
auth loginnever runs. It appears in no--helpoutput — this page is where it is documented.
Both minting paths require an already-authenticated principal to derive from, so the bootstrap runs on a human's machine and the artefact travels:
Mint on an authenticated machine, install on the fresh one
bash# on the authenticated machine$ heddle auth create-service-token 'github-ci-main' --namespace heddle/platform --out ci.hcred# on the CI machine — either of these$ heddle auth login --credential ./ci.hcred$ HEDDLE_CREDENTIAL=./ci.hcred heddle pushDerived agent credentials
heddle auth derive-agent attenuates the stored parent
credential into a scoped, short-lived child. It does this offline — no network call — and the child's TTL is
clamped by the parent's expiry. --out writes a self-verifying .hcred instead of installing into the keystore.
A contributor-ceiling agent credential, valid for an hour
bash$ heddle auth derive-agent --server heddle.sh --agent-id nightly-refactor --ttl 3600 --template contributor --scope repo:acme/api --out agent.hcred Three templates set the operation ceiling:
reviewer- Read plus Pull. No writes, no ref moves.
contributor- The reviewer set plus Push, UpdateRef, context writes and discussion
writes. No repo or namespace admin. This is the full safe agent
ceiling — the named form of deriving with no template and no
--allowat all. ci-landing- Read plus Pull plus the Push and UpdateRef a CI lander needs to run
readyandland. No context or discussion writes.
--scope takes repo:org/name, a bare repo path,
or namespace:org. The repo: form is the one
with server-side enforcement behind it today. Namespace-scoped agent
tokens are encoded client-side as a repo-path-prefix caveat, and whether
they are independently enforced server-side is not established here —
prefer repo: where you can.
Where credentials live
Not in an OS keychain. The keystore is plaintext TOML at <HEDDLE_HOME>/credentials.toml, default $HOME/.heddle, written atomically. Treat the file as the
secret it is.
A .hcred is a single self-verifying JSON file at mode 0600. Loading is fail-closed: it re-derives the subject,
proof key and expiry from the token bytes and rejects any mismatch,
refuses group- or other-readable files outright with a chmod 600 message, refuses symlinks to non-files, and caps
the size.
HEDDLE_HOME and HEDDLE_CONFIG are different
axes and are easy to conflate. HEDDLE_HOME roots credential
and device-identity state; HEDDLE_CONFIG points at a user config.toml and takes no part in credential resolution.
Descriptor trust is a separate thing
heddle auth trust pins the server's descriptor-signing key
on first use. It protects the signed endpoint descriptor used to
bootstrap a connection — relay URLs, ALPN versions, direct addresses —
against a MITM or a compromised relay substituting a different server
identity. It is not the Biscuit auth token, and it moves by
compare-and-swap: auth trust replace requires --expect-current-public-key to match the existing pin, so a
pin cannot move without out-of-band verification.