Skip to content

Agent-facing CLI

attest is built for coding agents as well as people. Every command is discoverable offline, prints one JSON document on request, and returns a documented exit code. attest in each SDK implements init itself and forwards every other command to attest-engine; the contract below applies to both spellings.

Terminal window
attest help --json # every command, its schema, its exit codes
attest guide # list the shipped guides
attest guide <topic> # print one guide as Markdown, offline

attest help --json prints {"commands": [{"name", "summary", "schema", "subcommands", "exit_codes"}]}. schema and each subcommand’s schema are paths relative to proto/attest/v1/ in the attest repository. Run through the SDK (uv run attest help --json, npx attest help --json), the document also lists init, which the SDK implements itself (schema cli/init.schema.json; exit 0 success, 1 --skills or --mcp could not install, 2 usage error). The text form (attest help) is unchanged.

For example, ask what this installed engine supports, then read a guide without opening a browser:

Terminal window
uv run attest capabilities --json
uv run attest guide replay --json

Every command and subcommand accepts --json. With --json a successful command writes exactly one JSON document to stdout and sends diagnostics to stderr. On a usage, load or runtime error the command writes nothing to stdout; the exit code and stderr describe the error. Errors are not JSON objects: read the exit code and stderr. Without it, output stays human-readable.

Commands that run a child process (capture, replay, world with -- <command>) send the child’s stdout to stderr under --json and print one result object at exit; exit_code in that object is the child’s exit code (null when a signal killed it). --serve already writes JSON lines, so --serve --json is a usage error (exit 2).

attest init --json prints {"created": [...], "updated": [...], "skipped": [...]} with paths relative to the project root; see attest guide agents.

CommandSchema
baseline pincli/baseline-pin.schema.json
baseline listcli/baseline-list.schema.json
baseline showcli/baseline-show.schema.json
baseline deletecli/baseline-delete.schema.json
cache statscli/cache-stats.schema.json
cache clearcli/cache-clear.schema.json
calibratecli/calibrate.schema.json
capabilitiescli/capabilities.schema.json
capturecli/capture.schema.json
doctordoctor.schema.json
guidecli/guide.schema.json
mcp tools (mcp --tools --json)cli/mcp-tools.schema.json
mcp installcli/mcp-install.schema.json
mutatecli/mutate.schema.json
policy evaluatecli/policy-evaluate.schema.json
replaycli/replay.schema.json
report junitcli/report-junit.schema.json
report summarycli/report-summary.schema.json
report rowscli/report-rows.schema.json
selectcli/select.schema.json
skills listcli/skills-list.schema.json
skills installcli/skills-install.schema.json
trace checkcli/trace-check.schema.json
trace convertcli/trace-convert.schema.json
versioncli/version.schema.json
viewcli/view.schema.json
worldcli/world.schema.json
helpcli/help.schema.json

doctor keeps its schema at proto/attest/v1/doctor.schema.json; init is cli/init.schema.json.

Convention: 0 success, 1 the command ran and the result is a failure (check failed, block, child failed), 2 usage or invalid input. policy evaluate is the exception: its exit code is the verdict, so usage and load errors use 3 and cannot be mistaken for a warning or a block.

The table is checked against the engine’s command registry by a test; a change to either side fails go test ./....

CommandCodeMeaning
baseline0success
baseline1the report could not be loaded or has no assertion results, the tag is not pinned (show), or the baseline store failed
baseline2usage error
cache0success
cache1the cache directory could not be read, or the home directory could not be determined
cache2usage error
calibrate0success
calibrate1the labels file could not be read, has no judge_score rows or no usable agreement, or persisting failed
calibrate2usage error
capabilities0success
capabilities1writing the output failed
capabilities2usage error
capture0the fixture is verified or captured with nothing to verify, or —check-redaction found no secrets; the command’s own exit code is recorded, not propagated
capture1the fixture is not verified (a drafted contract failed, the trace check failed, no step was mapped, —expect-fail drafted nothing, or nothing was drafted while the command exited non-zero or recorded no model call) or was not written, the capture failed, or —check-redaction found secrets
capture2usage error, an invalid —world file, or a —refresh that was not confirmed
doctor0success
doctor1configuration error the JSON-RPC server would refuse to start with
doctor2usage error
guide0guide list or guide printed
guide1an embedded guide is unreadable or has no title
guide2unknown topic or usage error
mcp0the client disconnected, the tools were listed, or the client configs were written
mcp1the server failed, the project root is unusable, or a config could not be read or written
mcp2usage error
mutate0a mutation report was produced
mutate1no contract applies to any fixture, so there is no score
mutate2usage error, or a fixture or contracts directory could not be loaded
policy0pass: every rule satisfied
policy1block: a block-severity rule was violated
policy2warn: only warn-severity rules were violated
policy3usage error, or the policy, report, baseline or mutation report failed to load, or a rule lacks its input (block_on_regression or regression without —baseline, min_mutation_score without —mutation), or the report has 0 tests while tests_collected is above 0, or the baseline was pinned under id scheme 1 (re-pin it on 1.1), or the head report uses id scheme 1 (re-run with an SDK on 1.1)
replay0every request was served and the command exited 0
replay1the command exited non-zero (its code is not propagated; —json reports it as exit_code), a request missed, or the fixture could not be loaded or served
replay2usage error or an invalid —world file
report0success
report2usage error, or unreadable or invalid input, or the output could not be written
select0success, including an empty selection
select2usage error, or git or the base ref failed
skills0skills listed or installed
skills1an embedded skill is invalid or a destination was refused or a file could not be written
skills2usage error
trace0success: the trace converted, or check found no structural errors
trace1check found structural errors, or the input could not be read, parsed or converted
trace2usage error
version0success
version1writing the output failed
version2usage error
view0success: the page was written
view2usage error, or unreadable or invalid input, or the page could not be written
world0the command exited 0, or —serve stopped cleanly
world1the command exited non-zero (its code is not propagated; —json reports it as exit_code), or the world could not be served or its state written
world2usage error or an invalid world.yaml

attest-engine replay --trace-out <file> -- <command> writes the trace of the new run (the spans the command exported over OTLP) to <file> as attest trace JSON. It is written when every request was served, whatever the command’s exit status (an incident recording exits non-zero). The trace is not redacted: it holds what the command sent and received during that run. Write it to a private directory and do not commit it. A drafted replay test keeps it in a private temporary directory that is removed when the run ends. --trace-out needs -- <command>; it is a usage error with --serve.

Nothing prompts under CI, --json or a non-TTY stdin. The only confirmation prompt (attest capture before it re-runs a command for --refresh) refuses with exit 2 and a --yes hint when CI is set, --json is given or stdin is not a terminal. Pass --yes to proceed. It is not the only place a recorded command runs: a drafted replay test runs the argv written in the test file itself (COMMAND, reviewed with the test) and refuses to run when the fixture’s source.command differs from it, or has redacted or templated arguments. See Capture.

attest guide and attest skills read assets embedded in the engine binary and make no network calls.