CLI reference

attest has five subcommands: sign, verify, log, export, and keygen. The default subcommand (running attest with no subcommand) is log.

All commands that touch a repository accept --path <dir> / -C <dir> (default .) to point at the repository to operate on.

attest <subcommand> [options]

Colored output

The human-readable output of verify and log is semantically colored: green for PASS / proceed / verified signatures, amber for review, red for FAIL / block / violations, cyan for reviewer identities, and dim for secondary text (unsigned records, absent tests/human, notes). Colour is meaning, not decoration; it is independent of any brand colour.

Colour is controlled by --color <mode> on verify and log:

ModeBehaviour
auto (default)colorize only when stdout is a TTY and NO_COLOR is unset.
alwayscolorize even when piped or redirected.
nevernever emit ANSI escape codes.

In auto, piping or redirecting (attest log | less, > file) and any --json output stay plain (byte-identical to --color never), so scripts and pipelines are unaffected. Setting the NO_COLOR environment variable disables colour in auto mode.

attest log --color always | less -R    # keep colour through a pager
NO_COLOR=1 attest verify --range main..HEAD   # force plain output
attest log --json                       # JSON is always plain

Exit codes

CommandExit 0Exit 1Other non-zero
verifyevery checked commit passes the policya commit violates the policyusage / git / I/O error
sign, log, export, keygensuccessn/ausage / git / I/O error

attest verify’s exit code is its contract: a policy violation propagates exit 1, which is what CI and agent loops gate on. The other commands exit non-zero only on an actual error (invalid arguments, not a git repository, a missing signing key, malformed input).

attest sign

Record an attestation for a commit, written to git notes (refs/notes/attest).

FlagDefaultDescription
--commit <rev>HEADthe commit to attest (SHA or revision).
--reviewer <id>(required)who or what reviewed, e.g. agent:claude, human:leif.
--confidence <0..1>nonereviewer confidence; clamped to 0…1.
--verdict <v>nonerecorded verdict: proceed, review, or block.
--tests-passedoffrecord that the change’s tests passed.
--human-approvedoffrecord that a human approved (implies confidence 1.0 if none given).
--note <text>noneoptional free-text note.
--from-augur <file|->noneread augur check --json and merge verdict + derived confidence.
--signoffsign the attestation with the key from attest keygen.
--jsonoffemit the stored attestation as JSON.

A confidence value must come from somewhere: pass --confidence, --human-approved, or --from-augur. Explicit --verdict / --confidence flags override augur-derived values.

# Unsigned, zero setup:
attest sign --commit HEAD --reviewer agent:claude --confidence 0.92 --tests-passed

# Signed sign-off by a human:
attest sign --commit HEAD --reviewer human:leif --confidence 0.7 --human-approved --sign

# Pipe augur straight in (verdict + confidence auto-filled from its JSON):
augur check --json | attest sign --commit HEAD --reviewer agent:claude --from-augur -

--from-augur

Reads augur check --json from a file or - (stdin) and merges it: augur’s verdict is copied, and its riskScore (0…100) becomes confidence = 1 − riskScore/100 (so risk 45 → confidence 0.55). See Signing & identity and the project README for the full augur pipeline.

attest verify

Exit non-zero if any commit in a range violates the policy. This is the gate for CI and agent loops.

FlagDefaultDescription
--range <a..b>nonea git range to check, e.g. origin/main..HEAD.
--commit <rev>nonecheck a single commit; defaults to HEAD when neither --range nor --commit is given.
--policy <path>.attest.jsonpath to the policy file (falls back to the permissive default if absent).
--jsonoffemit machine-readable JSON instead of the human report.
--color <mode>autocolorize the human report: auto (TTY only), always, or never.
attest verify --range origin/main..HEAD --policy .attest.json
attest verify --commit HEAD --json

The human report is a single headline line (PASS green, FAIL red), with any violations listed beneath in red under an amber heading:

attest verify · [ok] PASS (3 commits checked)
attest verify · [x] FAIL (2 commits checked)

  violations:
    x abc1234567  requireTestsPassed: no attestation reports passing tests

JSON shape:

{ "checkedCommits": 1, "passed": false,
  "violations": [ { "commit": "…", "detail": "…", "rule": "requireTestsPassed" } ] }

The current epoch is used as the reference time for the maxAgeDays freshness rule (see Policy reference).

attest log

List recorded attestations, human-readable or JSON. This is the default subcommand.

FlagDefaultDescription
--range <a..b>nonelimit to a git range.
--commit <rev>nonelimit to a single commit.
--jsonoffemit machine-readable JSON.
--color <mode>autocolorize the listing: auto (TTY only), always, or never.

With neither --range nor --commit, log lists every attested commit.

attest log                        # all attested commits
attest log --commit HEAD --json   # one commit, machine-readable
attest log --range main..HEAD

The listing groups attestations by commit. Each row is colorized by meaning: the verdict badge and verdict:/conf: tints track severity (green proceed, amber review, red block), reviewer identities are cyan, tests:ok / human:ok / signed[ok] are green, and unsigned / absent cues are dim:

attest · ledger

  commit abc1234567  (2 attestations)
    [ok] agent:claude  verdict:proceed  conf:95%  tests:ok  human:-  unsigned
    [!] human:leif  verdict:review  conf:72%  tests:ok  human:ok  signed[ok]
        note: reviewed the migration by hand

log is a human / diagnostic listing. For a durable, machine-stable audit document, use export.

attest export

Emit the complete provenance trail across a range as one stable JSON audit document, suitable for compliance archival. Always JSON (no --json flag).

FlagDefaultDescription
--range <a..b>nonea git range to export.
--commit <rev>noneexport a single commit; with neither, exports every attested commit.
--policy <path>noneoptional; when set, each commit’s pass/fail is included.
--pretty / --no-pretty--prettypretty-print (default) or emit compact JSON.
attest export --range origin/main..HEAD                    # whole range
attest export --commit HEAD                                # one commit
attest export --range main..HEAD --policy .attest.json     # with per-commit verdicts
attest export --range main..HEAD --no-pretty > audit.json  # compact, for storage

Output is deterministic: commits appear oldest-first (the order git rev-list --reverse returns), records in store order, and JSON keys are sorted, so it diffs cleanly. Every commit in the range is represented, including commits with no attestations. Each record carries a verification block: signed, and for signed records whether the signature verified (a tampered or wrong-key record reports verified: false; unsigned records omit verified).

{
  "allPassed": true,
  "commitCount": 1,
  "commits": [
    {
      "commit": "9f2c1a7b04...",
      "policyPassed": true,
      "records": [
        { "attestation": { "...": "..." },
          "verification": { "signed": true, "verified": true } }
      ]
    }
  ],
  "policyApplied": true,
  "recordCount": 1,
  "version": 1
}

attest keygen

Generate an Ed25519 signing keypair for signing attestations.

FlagDefaultDescription
--forceoffoverwrite an existing key.
attest keygen
# attest · wrote private key to ~/.config/attest/key (0600)
# public key: BASE64_PUBKEY      <- copy into signerPinning / trustedKeys

The private key is written to $XDG_CONFIG_HOME/attest/key (or ~/.config/attest/key) with 0600 permissions. keygen prints the public key to copy into a policy’s signerPinning / trustedKeys. See Signing & identity.