Skip to main content
hibi is a single self-contained executable. Output is TTY-aware: in a terminal you get a rich, grouped-by-document human view (color paired with symbols, honoring NO_COLOR); piped, redirected, or in CI you get compact JSON, so the machine contract is preserved. The JSON is decision-first: every payload leads { ok, action, schemaVersion, … }, the verdict and its remediation menu come before any supporting detail, so a truncated read still surfaces the decision and what to do about it. Force a specific shape with the flag vocabulary: --json (compact JSON — the machine contract agents and SDKs read), --json --pretty (indented JSON), --pretty (rich human view even when piped), --compact (one line per claim), --color auto|always|never (also honors NO_COLOR / FORCE_COLOR), and --simple (ASCII symbols). hibi completions <zsh|bash|fish> prints a shell completion script. Two flags tune how much each JSON payload carries — the agent hot path:
  • --explain (alias --detailed): the JSON is concise by default (decision fields plus the remediation menu, bulky evidence dropped). --explain appends the evidence tail, an advisories list, and the proposition fingerprint to every verdict.
  • --no-hints (or HIBI_ADVICE=0): drop the remediation action menu from every verdict and list row, for noise-sensitive harnesses.
All commands operate against a committed claim store (.claims/, one file per claim) beside your docs. The anchor is its own baseline, so every command runs offline and is correct under a shallow clone (git clone --depth=1).

Commands

version and help round out the set.

hibi record

record is span-first: the documented sentence’s span supplies the claim text (the doc side), and you anchor zero or more code spans that back it (the code side). The doc span is the only source of the claim text — there is no side-channel override.
How a claim becomes behavioral. --behavioral makes it behavioral, wording irrelevant. With neither flag, the claim is behavioral iff the deterministic keyword heuristic matches (keyword, comparison/ordering, temporal/sequencing, or exception/error language) or it declares at least one verifier. --no-behavioral skips the heuristic entirely and requires the verifier list to be empty — a verifier is itself a behavioral declaration, so the combination is a contradictory record, rejected by the schema at record time and at store load. The error names the two legitimate noise levers: narrow behaviorScope (exclude globs, or depth: 0) or hibi ignore --claim <id> --reason <text>. Free-form kind labels (e.g. “retry”) belong in the open attrs bag; the engine does not interpret them.
record refuses an enforced claim unless the doc side resolves, a --ref is present, the code side is precise (not coarse or glob-only), and every code target resolves. Otherwise the record lands as suggested. Coarse and --glob targets are navigation-only and cannot back an enforced claim.
Record-time doc-quote guard. The doc span must anchor reliably, so record (including --from-file) and reanchor reject a doc-side quote that cannot. Two rejections, each exiting 1:
  • Too short — a quote under 8 characters: doc quote is shorter than 8 characters — too short to anchor reliably. Record a wider span (--doc-range) that covers the full sentence.
  • Ambiguous — a quote that occurs more than once and whose 48-character context can’t single out one occurrence: doc quote occurs N times in <docPath> and the surrounding context does not select a single occurrence. Record a wider span (--doc-range), or add an inline ID and re-record.
In a --from-file batch, one failing spec fails the whole batch — nothing is written.
When a recorded claim lands suggested, its JSON carries a warning“recorded as suggested — won’t gate the build; pass --enforce to make it gating” — so the advisory status never passes silently. And when the claim’s proposition was reached by fingerprint dedup (the same sentence is already claimed), the JSON adds existingClaims (the other claims asserting that proposition) and a next hint — “this proposition is already claimed — did you mean hibi reanchor?” — so you re-point the existing claim instead of recording a duplicate.

Batch authoring — --from-file

To author many claims at once — onboarding a repo, or an agent grounding a set of docs — pass a JSON array of claim specs instead of one claim’s worth of flags. This avoids shell-quoting verbatim spans and records the whole set in one pass. - reads the array from stdin.
Each item’s keys mirror the flags in camelCase. doc plus one doc-span key are required; everything else is optional:
Keys: doc, docQuote / docRange / docLine, codeFile, codeQuote / codeRange / codeLine, glob, coarse, inlineId, trust (default inferred), enforce / enforcement, behavioral, verifier, pristine, owner, ref, ttl.
Every spec is validated before any write — a malformed item fails the whole batch, never leaving half of it recorded. Propositions still dedup by fingerprint, so the same sentence recorded from two files shares one meaning.

hibi reanchor

reanchor re-resolves a claim’s anchors against the current working tree and resets its state to unchanged — the supported way to settle a moved claim or re-point one after an edit. It preserves the claim’s identity (same id, owner, and history); only its anchors and evidence baseline change. Whether authored trust survives depends on --ref — reanchoring with --ref asserts “I re-verified this” and retains trust; reanchoring without it downgrades verified trust to inferred (see the flag table).

Recovering an orphan — --suggest

