# Heddle — the CLI contract for agents > Driving `heddle` unattended. Ground truth: heddle 0.12.0 — pin a minor and > the catalogued output shapes hold. ## Your git prior, corrected Heddle embeds its own git engine (sley) and NEVER shells out to `git`. - **States**, not commits: immutable snapshots with a stable `hd-…` id. - **Threads**, not branches: named work with its own checkout, `stale` once the target advances. - **Capture**, not add-then-commit: `heddle capture -m "intent"` records the WHOLE tree. No staging area, no path filter. - `heddle commit` is not git commit: it publishes captures to `.git`, exists only in Git Overlay, runs NO git hooks. - `hd-…` ids go to heddle, the checkpoint sha to git clients, the `(abcd1234)` BLAKE3 hash to neither. Rebase or amend mints a NEW `hd-…`. ## The two modes (everything dispatches on this) - **Git Overlay** — `heddle init` in an existing checkout. `.git` stays authoritative, `.heddle` is a sidecar. - **Native Heddle** — `heddle adopt`. Heddle owns source authority; `capture` alone saves history; `.git` becomes a compatibility projection. ONE-WAY — get human sign-off. `heddle status` is observe-only, safe in ANY directory, creates nothing, prints the next command. Start every session with it. ## Memory that is not a markdown file `heddle context set --kind invariant --scope symbol: -m "..."` pins a versioned annotation to a file, symbol, or line range (kinds: constraint, invariant, rationale). The claude-code integration injects matching annotations on PreToolUse for file-touching tools — read BEFORE editing, not after failing. Harness-less: `heddle context get --path `. `heddle context check` reports when code moved out from under an annotation; `edit`/`supersede`/`history` keep revisions. NEVER projected into Git: annotations move only over `heddle push`/`pull` — a plain `git clone` has NO STORE PRESENT, which is not "no annotations". ## Machine output - `--output json`: the full contract (`output_kind` discriminator, exit codes). `--output json-compact`: decision surface only, fewer tokens. - Text is the default ALWAYS — no TTY detection. Never parse it. - **Success JSON to stdout, error envelopes to STDERR.** Capture both or failures look like empty output. Envelopes carry a typed `kind` and an executable `argv_template`. - `heddle schemas ` per verb; nine verbs are text-only, notably `heddle auth login`. - Mutating commands take `--op-id `; replay is safe (`heddle help operation-ids`). ## Exit codes (typed error kinds, never message text) 0 ok · 64 usage · 65 semantic rejection · 73 output file refused · 74 IO catch-all · 77 permission · 78 missing precondition (print the missing setting, do not retry). - **75 transient is the ONLY safe retry**, same args. - **76 protocol: the remote rejected the payload.** Identical inputs fail identically — escalate, never loop. Declared per-code only for init, status, verify, commit, push, pull, `heddle import git`, `heddle sync git`. ## Auth, headless A **principal** (human) owns the account; agents act as scoped credentials under it. `heddle whoami` answers "am I set up?". - `heddle auth login` — DEVICE-CODE flow: prints a URL and short code, polls until a human approves. - CI: `HEDDLE_CREDENTIAL=` is authoritative, bypasses the keystore, re-read per call. Real, though absent from `--help`. ``` heddle auth derive-agent --server --agent-id --ttl 3600 \ --template contributor --out agent.hcred # offline ``` Templates `reviewer` · `contributor` · `ci-landing`; `--allow` only narrows, TTL clamped by the parent. `.hcred` files self-verify, fail closed. ## The core loop ``` heddle status --output json # where am I, what next heddle diff --output json heddle capture -m "why" # -f for huge trees heddle commit # Git Overlay only heddle push # 75 retry, 76 do not ``` ## Isolated work ``` heddle start --path ../ --task "..." # own checkout heddle ready # conflicts, blockers, freshness; never lands heddle land --thread # fails closed on conflicts ``` `--hydrate` SYMLINKS node_modules/.venv/target from the origin — installing a dependency there mutates the origin's copy. Isolated checkouts have no `.git`. Recovery: `heddle resolve` · `heddle continue` · `heddle abort`. `heddle undo` is THREAD-LOCAL — run it in the checkout you want rewound. ## The lease protocol (parallel agents) ``` heddle agent reserve --thread feature/x # -> lease_id + token heddle agent heartbeat|capture|ready|release --lease L --token T ``` Five-minute lease; capture and ready renew it; release closes `complete` or `abandoned`. Prefer `HEDDLE_RESERVATION_TOKEN` to `--token` where process lists are visible. Session ids attribute provenance, not write authority. All of `heddle agent` is local — no server. Hooks: `heddle integration install claude-code|codex|opencode`. ## Hazards - Discovery walks UP the tree — pass `-C ` in automation. - `heddle capture` has no path filter: check `heddle status` first. - `heddle commit` bypasses git hooks — run linters yourself. - `heddle redact` and `heddle redact purge` remove history — human sign-off. Self-documenting throughout: `heddle help model` · `git-concepts` · `output-formats` · `operation-ids` · `threads` · `agent-flags` · `heddle help --output json`. Index: https://heddle.sh/llms.txt · Assembled at build from the docs route tree; links and commands checked against it.