crashtest docs

CLI Reference

Every verb, every flag, nothing else. This page is hand-kept to crashtest --help - when they disagree, run --help (version-suffixed output) and report the page. The docs fiction scan and the web docs consistency probe hold this page to that rule.

crashtest init [--force]

Scaffold the run root: labs/crashledger.json + labs/hardening.md stubs, plus packs/public / packs/local directories. First run also appends packs/local/ to .gitignore (private packs stay on your machine; packs/public/ is tracked and sharable). Re-running without --force refuses to stomp an existing baseline.

crashtest run

Attack the target declared in crashtest.config.js. Writes labs/crashledger.json + labs/hardening.md on success - that is how a baseline is cut. Flags:

Flag What it does
--config <path> Target a config other than ./crashtest.config.js.
--allow-vacuous Configless root: one honest vacuous-run line + exit 0, for pre-handler shells that adopt the pinned install before they have handlers. WITHOUT the flag, a missing config stays a hard exit 2 - the default never silently greens.
--json Append the machine run blob to stdout (last line).
--module-plan Dry-run: which attack ids WOULD fire (exit 0 always). NEEDS-ARMING rows mean a pack wants moduleCtx['<key>'] in your config; at run time they refuse-skip, never false-positive.
--expect-baseline <path> Diff against a given ledger WITHOUT touching labs/ (read-only CI/hosted mode; exit rules unchanged).
--out-dir <dir> ALSO write run-blob.json + crashledger.json + hardening.md copies into dir (artifact fan-out; the repo’s labs/ rules are untouched).
--lint-determinism The determinism grep INSTEAD of the campaign (same lane as the lint-determinism verb).
--lint-packs The packstruct lint INSTEAD of the campaign (same lane as the lint-packs verb).

crashtest packs

List discovered packs (public + local), env claims shown, unmet lines rendered. Flags:

Flag What it does
--config <path> Honor the config’s packs: knob.
--json Machine inventory (versions, armedByKey, npm pkg) - last stdout line.
--allow-vacuous Configless root: honest vacuous line + empty listing, exit 0 (a CI row can pass the flag to both verbs).

crashtest packs add <name> [--public]

Scaffold a fresh pack. Local + gitignored by default; --public makes it tracked and sharable. A fresh pack’s manifest carries the placeholder description TODO: one line on what <name> attacks - write a real one before shipping the pack.

crashtest lint-determinism [--config <path>] [dirs...]

Grep the DECLARED sources (config scenarioDirs + packs roots, or explicit dirs) for wall-clock / unseeded-randomness tokens (Date.now, new Date(, Math.random). Findings exit 2 naming file:line. The determinism law, enforced at the door: same commit -> same findings.

crashtest lint-packs [--deep] [--json] [--against <lib>] [dir]

Lint the packs root against the packstruct packs spec (schemaVersion: 1, name/dir match, entry ships, dotted version). Opt-in passthrough to the packstruct binary THIS REPO has installed (node_modules/.bin, then PATH) - never downloads one. Default dir is the packs root, NEVER packs/public (packstruct’s contract root is <dir>/ with its public/local children). packstruct not installed where the flag/verb is explicitly asked = exit 2 naming the fix: npm i -D packstruct@<exact>.

crashtest preset <name> [--root <dir>]

Generate a starter config for an agent-builder export (lovable, bolt, replit) from what is ACTUALLY in the repo - never a guess. Usage without a name prints the usage line.

crashtest --version

Print the single-string version. -v and version are synonyms.

Exit codes (the CI contract)

Code Meaning
0 Baseline held (nothing new weak, nothing old broke).
1 NEW EXPLOITED finding, or a REFUSED -> EXPLOITED regression.
2 Config problem (missing/bad config or baseline) - the run is wrong, not your code.

Full semantics in Exit Rules.