When a claim’s documented sentence has been deleted from its file, reanchor alone can’t repair it — it has no span to resolve against. hibi reanchor <claim-id> --suggest is the read-only recovery aid: it takes the claim’s stored doc-side text-quote and localizes it against the current content of every document registered in the store, then prints the ranked candidate targets so you can pick one and re-anchor with an explicit --doc-range. It never writes the store or any document, and it always exits 0 (an operational error still exits 1). It refuses to be combined with any mutation flag, failing with exactly: --suggest is read-only and cannot be combined with mutation flags.
Candidates keep a similarity ≥ 0.5, are sorted by similarity descending, then document path ascending, then region start ascending, and are capped at 5; each snippet is the matched region text trimmed to 120 characters. Zero candidates is a valid result (an empty array). The doc:orphaned remediation action carries this command pre-filled, so you run it, inspect the candidates, then hibi reanchor <id> --doc-range … to re-anchor.
Relocating a doc anchor (--doc) moves the claim, it does not copy it: the source document is left intact as audit, and the claim no longer anchors to it — so the old file can be deleted without orphaning anything. This is the generic primitive behind doc splits, merges, renames, and promotions; it is not supersession, which records a document-to-document edge.

hibi relocate

relocate is the batch consolidation primitive: it re-homes every live (non-retired) claim stranded on --from onto --to in one pass, instead of making you reanchor each one by hand. A claim is re-homed when its current documented sentence appears verbatim in --to; each move rides the same reanchor machinery, so it keeps the claim id, code side, and history, and only the documentId changes. Claims whose sentence is absent from --to are never silently dropped — they are reported as misses for you to reanchor or retire by hand.
The JSON reports what moved and what did not:
doc and code on each relocated entry are the post-reanchor per-side AnchorStates (e.g. unchanged). misses lists the claims that need a manual reanchor or retire.

hibi list

list is the triage view: one lean row per claim, ordered most-severe-first, so you can see the whole suspect set at a glance and pick the next claim to act on. Narrow it with --state:
Each row carries just the handle and the headline decision — claimId, propositionId, documentPath, codePath, status, severity, gates, and the recommended remediation action (or null). It is the fast path to “which claim, and what do I do,” with the full verdict a check away. Pass --ids-only (on list or query) to drop the JSON envelope entirely and emit a bare, de-duplicated, newline-delimited list of claim ids to stdout — the shape a shell loop wants:

hibi coverage

coverage is the grounding-audit worklist: it segments a document into blocks (blank-line separated; fenced code blocks kept whole) and reports each block as covered — a live, code-grounded claim’s doc anchor resolves cleanly into it — or uncovered. Read-only; it writes nothing and judges nothing.
A block counts as covered only when the claim is live and code-grounded and its doc anchor resolves unchanged/moved — a doc-only suggested placeholder or a drifted anchor does not count (that is check’s concern). Walk the covered: false regions and decide ground-or-prune: anchor the blocks a code span backs (hibi record, or the batch --from-file), and cut the prose nothing backs. Hibi never extracts claims from prose — the judgment on every uncovered block stays with you. Note range offsets are banner-normalized (the HIBI banner is stripped before segmenting), so identify a block by its preview text rather than byte-slicing the raw file at range. Each region also carries executable: true when its block is or contains a fenced code block whose info string is one of the exact set sh, bash, zsh, shell, console — the whole detection rule, no other heuristics (a ```json or ```ts block is not executable). An uncovered executable block is the highest-value grounding target: it can carry a command: verifier and reach a supported/refuted behavioral verdict, so when any exist the next hint leads with them and summary.uncoveredExecutableBlocks counts them; the general ground-or-prune steer for any remaining prose blocks still follows. coverage only tags — it never records a claim; creation stays explicit.

Gating a plan — --fail-uncovered

By default coverage is a pure report and always exits 0. Pass --fail-uncovered to make it gate: when any uncovered block remains, the command exits with the gating exit code 2 (the same code check uses for a gating verdict). JSON and human output are unchanged — only the exit code differs. This is the CI-enforceable form of “this plan must be fully grounded”: an uncovered block is an unimplemented or unpruned plan item.

hibi retire

retire withdraws a single claim: it flips that claim’s enforcement to retired, and a retired claim never gates or warns again. It is the supported way to silence a claim that is genuinely obsolete — never hand-delete the claim’s file from .claims/, which loses the audit trail.
The call is idempotent: retiring an already-retired claim succeeds and reports alreadyRetired: true. Most drift verdicts that recommend retiring already hand you the exact command in their remediation menu, claim id pre-filled. Pass --dry-run to see what would be withdrawn without writing — the envelope gains dryRun: true and next: "re-run without --dry-run to apply".

hibi ignore

