Exit codes
The standalone CLI uses three exit codes. Use the exit status to gate a pipeline; it does not itself enforce an agent’s loading decisions.
| Code | Name | Meaning |
|---|---|---|
0 |
Success / Permitted | The command succeeded or verification permits the pipeline to continue under its policy. Drift and Warning also return 0. |
1 |
Blocked | seal verify only. The project has unverified or mismatched bundles under policy: "block". |
2 |
Fatal Error | A fatal configuration, usage, confirmation, or system error prevented completion. |
Per‑command semantics
Section titled “Per‑command semantics”seal init
Section titled “seal init”| Code | Triggered by |
|---|---|
0 |
New seal.json written. |
2 |
seal.json already exists, confirmation declined (init aborted), no TTY for confirmation, or a system error. |
seal pin
Section titled “seal pin”| Code | Triggered by |
|---|---|
0 |
Pin applied successfully, or no changes were required (the short‑circuit No changes path). |
2 |
seal.json missing or invalid, no TTY for confirmation, confirmation declined (pin aborted), path argument outside project root, unreadable file during hashing, unsupported file (symlink/device) inside a sealed root, lockfile contains unknown fields, or any other system error. |
seal verify
Section titled “seal verify”| Code | Outcome | Triggered by |
|---|---|---|
0 |
Verified |
All checked roots match; nothing unverified, removed, or mismatched. A valid empty verification set also qualifies. |
0 |
Drift |
One or more recorded roots are missing, with no unverified or mismatched roots. Reported, not blocking. |
0 |
Warning |
One or more unverified or mismatched bundles under policy: "warn". Reported, not blocking. |
1 |
Blocked |
One or more unverified or mismatched bundles under policy: "block". |
2 |
(fatal) | seal.json missing or invalid, --json + --quiet combined, system error. |
An individually pinned file or whole bundle that disappears produces Removed and, alone, Drift with exit 0. A missing file inside a still-present directory bundle produces Mismatch. See the scenario tables and policy precedence.
Native agents must also block if they cannot suppress project-external extensions. That requirement belongs to the native integration contract; the standalone CLI does not suppress extensions.
seal upgrade
Section titled “seal upgrade”| Code | Triggered by |
|---|---|
0 |
Upgrade check completed, no update was needed, or the upgrade completed successfully. |
2 |
Current version is not a stable release, release lookup failed, no matching asset exists, checksum verification failed, go install failed, replacement failed, or any other system error. |
Why these specific codes
Section titled “Why these specific codes”0: permitted by the command or policy. For verification, inspect the outcome if you need to distinguish matching contents from removed roots or warnings.1: verification blocked by policy. A mismatch or unverified bundle was found underblock.2: the command could not complete. Investigate the diagnostic for an invalid lockfile, usage or confirmation problem, or filesystem/system error.
For CI verification, both 1 and 2 should fail the job. Neither Verified nor exit 0 proves that files outside the configured verification set were checked.
Streams
Section titled “Streams”Diagnostics, prompts, human verification output, and warnings go to stderr.
Machine‑readable output (seal verify --json) goes to stdout.
--quiet produces no output anywhere.
If seal verify exits with code 2, it does not emit JSON to stdout. CI scripts parsing stdout should always also check the exit code.
Cobra usage errors
Section titled “Cobra usage errors”If you mistype a subcommand or pass an unknown flag, the CLI exits 2 with a seal: <message> line to stderr. The full cobra help block is suppressed because the per‑command output is already actionable.
Cheat sheet for CI
Section titled “Cheat sheet for CI”For a simple gate, let the command’s nonzero exit fail the job:
seal verify --quietIf you need custom messages, preserve the exit code. This form also works in shells using set -e:
seal_status=0seal verify --quiet || seal_status=$?case "$seal_status" in 0) echo "Permitted by policy: Verified, Drift, or Warning" ;; 1) echo "Blocked: mismatched or unverified bundles" ;; 2) echo "Fatal: verification could not complete" ;;esacexit "$seal_status"