corral
Generated by
scripts/gen-cli-docs.shfrom corral’s own-houtput and its main.go doc comment. Do not hand-edit — runscripts/gen-cli-docs.shand commit the result.
corral — the CorralAI brain: an OIDC-authenticated, MCP-native coordination server
Usage: corral serve /mcp/ + /healthz on $CORRALAI_ADDR corral secret set|get|list|rm manage provider keys + tokens in the secure keystore (env → OS keyring → age-encrypted file; set reads stdin, never argv) corral control seed [flags] seed one vetted control test into the control-gate store (--spec-db --owner --goal --target --code-path --test-path --test-file) corral certify [<ref>] [--out <file>] [--net=false] [--produced-by a,b] -- <check-cmd>... certify a change by execution: check out <ref> (default HEAD) into a jail, run <check-cmd> there, and write a signed, offline-verifiable record; exits with <check-cmd>'s own exit code signs locally (no server) unless --brain is given flags: --produced-by a,b --out <file> --net=false --repo/--commit/--branch (default: read via git) corral certify --brain <url> [flags] -- <check-cmd>... same as above, and also post the signed record to a brain (report_build) as a tamper-evident build attestation corral certify --adversarial --code <path> --goal "<text>" [--test <path>] -- <test cmd> grade a change's own tests: fire the adversarial pool on the brain, poll to a signed verdict corral certify --repo <dir> [--top n|--all] [--goals <file>] [--dry-run] [--swarm n] [-- <test cmd>] fan the --local audit out over a WHOLE repository: enumerate every source file with a paired test, rank them by churn x size, audit the top --top (default 25, --all for every one) through a bounded swarm, and print a repo report whose kill rate is over the AUDITED surface only, with every excluded file accounted for by reason — including the ones the bound left out each file's goal is DERIVED from its source by --derive-model; --goals <file> instead takes goals from a JSON map and makes no model call --dry-run stops after enumeration (no jail, no LLM calls) an explicit -- <test cmd> grades EVERY file, so it is refused when the scan spans more than one language (omit it and each file is graded with its own language's stock command) the report is NOT signed yet — that lands with the sealed repo statement corral certify verify <record-file> [--pubkey <hex>|--brain <url>] [--allow-unanchored] independently verify a --out (or report_build) record: the Ed25519 signature, the ledger's hash chain, and that the statement is bound to that exact ledger head — requires a trusted key via --pubkey or --brain (a record's own embedded public_key is never a trust anchor); prints "verified" and exits 0, or names the failing check on stderr and exits non-zero corral certify pubkey print the local signing pubkey (for --pubkey trust anchors) corral scorecard [--json] show the bug-catching scorecard (recall/precision per model×role, plus a C-PREC column: the test-critic role's execution-checked precision from criticscore adjudications); table by default, or the raw cells as indented JSON with --json corral criticscore list list execution-checked test-critic findings still awaiting human adjudication (requires CORRAL_BRAIN — no offline mode) corral criticscore show <id> print one finding in full (model, target test, evidence) corral criticscore confirm <id> record a human "confirmed" verdict — the finding was real corral criticscore refute <id> record a human "refuted" verdict — the finding was wrong (confirm/refute permanently override the pool's own auto-adjudication; this IS the human gate the critic-precision column measures) corral matrix list [--json] show the tests×mutants matrix (swarm slice 5): per-test execution-proven adequacy against a run's own mutant set, plus a safe-to-delete candidate list — populated only by runs opted in via certify --local --matrix (requires CORRAL_BRAIN — no offline mode) corral scans list|show [flags] read the scan ledger certify --repo --record writes: list shows recent scans, show <id> their per-file dispositions — including WHY a proven-gap count of 0 is 0 (writer failed / test unsound / tried and missed), which the bare number cannot say. show <id> --evidence prints the pool's own authored test, kept even when it proved nothing — that is the case worth reading. Local DuckDB file, no brain required: --db <path> (default $CORRALAI_SCANS_DB, else ~/.claude/corralai_scans.duckdb), --limit n, --json corral verify --attest <path> [flags] the checker for a certify --repo --attest statement: verifies its DSSE signature (against --pub or the local certify key, reporting who signed either way), and — opted in per flag — recomputes the pushed warehouse rows' hash from a --db and confirms a Rekor entry (--rekor-index, or read from --db) matches the envelope on disk. Prints check marks and one plain sentence per check; exits 1 only on a real mismatch. Different from "corral certify verify", which checks a corral certify BUILD record, a different artifact. flags: --db <dsn> --rekor-index <n> --pub <hex> corral seal [flags] the repo's CURRENT state as the union of still-valid verdicts, read from a certify --repo --push warehouse (many audits, one current state — not one scan's snapshot). Reads corral_seal (latest kill-rate-bearing row per path), creating the view if a writer never has. With --repo <dir>: judges each of the repo's churn x size top-N ("hot") files live (bytes unchanged since the audit), stale (changed since), never audited, unreadable, or unknown (the row recorded no validity key) — and prints "coverage: N of M hot files carry a live verdict", which counts the live ones only. Without --repo: the warehouse's latest verdict per path, no live/stale judgement. Read-only — never writes a row. flags: --db <dsn> (default $CORRALAI_SCANS_DB, else ~/.claude/corralai_scans.duckdb) --repo <dir> --top n (default 20) --json corral demo [flags] a complete audit of a tiny project, in ONE command: writes a small Go package with a five-clause password rule and a test that checks only two of them, then audits it with the real certify --local. Needs a Go toolchain (you installed corral with one) and a provider key — no venv, no database, no fixtures. The fastest honest answer to "what does this do?" flags: --writer-model/--mutant-model (required; corral has no default models) --critic-model --dir corral doctor [flags] [-- <test cmd>] check the environment BEFORE paying for a run: does the sandbox start, is your test command's toolchain reachable INSIDE it, has every grading seat been given a model (corral has no defaults) with a credential for it, and does the file you named have a test corral can pair with. Every check is free — no model is ever called — and they run in the order an audit would hit them, so the first FAIL is the first thing to fix. Exits non-zero if any failed. flags: --code <path> --test <path> (adds the pairing check) --jail <backend> (default: auto-detect) --mutant-model/--writer-model/--critic-model <name> It does NOT check two things that need a real seeded workspace: whether your suite passes on UNMUTATED code inside the sandbox (the most common way an audit dies), and whether a multi-file project needs --repo-dir. corral eval [flags] run the adversarial pool across the versioned eval corpus and print a soundness report (does the recall metric catch known gaps?) flags: --corpus <path> (default eval/corpus/manifest.json) --iterations <n> (default 1) --only <id,id,...> --brain <url> (or $CORRAL_BRAIN) --progress <path> (default eval/.eval-progress.json) corral --version print the build version and exit corral -h print this help and exit
Configuration is entirely environment variables — see CORRALAI_ADDR,CORRALAI_DB, and the rest of the // Env: block at the top of this binary'smain.go (also reproduced in the generated CLI reference).corral certify --local flags
Section titled “corral certify --local flags”Usage of certify --local: -bind-dir value extra repo-relative dependency dir to mount read-only into the jail instead of copying it into the workspace (repeatable; node_modules/vendor/.venv/venv/.bundle are auto-detected) — --repo-dir mode only -code string path of the code under review (required) -commit string commit sha (default: git rev-parse HEAD, else "local") -critic-model string model for the test-critic role, which must differ from the writer's; "off" disables the critic entirely (it is advisory and never gates the verdict, so a single-vendor run with only one usable model can drop it). No default -goal string the correctness/security goal the code must satisfy (required) -jail string sandbox backend: bwrap|container (Linux), sandbox-exec (macOS) (default: auto-detect for this OS; "none" is not supported — --local always sandboxes). "container" needs CORRALAI_EXEC_IMAGE set to a toolchain image, e.g. CORRALAI_EXEC_IMAGE=python:3.12-bookworm -lang string source language (default: inferred from --code extension) -local run the adversarial pool in-process (this mode) -local-endpoint value place a LOCAL seat on a specific ollama daemon, as <role>=<url> (repeatable; e.g. test-writer=http://localhost:11436). A daemon is pinned to a GPU by its own environment (HIP_VISIBLE_DEVICES / CUDA_VISIBLE_DEVICES), so this is how two models occupy two cards at once — corral selects the DAEMON, never the device. Without it every local seat shares OLLAMA_URL, one card and one VRAM budget. Roles: mutant-generator, test-writer, test-critic, mutant-generator-shadow, test-writer-shadow. An unknown role, a duplicate role, a non-absolute url, or an endpoint on a seat holding a CLOUD model is refused rather than ignored -matrix opt into the tests×mutants matrix: after the primary pass, re-score EVERY dev test ALONE against the run's mutants — a per-test adequacy readout + a delete-candidate list, instead of one dev-suite-wide number. COSTLY: T tests × M mutants extra jail runs (T×M, on top of the primary pass), so leave off by default on a big suite -max-shards int max mutant-generator seats fanned out across the file's functions (0 = 8). Bounds PARALLELISM only — every function is probed regardless; --n-mutants is the PER-SHARD budget -mutant-model string model for the mutant-generator role — REQUIRED, corral has no default models -mutants string REPLAY a recorded mutant set (see --record-mutants) instead of generating one: --code is graded against exactly the mutants recorded for it, and no mutant-generator model call is made. Refused (exit 2) if the file is absent from the set or its bytes have changed since it was recorded — a mutant is a single-point edit of specific bytes, and re-applying it to different ones grades an exam nobody wrote. Reads a corral-mutants-2 document, or an older corral-mutants-1 one, whose whole-file mutants still replay byte-for-byte. -n-mutants --n-mutants 20 PER-SHARD seeded-violation mutant budget (default 5) — this is NOT the run's total: total mutants scored scale with --max-shards (default 8) shards, and DOUBLE again if the shadow challenger is on (default). E.g. the default 5 with the default 8 shards means up to ~40 primary + ~40 shadow = ~80 full dev-suite jail executions, not 5 — --n-mutants 20 means roughly ~320 -no-bind-deps copy dependency dirs into the jail workspace instead of bind-mounting them read-only (the pre-bind behavior; subject to the workspace size cap) -out corral certify verify <file> --pubkey <hex> --allow-unanchored also write the signed verdict as a self-contained record file, re-verifiable offline with corral certify verify <file> --pubkey <hex> --allow-unanchored -poll duration how long to wait between drive iterations when nothing is claimable (default 2s) -quiet suppress the live progress echo on stderr (the verdict, --out and --record are unaffected) -record string write a replayable tape of the run (the pool's reasoning beats, task lifecycle, and findings) to this JSON file — the same {events:[…]} shape the corralai.dev cockpit replays -record-mutants string write the mutants this run actually GRADED to this file, as a replayable corral-mutants-2 document — each mutant its SEARCH/REPLACE hunk, tied to the sha256 of the source it is an edit of. Mutants are authored by a model, so an ordinary run re-draws the exam every time; pin the set and a later comparison measures the thing you changed instead of generator variance. Written even when the verdict is needs-review. A v2 document re-recorded from a --mutants replay of an older corral-mutants-1 set contains that set's WHOLE-FILE entries, not hunks — the run graded what was recorded, and re-recording it does not manufacture anchors it never had -record-stream tail -f stream each run event as newline-delimited JSON to this file AS IT HAPPENS — the same events --record collects into a tape at the end, so a watcher (tail -f, the cockpit) can follow a run in flight instead of waiting hours for it to finish. Independent of --record: either, both, or neither -repo string repository (default: git remote.origin.url, else "local") -repo-dir -- audit --code IN THE CONTEXT of this cloned repo/package: the whole tree is seeded into the jail, the file is mutated in place, and the project's OWN test command (given after --) grades it — so real multi-file projects with package imports work (--code/--test are repo-relative) -shadow-model string challenger model that attacks every region a SECOND time for a region-controlled head-to-head. OFF unless named. Recorded for comparison — NEVER gates the verdict -shadow-writer-model string challenger WRITER model that authors a second suite against the SAME mutant set for a mutant-controlled head-to-head. OFF unless named. Recorded for correlation — NEVER gates the verdict -swarm int max concurrent audit workers (0 = auto-size to this host's cores). The BUDGET clamp: independent role tasks run in parallel up to this bound, so a big audit swarms without melting the box -test string path of the dev's test (default: the sibling test of --code) -test-timeout duration hard cap on a SINGLE test-suite run in the jail (0 = auto: derived from the healthy suite's own runtime, so a mutant that makes the suite hang is killed fast instead of eating the whole --timeout). Raise it only if your suite legitimately runs long -timeout duration give up if the run makes no progress for this long (not a hard wall-clock cap — a single slow LLM call can overshoot it) (default 10m0s) -writer-mode per-survivor how the test-writer attacks this file's survivors: per-survivor (the default) makes ONE call per survivor — each carrying the file once as a cacheable shared prefix plus that survivor's diff, each repaired on its own budget and each PROVEN ALONE against its own mutant — or `batched`, the original shape: one call carrying every survivor, one repair budget, one proof pass over all of them. Nothing measured changes between them (a survivor is proven iff an authored test kills it alone and passes on the original, either way); what changes is that one unbuildable test no longer spends the whole file's retries and takes every other survivor down with it. Each survivor's proof in per-survivor mode runs its OWN compliant baseline (a compliant pass plus a canary, per seat), so a file with N survivors pays N baselines where batched paid one: on a repo whose suite takes a minute, prefer --writer-mode batched or expect N baselines' worth of wall clock. -writer-model string model for the test-writer role — REQUIRED, corral has no default modelscorral certify --repo flags
Section titled “corral certify --repo flags”Usage of certify --repo: -all audit every candidate, ignoring --top -attest string write the scan's verdict as an in-toto Statement to this file — the receipt a reviewer can verify without trusting the run that produced it. Consumed by GitHub's attestation API (actions/attest), which signs it keylessly through the workflow's own OIDC identity, so the signature chains to the repository and workflow rather than to a key that lived on an ephemeral runner. Carries every file's kill rate, survivors and proven gaps WITH the honesty flags that say what a zero means, the thresholds it was judged against, and the models in each role. When a local signing key is configured (CORRALAI_CERTIFY_KEY_FILE), the same statement is ALSO signed into a DSSE envelope written beside this file as <path>.dsse.json — this plain file is unchanged either way, so actions/attest keeps working exactly as it does today; --transparency uploads the envelope, never this file -commit string commit SHA the report is bound to -critic-model string model for the test-critic role, which must differ from the writer's; "off" disables the critic entirely (it is advisory and never gates the verdict, so a single-vendor run with only one usable model can drop it). No default -derive-model string model that derives a goal per file when --goals is not given — REQUIRED unless --goals is supplied; corral has no default models -diff-base string bound the scan to files changed since this git ref, instead of ranking + --top. In a PR the diff IS the bound: ranking and --top do not apply on this path -dry-run enumerate and emit jobs, then stop — no audits run -goals string JSON file mapping repo-relative paths to goals (default: derive a goal per file) -json with --dry-run, emit the repository's audit surface as JSON instead of the human report: per-language counts, every auditable file with its inferred test pairing, and the machine-stable exclusion tally. Needs no key, no jail and no money — it is the free inventory a UI or a tenant's own tooling can consume instead of scraping stdout -local-endpoint value place a LOCAL seat on a specific ollama daemon, as <role>=<url> (repeatable; e.g. mutant-generator=http://localhost:11436). A daemon is pinned to a GPU by its own environment, so this is how two models occupy two cards at once — corral selects the DAEMON, never the device. Without it every local seat shares OLLAMA_URL, one card and one VRAM budget -max-proven-missed string fail the scan (exit 1) if ANY audited file has MORE than this many proven-missed gaps — survivors the pool then killed with a test it WROTE and RAN. Opt-in and unset by default. Prefer this to --min-kill-rate as a merge gate: a kill rate is a proportion of freshly generated mutants and moves between runs on unchanged code, so a threshold set near a healthy value flaps red and gets switched off. A proven-missed gap is a specific demonstrated bug the suite does not catch, established by execution, and 0 means the pool proved nothing — not that it sampled well -min-kill-rate string fail the scan (exit 1) if ANY audited file's kill rate is below this value (0.0-1.0 inclusive; a minimum, so a file exactly at the threshold passes). Opt-in: unset by default, so exit codes are unchanged unless this is given. Applies PER FILE, not to the aggregate — a well-tested file must not mask a weak one -mutant-model string model for the mutant-generator role — REQUIRED, corral has no default models -mutants string REPLAY a recorded mutant set (see --record-mutants) instead of generating one: every audited file is graded against exactly the mutants in this file, and not one generator model call is made. Mutants are authored by a model, so an ordinary run re-draws the exam every time and two runs of the same audit are not two samples of one measurement — pin the set and a change to anything ELSE becomes measurable. Every selected file must appear in the set with the SAME bytes it was recorded from; a missing file or a changed one is refused (exit 2) up front, never half-replayed. Reads a corral-mutants-2 document, or an older corral-mutants-1 one, whose whole-file mutants still replay byte-for-byte. -no-goal-cache skip the goal cache — every candidate is re-derived even when a PRIOR scan already derived a goal for the exact same bytes, model and prompt revision. Re-buys a model call per file that a content-addressed cache would otherwise have served for free; use this to isolate goal-derivation variance from a comparison, or on a scan whose operator does not want a goal receipt kept in the ledger at all. The cache lives in the same ledger --record-db names, independent of --record itself -no-selection-cache skip the selection cache — the ONE instrumented coverage run always executes, even when a PRIOR scan already ran the identical instrumented command over a byte-identical tree. Re-buys a full suite run (the single most expensive measurement a scan makes outside model calls) that a content-addressed cache would otherwise have served for free; use this to isolate selection variance from a comparison, or when the operator does not trust the tree to be unchanged. The cache lives in the same ledger --record-db names, and (like the goal cache) is consulted independent of --record itself; only WRITING a fresh hit requires --record, since a scan_id has to exist to write one against -owner string owning account for the scan (tenant identifier) (default "local") -preflight run the project's test suite once with coverage instrumentation and report which source files it never executes. One extra suite run; reports coverage-grade evidence, not proof -push md:<db> append this scan's per-file verdicts to a DuckDB you own — a path, or md:<db> for MotherDuck (which reads motherduck_token from the environment; the database is created on first push if it does not already exist — a MotherDuck SHARE is a read target and cannot be pushed to). corral has no hosted tier and keeps nothing: the warehouse is yours, and any DuckDB works, so this is a destination rather than a lock-in. Append-only. Every row carries the ledger's scan id (0 when --record was not given), and — traceable only with --attest — the sha256 of the signed statement it came from, so a row can be checked against something a third party can verify; without --attest, statement_sha256 is honestly empty rather than fabricated; and with --attest, a statement that FAILS to write withholds the push too, since a row that cannot name the statement it came from is not written. It answers what one pull request cannot — a single kill rate is a sample, and the same unchanged diff has scored 0.85 and 0.90; forty of them are a distribution -push-source with --push, also send the SOURCE BYTES corral holds to your warehouse: the pool's authored test, and the full verdict JSON. Off by default because those bytes are derived from — and quote — your audited code; without this the pushed rows carry numbers, hashes, reasons and model names, and no source leaves the box. Mutant code is NOT carried, by either setting: corral does not keep mutant source at rest, so the corral_mutants.code column exists and is always NULL until something records it. The scan row records which setting was used, so the custody question is answerable from the table rather than from whoever remembers the argv -record certify --local record every file this scan audited or rejected, and why, into the DuckDB scan ledger (default: off). A BOOL here — unlike certify --local's --record, which takes a tape PATH — see --record-db for where the ledger goes. A recording failure never changes the scan's verdict or exit code -record-db string path to the scan ledger (default: $CORRALAI_SCANS_DB, else ~/.claude/corralai_scans.duckdb) -record-mutants string write the mutants this scan actually GRADED to this file, as a replayable corral-mutants-2 document — one entry per audited file, each mutant its SEARCH/REPLACE hunk, tied to the sha256 of the source it was derived from. Written even when the scan's gates fail: a red verdict is still a recorded exam. A v2 document re-recorded from a --mutants replay of an older corral-mutants-1 set contains that set's WHOLE-FILE entries, not hunks — the run graded what was recorded, and re-recording it does not manufacture anchors it never had -repo string path of the repository to audit (required) -scope-tests REMOVED — see --whole-suite. Selection by coverage evidence is now the default -shadow-model string challenger model that attacks every region a SECOND time. OFF unless named. Recorded for comparison — NEVER gates the verdict -shadow-writer-model string CHALLENGER test-writer: a second writer attacks the SAME survivors as the primary, so the two seats' misses can be compared (Jaccard over survivors, Cohen's kappa). Measurement only — it NEVER gates the verdict. OFF unless named. Recording the per-mutant outcomes additionally needs --mutant-attempts-db -substrate string where the audit runs: jail (bwrap) or workspace (mutate --repo in place; the caller IS the isolation boundary, e.g. an ephemeral CI runner) (default "jail") -swarm int max concurrent audit workers (0 = auto-size to this host's cores); on --substrate workspace it also sizes the private trees that score one file's mutants at once (budget/4, min 1), so --swarm 4 is one tree -tests string JSON file mapping repo-relative SOURCE paths to their test files, consulted before filename convention. Convention cannot pair a project that names tests after behaviour rather than after source files (expressjs/express: lib/response.js is tested by test/res.send.js, res.json.js …), and it can pair the WRONG file (psf/requests pairs adapters.py to an 8-line test_adapters.py while its real coverage is in a 108KB test_requests.py). A mapping to a file that does not exist is refused, never silently fallen back to convention -timeout certify --local per-file budget: give up on a single file's run if it makes no progress for this long (not a hard wall-clock cap — a single slow LLM call can overshoot it). Same default and semantics as certify --local's --timeout; raise it for a large file that needs more room to converge (default 10m0s) -top int audit only the N highest-ranked candidates (0 or --all = every candidate). Bounded by default: a whole-repo audit runs a full herd per file, so an unbounded first scan on a large repo costs hours and real money. The DEFAULT bound does not apply with --goals — a hand-written goals map has already chosen the surface — but an explicit --top does (default 25) -transparency also upload the --attest statement — SIGNED into a DSSE envelope with the local certify key — to Sigstore's public Rekor transparency log (requires --attest — there is nothing to log without one; and a usable local signing key, CORRALAI_CERTIFY_KEY_FILE — refused with exit 2 naming it if none is configured, since an unsigned entry in a public log is worthless and this never mints a fresh key just to have one). THE ENTRY IS PUBLIC AND PERMANENT: once logged it cannot be removed or edited, by anyone, including you. It carries the same statement --attest writes — the repo URL, the audited commit, per-file paths, kill rates and survivor/proven-gap counts, and the models in each role — and never the audited source itself. Fails OPEN for the UPLOAD itself: an unreachable log or a rejected entry prints one line and leaves the scan's own verdict and exit code untouched; the local statement, envelope and ledger are unaffected either way. Prints the log index and entry UUID on success, and records both in the scan ledger and, with --push, the warehouse -whole-suite grade every mutant against the project's WHOLE suite instead of the tests that demonstrably execute each file (the default, from one instrumented run per scan). Costs O(mutants x whole-suite runtime) per file and answers a different question — 'did ANY test catch it' rather than 'do this file's tests test it'. The verdict records which was used -writer-mode per-survivor how the test-writer attacks a file's survivors: per-survivor (the default) makes ONE call per survivor — each carrying the file once as a cacheable shared prefix plus that survivor's diff, each repaired on its own budget and each PROVEN ALONE against its own mutant — or `batched`, the original shape: one call carrying every survivor, one repair budget for the file, one proof pass over all of them. Nothing measured changes between them (a survivor is proven iff an authored test kills it alone and passes on the original, either way); what changes is that one unbuildable test no longer spends the whole file's retries and takes every other survivor down with it. The verdict, the report line, the ledger and the attestation all record which mode earned the numbers. Each survivor's proof in per-survivor mode runs its OWN compliant baseline (a compliant pass plus a canary, per seat), so a file with N survivors pays N baselines where batched paid one: on a repo whose suite takes a minute, prefer --writer-mode batched or expect N baselines' worth of wall clock. -writer-model string model for the test-writer role — REQUIRED, corral has no default modelscorral certify verify flags
Section titled “corral certify verify flags”Usage of certify verify: -allow-unanchored accept a signed-but-not-publicly-witnessed record (weaker: no third-party transparency guarantee) -brain string fetch the public key from this brain's /api/certify/pubkey -pubkey string hex-encoded Ed25519 public key to verify against -rekor-url string Rekor instance to verify the inclusion proof against (default $CORRALAI_REKOR_URL or https://rekor.sigstore.dev)corral scans push flags
Section titled “corral scans push flags”usage: corral scans push --db <dsn> [--scan <id> | --all] [--since YYYY-MM-DD] [--dry-run]
Reads from the SAME local ledger `corral scans list` reads (default:$CORRALAI_SCANS_DB, else ~/.claude/corralai_scans.duckdb) — set that env var topush from a non-default ledger.
Pushes scans ALREADY in the local ledger (`certify --repo --record`) to awarehouse — the verb for someone who recorded for weeks before deciding theywanted a warehouse, so they do not have to re-run every audit to get there.
The warehouse tables are APPEND-ONLY: pushing the same scan id twice adds itsrows a second time rather than overwriting the first. --dry-run reports therows a push would ADD, which is the same count whether or not this scan hasbeen pushed before.
Never carries source (the authored test, mutant code, the verdict blob) —this command has no --push-source flag, so BlankUnpushedSource withholds itunconditionally, even for a scan whose original run pushed source itself. -all push every recorded scan (optionally narrowed by --since) -db string the warehouse to push to — a DuckDB path, or md:<database> for MotherDuck (required) -dry-run print exactly what would be pushed and touch nothing — neither the ledger nor the target warehouse -scan string push only this one scan id (see corral scans list) -since string with --all, push only scans recorded on or after this date (YYYY-MM-DD)Environment variables
Section titled “Environment variables”CORRALAI_ADDR listen address (default 127.0.0.1:9019)CORRALAI_DB coordination SQLite path (default ~/.claude/corralai_coord.sqlite3)CORRALAI_MEMORY_DB memory DuckDB path (default ~/.claude/corralai_memory.duckdb)CORRALAI_RECORDINGS_DB recordings DuckDB path for scrubbed replay exports (default ~/.claude/corralai_recordings.duckdb)CORRALAI_MEMORY_DIR where new memory entries are written (default ~/.claude/projects/default/memory)CORRALAI_PROJECT_TIERS optional path->tier rules "substr=tier,substr=tier"; front-matter project: wins, else "default"CORRALAI_OIDC_ISSUER OIDC issuer URL (any OIDC provider: Keycloak, Auth0, Okta, Dex, Authentik, …); empty => AUTH DISABLED (dev)CORRALAI_ALLOW_INSECURE set "1" to allow auth-disabled startup on a non-loopback CORRALAI_ADDR (refused otherwise, H-3)CORRALAI_OIDC_AUDIENCE expected token aud (the client_id)CORRALAI_OIDC_CLIENTS extra trusted clients "issuer|aud,issuer|aud"CORRALAI_ALLOWED_PRINCIPALS day-0 SEED of member emails (DB is canonical after; empty => any authenticated)CORRALAI_PRINCIPALS_DB role/allowlist SQLite path (default ~/.claude/corralai_principals.sqlite3)CORRALAI_MEMORY_OWNERS comma list of emails allowed to read/write memory (empty => any authorized)CORRALAI_ALLOWED_HOSTS comma list of accepted Host headers (default: the brain's domains + localhost)CORRALAI_CLIENT_IP_HEADER trusted real-client-IP header for rate limiting (e.g. CF-Connecting-IP); empty => RemoteAddrCORRALAI_RATELIMIT_IP_PER_MIN / _IP_BURST per-IP rate limit (default 300/min, burst 100)CORRALAI_RATELIMIT_USER_PER_MIN / _USER_BURST per-principal rate limit (default 600/min, burst 200)CORRALAI_MAX_BODY_BYTES max request body size (default 1 MiB)CORRALAI_TLS_CERT / _KEY serve HTTPS with these PEM files (built-in TLS, no proxy needed)CORRALAI_TLS_AUTOCERT_DOMAINS comma list => auto Let's Encrypt certs (needs public reachability)CORRALAI_TLS_AUTOCERT_CACHE cert cache dir (default ~/.cache/corralai-autocert)CORRALAI_ADMIN_PRINCIPALS day-0 SEED of superuser emails (DB is canonical after; `corral createsuperuser` adds more)CORRALAI_GATEWAY_DB MCP-gateway registry SQLite path (default ~/.claude/corralai_gateway.sqlite3)CORRALAI_ARTIFACTS_DB fleet skill/hook sync SQLite path (default ~/.claude/corralai_artifacts.sqlite3)CORRALAI_GATEWAY_ALLOWED_HOSTS hosts the gateway may dial despite the SSRF block (private/internal targets); empty => block all private/loopbackCORRALAI_MOTHERDUCK fleet-sync target: "md:<db>" or a .duckdb path; empty => sync offCORRALAI_MOTHERDUCK_TOKEN MotherDuck token (exported as motherduck_token for md: attach)CORRALAI_BRAIN_ID tag for this brain's rows (default hostname)CORRALAI_SYNC_INTERVAL fleet sync interval, seconds (default 30)CORRALAI_FLEET_RETENTION_DISABLE set "1" to disable the retention/compaction cycle entirelyCORRALAI_FLEET_RETENTION_DAYS TTL window in days (default 90; 0 = TTL off, compaction still runs)CORRALAI_FLEET_RETENTION_INTERVAL_SEC how often (seconds) to run the retention cycle (default 3600)CORRALAI_GIT_TOKEN GitHub PAT for repo-work missions (clone + PR); empty => repo engine disabled unless CORRALAI_REPO_ENABLE=1CORRALAI_GITHUB_API GitHub API base URL (default https://api.github.com)CORRALAI_REPO_WORKSPACE root dir for per-mission working copies (default $TMPDIR/corral-repos)CORRALAI_REPO_ENABLE set "1" to enable the repo engine even without a token (anonymous / GitHub Apps token flow)CORRALAI_REVIEW_POLL_SEC how often (seconds) the brain polls open PRs for CHANGES_REQUESTED reviews (default 60)CORRALAI_BRAIN_KEY base64-encoded Ed25519 seed (32 bytes) for cross-swarm brain identity; takes priority over key fileCORRALAI_BRAIN_KEY_FILE path to persist the brain key seed (default ~/.claude/corralai_brain_key); created 0600 on first runCORRALAI_BRAIN_PEERS optional allowlist "brain_id:pubB64" entries (comma or newline separated); empty => TOFU modeCORRALAI_LEARN_DB learning-loop proposals SQLite path (default ~/.claude/corralai_learn.sqlite3)CORRALAI_LEARN_SWEEP_SECONDS how often (seconds) the learn sweep clusters findings/lessons into proposals (default 60)CORRALAI_BUILD_DB `corral certify` signed build-record ledger DuckDB path (default ~/.claude/corralai_build.duckdb)CORRALAI_CERTIFY_KEY hex-encoded Ed25519 seed (32 bytes) `corral certify` build attestations are signed with; takes priority over key fileCORRALAI_CERTIFY_KEY_FILE path to persist the certify signing key seed (default ~/.claude/corralai_certify_key); created 0600 on first runCORRALAI_BRAIN_TOKEN `corral certify`'s bearer token to authenticate to a brain (via `corral secret set`); distinct from CORRALAI_BRAIN_KEY above (that's an Ed25519 IDENTITY SEED, not a bearer token — do not reuse it)CORRALAI_REKOR_URL Sigstore Rekor instance report_build anchors signed build attestations to (default https://rekor.sigstore.dev); `corral certify verify` checks the same default unless --rekor-url overrides itCORRALAI_GATE_POLICIES repo merge gate: ";"-separated policies "repo=owner/name,base=main,net=false,timeout=600,cmd=go test ./..."; cmd= MUST be the last field — everything after it is the command verbatim (commas allowed, never split) so "cmd=go test -run A,B ./..." isn't silently truncated; timeout= is seconds, defaults to gate.DefaultGateTimeout (600s) when omitted; empty => the repo gate is OFF (no poller starts); GitHub-only for v1CORRALAI_GATE_DB repo gate dedupe/index store DuckDB path (default ~/.claude/corralai_gate.duckdb)CORRALAI_GATE_POLL_SECONDS how often (seconds) the repo gate polls covered repos for new PR heads (default 120)CORRALAI_GATE_EXEC_BACKEND / _EXEC_UNSAFE_HOST same jail backend used by the independent verify-gate (see below); the repo gate reuses it — a missing backend disables the repo gate too, loudly, never unsandboxedCORRALAI_CONTROL_GATE control gate: ";"-separated "repo=owner/name,owner=<principal>,lang=go,base=main" — owner= MUST equal the control owner's authenticated principal (the identity they author controls under), else the gate finds no vetted controls — runs the owner's VETTED tests against PR heads, posts corral/control-gateCORRALAI_CONTROL_GATE_SPEC_DB control-gate vetted-tests store (default ~/.claude/corralai_control_spec.duckdb)CORRALAI_CONTROL_GATE_DB control-gate dedupe/index store (default ~/.claude/corralai_control_gate.duckdb)CORRALAI_CONTROL_GATE_POLL_SECONDS how often the control gate polls for new PR heads (default 120)CORRALAI_BUGCATCH_DB adversarial pool's bug-catching scorecard store DuckDB path (default ~/.claude/corralai_bugcatch.duckdb); also read by `corral scorecard`CORRALAI_CRITICSCORE_DB adversarial pool's critic-accuracy store DuckDB path (default ~/.claude/corralai_criticscore.duckdb); the scorecard's C-PREC column and `corral criticscore` read it over the API — see CORRAL_BRAIN below