ignore acknowledges a behavioral at-risk you have re-verified by hand: it stores the acknowledged evidence — the current { path → hash } map — plus your reason on the assertion (suppressed). While every acknowledged path still carries its acknowledged hash, the at-risk is non-gating: the verdict surfaces suppressed: true in JSON and does not affect exit codes.
The suppression lapses automatically: the moment any acknowledged evidence path’s hash moves past the acknowledged one, or a new evidence path appears, the claim flags again. ignore silences one specific, inspected change-set — never the claim itself. To withdraw a claim for good, use hibi retire.

hibi doctor

doctor is a store-health report: it surfaces the dead state that check hides — claims and propositions that are not drifting but are nonetheless broken or redundant. It is purely informational and always exits 0, so it never gates a build; run it to triage the store, not to guard it.
It reports four categories: Beyond the categories, doctor reports two rate metrics, computed from a read-only resolution pass (doctor never runs verifiers, and it still always exits 0):
  • Behavioral flag-rate — the share of behavioral claims currently at-risk or refuted. Guidance: above ~30% on a typical commit, tighten the change gate — narrow behaviorScope with exclude globs or a smaller depth.
  • Doc-side orphaned / moved / changed rates. Guidance: above ~30% orphan rate on typical edits, use inline IDs for high-severity claims.
The envelope adds a counts object (one tally per category), a healthy: boolean (true iff every category is empty), and a next hint that routes to the most pressing category (e.g. hibi list --state orphaned):

The verdict, in brief

Hibi never collapses a claim into one word. A verdict carries two independent axes plus a flag: anchor resolution per side (doc:unchanged · code:changed, from the vocabulary unchanged · moved · changed · ambiguous · orphaned), an optional behavioral belief on behavioral claims (unverified · at-risk · supported · refuted), and an orthogonal expired TTL flag. The JSON is decision-first — the verdict and its remediation menu lead, the bulky evidence trails (and only appears under --explain) — so a truncated read still surfaces the decision and the next step. “Drift” and “stale” are only the human roll-up for any claim needing attention, never machine states.

The full verdict model

States, confidence bands, grading, the remediation menu, and how a verdict becomes an exit code, all live on the Verdicts page.

JSON output shapes

Every payload leads { ok, action, schemaVersion, … }, where schemaVersion (e.g. "v1") is emitted in the payload so a consumer can branch on the contract version without reading a filename. check / diff / status return a decision-first envelope: an ok/action/ schemaVersion header, a summary of counts, a verdicts array, and a documents roll-up. Each verdict is concise by default — { assertionId, propositionId, documentId, doc, code, behavior?, expired, suppressed?, gates, changed?, remediation, notes } — with the evidence tail, advisories, and fingerprint added only under --explain. The changed? field is the one-line behavioral carve-out: it appears on behavior:at-risk / refuted verdicts even on the concise path so you learn what moved. suppressed? is true on an at-risk acknowledged via hibi ignore — the verdict is surfaced but never affects exit codes. diff additionally reports since and changedFiles. Mutating verbs add a next field — the exact follow-up command to run — and record, reanchor, and retire also return the resulting claimId:
list returns { ok, action, schemaVersion, state, count, claims[] }, where each claim row is the lean handle described above. query returns { ok, action, schemaVersion, path, count, hits[] } — the way you find a claim’s id before editing. coverage returns { ok, action, schemaVersion, doc, summary: { blocks, coveredBlocks, uncoveredBlocks, uncoveredExecutableBlocks, coverageRatio }, regions[], next } — see hibi coverage above.

Exit codes

Hibi communicates results through its exit code, so it slots straight into CI and git hooks: moved and at-risk never gate. suggested claims never set a failing exit code; only enforced claims can.

Strictness: --fail-on

--fail-on tunes which states fail the run:
In CI, pair hibi check with --fail-on to choose how strict the gate is. The official GitHub Action wraps this.

Running verifiers: check --run-verifiers

Verifiers execute repo-committed commands — a supply-chain surface — so they run only under check --run-verifiers. status, query, list, doctor, and plain check never spawn a verifier process.
The built-in command runner handles kind: "command": it runs the verifier’s ref as a shell command via sh -c on POSIX or cmd /c on Windows (cwd = repo root), so cross-platform repos should keep verifier refs shell-neutral (e.g. bun test retry, not a shell builtin or && chain). Exit 0supported; non-zero → refuted; a timeout or spawn failure produces no result, so the belief stays at the deterministic baseline. The per-verifier timeout defaults to 120 seconds; tune it with --verifier-timeout <seconds>. External runner resolvers still require the default-deny manifest (.claims/resolvers.json). Verifier results beat change-gate routing: any failing verifier → refuted (gating on an enforced claim); all passing → supported; otherwise the gate result stands.

Global options

These apply to every command:

Next

Verdicts, states & exit codes

The two-axis model in full: every state, the confidence bands, and gating.

CI, git hooks & agents

Wire these commands into a GitHub Action, a git hook, or an agent’s edit loop.