HEDDLE

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 login never runs. It appears in no --help output — 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 push

Derived 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 --allow at all.
ci-landing
Read plus Pull plus the Push and UpdateRef a CI lander needs to run ready and land. 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.