Four verdicts.
No fifth, and no hedging.
The CLI is the adoption surface: the only interface a solo developer uses without a signup, a server or a conversation. Here is every shape its output can take, including the one that says it does not know.
No blocking obligation found for the declared intent
A clean run still reports what it read. "No findings" and "nothing scanned" must never look the same — so the header always states the counts and the corpus version.
~$ clearance check . CLEARANCE VERDICT — vector-lite ======================================== SHIP: SHIP BLOCKERS: 0 CONDITIONS: 0 SCANNED: 31 dependencies CORPUS: 2026.09.2 · signed ✓ NOTES [NOTE] 30 dependencies permissive (MIT, ISC, BSD-3-Clause) reason: attribution recorded, no gate applies ---------------------------------------- This is an informational finding based on the licence text as published on the date recorded. It is not legal advice. Ambiguous clauses are flagged as such. Important decisions should be reviewed by a qualified professional. ~$ echo $? 0
No obligation in the corpus contradicts your declared intent. It is not a warranty — it is the absence of a finding.
Exit 0. The job passes. SARIF is still uploaded, so the record exists without failing the build.
One new dependency. One intent field flipped. The verdict is a function of both.
Shippable, once stated conditions are met
Attribution, a rebrand, a cap on users. A condition is a real obligation with a real remedy — so each one carries the same citation and confidence machinery as a blocker.
~$ clearance check . --fail-on BLOCK CLEARANCE VERDICT — acme-portal ======================================== SHIP: SHIP CONDITIONAL BLOCKERS: 0 CONDITIONS: 2 SCANNED: 214 dependencies · 1 weight file · 1 upstream CLI CORPUS: 2026.09.2 · signed ✓ CONDITIONS [COND] kokoro-82m Apache-2.0 (code AND weights) clause: LICENSE §4(c) (retain notices) reason: clean commercial path; attribution required evidence: models/kokoro/LICENSE:1-201 confidence: HIGH [COND] acme-brand-kit MIT (code) + reserved marks clause: TRADEMARK.md §2 reason: name and logo excluded from the grant — rebrand before distribution evidence: vendor/brand-kit/TRADEMARK.md:1-14 confidence: MEDIUM — clause text is ambiguous "the Marks may not be used in derivative works without prior written permission" — 'derivative work' is undefined here ---------------------------------------- This is an informational finding based on the licence text as published on the date recorded. It is not legal advice. Ambiguous clauses are flagged as such. Important decisions should be reviewed by a qualified professional. ~$ echo $? 0 # 1 only if --fail-on CONDITION
Exit 0. Conditions do not fail a build by default — they are recorded in the verdict.
--fail-on CONDITION or block_on: [BLOCK, CONDITION] makes them blocking for your org.
A MEDIUM condition shows the clause text and the reading that was rejected. You can disagree with it — that is the point.
At least one obligation contradicts your declared intent
This is the verdict the product exists for, and the one a vendor with a volume-based business model has no incentive to print. It carries the clause, the reason, the evidence and a suggested replacement.
~$ clearance check . CLEARANCE VERDICT — my-saas ======================================== SHIP: DO NOT SHIP BLOCKERS: 1 CONDITIONS: 2 SCANNED: 47 dependencies · 3 weight files · 2 upstream CLIs CORPUS: 2026.09.2 · signed ✓ BLOCKERS [BLOCK] firecrawl AGPL-3.0-only clause: LICENSE §13 (network use) reason: you run a MODIFIED version and expose it over HTTP evidence: node_modules/firecrawl/LICENSE:1-9 fix: swap to crawl4ai (Apache-2.0, same capability) confidence: HIGH CONDITIONS [COND] kokoro-82m Apache-2.0 (code AND weights) reason: clean commercial path; attribution required confidence: HIGH [COND] hey-gem weights Custom community licence reason: >1k MAU triggers a commercial gate evidence: LICENSE.md §3.2 confidence: MEDIUM — clause text is ambiguous ---------------------------------------- This is an informational finding based on the licence text as published on the date recorded. It is not legal advice. Ambiguous clauses are flagged as such. Important decisions should be reviewed by a qualified professional. ~$ echo $? 1
Exit 1. The pipeline fails at the point of the change, not at the point of the launch — which is the entire value of a build-step gate.
reason: you run a MODIFIED version and expose it over HTTP — the finding states the fact about your project, not just the licence's name.
Insufficient information to produce a verdict
The most important verdict in the product. A tool that guesses when it does not know is worse than no tool — and UNDETERMINED never rounds toward SHIP.
~$ clearance check . CLEARANCE VERDICT — whisper-gguf ======================================== SHIP: UNDETERMINED BLOCKERS: 0 CONDITIONS: 1 SCANNED: 18 dependencies · 2 weight files CORPUS: 2026.09.2 · signed ✓ REASON: 2 items could not be classified UNDETERMINED [UNDETERMINED] models/model.bin licence not found error: E-SCAN-010 — Weight file 'models/model.bin' has no licence statement in config.json, README.md, MODEL_CARD.md or a sibling LICENSE. evidence: models/model.bin (2.1 GB, SafeTensors) action: Locate the licence, or remove the file [UNDETERMINED] npm:legacy-js@0.9.1 licence unresolved error: E-SCAN-011 — no licence could be resolved for legacy-js (raw value: none) evidence: node_modules/legacy-js/package.json (no licence field) action: Read the file, or contribute a corpus entry ---------------------------------------- This is an informational finding based on the licence text as published on the date recorded. It is not legal advice. Ambiguous clauses are flagged as such. Important decisions should be reviewed by a qualified professional. ~$ echo $? 0 # 5 with --strict
An error means the tool failed. UNDETERMINED means the tool succeeded and the project is incomplete. It is a statement about your tree, not about Clearance — and it is the single most common honest answer in AI stacks, where weight files routinely ship without terms.
Exit 0 by default, because an unknown must not break a build. --strict makes it exit 5 for teams that would rather fail than ship an unknown.
Predicates evaluate to true, false or UNKNOWN — never a default. The fold then treats UNKNOWN as outranking a condition and never collapsing to a pass.
Kleene three-valued evaluation. An omitted field propagates as UNKNOWN all the way to the verdict instead of being silently treated as false.
Errors are not verdicts
An error means no verdict was produced. There are 102 stable codes, each with a class, an exit code, an exact message and a recovery path. These are the two that matter most.
~$ clearance check . clearance: E-CFG-002 — Config is missing required fields: use.commercial, use.distributed. Intent must be declared, not inferred. fix: Add the listed fields ~$ echo $? 2
No intent means no answer. The tool refuses rather than assuming commercial: false on your behalf — an assumption that would silently permit everything. There is no scaffolding command: clearance.config.yml is a file you write by hand in the project root, and fixtures/mixed/clearance.config.yml is a minimal working example.
~$ clearance check . clearance: E-CORPUS-002 — Corpus signature is invalid. Refusing to verdict. The previous corpus is unchanged. fix: Re-download the release, or check for tampering ~$ echo $? 3
This is the moat working. A fork can copy the code; it cannot sign the corpus. And a refusal never leaves you without a corpus — the previous one is untouched.
The frozen contract
A CI pipeline written against clearance check . today will still work in five years. Flags are additive only; exit codes are frozen forever.
| Code | Meaning |
|---|---|
| 0 | Verdict produced; no blocker, or CI disabled |
| 1 | DO NOT SHIP |
| 2 | Configuration error |
| 3 | Corpus error |
| 4 | Internal error |
| 5 | UNDETERMINED and --strict |
| Command | Purpose |
|---|---|
| clearance check [path] | Scan and verdict |
| clearance explain <code> | What an error code means, and what to do about it |
| clearance corpus info | Version, date, entries, signature |
| clearance corpus verify | Verify the local corpus signature |
| clearance mcp serve | MCP server over stdio |
| Flag | Default | Meaning |
|---|---|---|
| --config <path> | ./clearance.config.yml | Intent file |
| --format <fmt> | human | human · json · md · sarif |
| --sbom <fmt> | off | cyclonedx · spdx |
| --offline | true | Disable every network call (true in this build) |
| --strict | false | Exit 5 on UNDETERMINED |
| --fail-on <sev> | BLOCK | Minimum severity that fails CI |
| --quiet | false | Suppress the NOTES section |
| Format | Consumer |
|---|---|
| human | Developer at a terminal |
| json | Machines, CI |
| md | A pull-request comment |
| sarif | GitHub code scanning |
| cyclonedx · spdx | Existing SBOM tooling |