CLI reference

Every chainsaw command, subcommand, and flag — 148 commands generated from the CLI itself.

Complete reference for the chainsaw CLI: 148 commands across 7 groups, with every flag, default, and exit code.

These pages are generated from the CLI binary itself, so they match chainsaw --help exactly. If a command exists, it is here; if the text here is wrong, --help is wrong the same way.

New to Chainsaw? Start with Getting Started — this section is a reference, not a tutorial.

Command index

Target & scan

CommandSubcommandsWhat it does
chainsaw pr-scan—Diff manifest/lockfile changes and flag added or upgraded dependencies
chainsaw sbom5Software Bill of Materials commands
chainsaw scan—Scan packages for vulnerabilities and supply-chain conditions
chainsaw scan-actions—Scan GitHub Actions workflows for supply-chain risk
chainsaw scan-remote—Upload a single lockfile to the server and stream the aggregated intelligence report
chainsaw scan-repo—Scan a repo tree for Chainsaw-bypass config files
chainsaw why—Explain why a package install was blocked

Policy & enforcement

CommandSubcommandsWhat it does
chainsaw admission3K8s admission webhook helpers (shadow-mode soak gate, etc)
chainsaw policy17Manage release policies
chainsaw risk-weights3Show, preview, and apply per-signal risk-weight overrides

Intelligence

CommandSubcommandsWhat it does
chainsaw affected—Find which repos, clients, and SBOMs contain a package or CVE
chainsaw deps1Dependency commands
chainsaw intel4Query the v1 risk-intelligence API (package, scan, signals, health)
chainsaw pkg3Package discovery and inspection commands
chainsaw verify—Verify a package’s provenance attestation chain

Guard (install-time)

CommandSubcommandsWhat it does
chainsaw cargo—Run cargo through Chainsaw — refuse malicious/typosquatted crates at install time
chainsaw cargo-credentials—Cargo credential-provider helper (store / clear / status; cargo itself invokes the binary via –cargo-plugin)
chainsaw gem—Run gem through Chainsaw — refuse malicious/typosquatted gems at install time
chainsaw go—Run go through Chainsaw — refuse malicious/typosquatted modules at go get
chainsaw guard4Install-path guard maintenance
chainsaw install-hook—Wire chainsaw into a package manager
chainsaw npm—Run npm through Chainsaw — refuse malicious/typosquatted packages at install time
chainsaw pip—Run pip through Chainsaw — refuse malicious/typosquatted packages at install time
chainsaw uninstall-hook—Remove the chainsaw-managed block from a package manager

Audit & findings

CommandSubcommandsWhat it does
chainsaw audit2Audit event commands
chainsaw exception4Manage policy exceptions (scoped allow-rules with expiry)
chainsaw finding9Manage security findings (triage lifecycle: ack / snooze / resolve / suppress / reopen)
chainsaw report4Cross-org reports derived from install events

Config & auth

CommandSubcommandsWhat it does
chainsaw auth9Authentication commands
chainsaw bundle1Manage the offline intelligence bundle
chainsaw codeowners2Sync and query GitHub CODEOWNERS mappings
chainsaw introduce—Show how people use Chain305 — personas, workflows, glossary, examples
chainsaw onboard—Record your persona to tailor onboarding (twin of the MCP chainsaw_onboard tool)
chainsaw onboarding1Inspect onboarding state (twin of the MCP chainsaw_onboarding_state tool)
chainsaw org1Manage the active organization (delete with safety gate)
chainsaw repo5Manage upstream proxies and registries
chainsaw setup—Interactive first-time setup wizard
chainsaw status—Show server, org, and authentication status
chainsaw team4Manage repo→team ownership mappings
chainsaw token4Manage API tokens (PATs and AI-agent credentials)
chainsaw undo—Roll back the most recent agent action (or a specific action by id)

Debug & diagnostics

CommandSubcommandsWhat it does
chainsaw coverage10Inspect install-coverage measurements (opt-in)
chainsaw doctor1Diagnose local package-manager wiring and server-install health
chainsaw features—Show local edition capabilities and server plan entitlements
chainsaw telemetry5Inspect or control local analytics
chainsaw version—Print version information

Global flags

Every command accepts these. They are persistent flags on the root command, so they work in any position — except --server, which must precede the subcommand (chainsaw --server <url> policy list).

FlagTypeDefaultDescription
--formatstringtableResult format: table|json (–json is sugar for –format=json)
--jsonbool—Output JSON instead of human-readable text (alias for –format=json)
--no-colorbool—Disable colored output
--orgstring—Org ID for local use only (status, ‘org delete’, SBOM metadata); never sent to the server
--serverstring—Chain305 server URL (overrides the saved config)
--tokenstring—Auth token (overrides config)
-o, --outputstring—Write results to this file instead of stdout (logs/progress stay on stderr)
-q, --quietbool—Suppress progress/chatter (results and block reasons are still emitted)
-v, --verbosebool—Emit extra diagnostic detail to stderr

--output writes the result to a file; logs and progress stay on stderr. It is only accepted together with a machine-readable format (--json or --format=json) — the human table renderers write to stdout directly, so pairing them with --output would silently produce an empty file. Eleven commands declare their own --format or --output with a wider vocabulary (csv, ndjson, yaml, sarif, cyclonedx, spdx); on those, the command’s own flag wins and this restriction does not apply.

--quiet and --verbose change chatter only. Neither ever suppresses a block reason or changes an exit code.

-h / --help works on every command and is not listed in the per-command tables below. The guard wrappers are the one exception: chainsaw npm --help forwards to npm, so use chainsaw help npm to read Chainsaw’s own text.

Exit codes

A policy block is an expected outcome, not a crash, so it is distinguishable from an operational failure by exit code. Scripts that gate on enforcement should test for 1 specifically rather than for any non-zero status.

CodeNameMeaning
0ExitOKSuccess.
1ExitBlockedThe expected enforcement outcome: a policy block, a failed gate, or findings at or above the configured threshold. Stays 1 so existing block-gating scripts keep working. Three commands also return 1 for a softer command-specific outcome — doctor --strict (egress probe inconclusive), doctor --upgrade-check (warnings) and policy lint (warnings only) — so on those, check the command’s --help before reading 1 as a block.
2ExitOpErrorOperational failure: network, server, IO, or internal error. Distinct from a block so CI can tell infrastructure trouble apart from enforcement. Two commands overload it: doctor --upgrade-check returns 2 for breaking changes and policy lint returns 2 for lint errors, so on those a 2 is a finding rather than a failure. Check the command’s --help.
3ExitConfigAuthConfiguration or authentication problem (no server configured, unauthorized, forbidden).
4ExitUsageThe invocation itself was wrong: unknown command, unknown flag, or bad argument shape.

Command-specific outcomes start at 10 so they never collide with the shared buckets. They are NOT globally unique: 10 and 30 each have more than one owner, so a given number can mean different things on different commands. Always read the exit codes in the command’s own --help before wiring a CI gate.

CodeNameMeaning
10ExitSoakNotClearedadmission soak clear ran successfully but the shadow-mode soak gate is not yet cleared. 10 is not unique — see the two rows below for what it means on other commands.
10pr-scanpr-scan found one or more warning-level findings. With --strict these escalate to 20 instead.
10scan-repo, doctor --strictscan-repo found at least one bypass file, or doctor --strict found drift (project config, env override, or a lockfile pointing at a public registry). The two share the number deliberately so one CI step combining both gets a predictable non-zero.
11ExitIntelBlockintel scan found at least one Quarantine or Replace node — the strongest block the command emits. Weaker Warn/UpgradeAvailable trees still exit 1.
12policy lint, policy preflightpolicy lint or policy preflight could not cover the whole policy set, so the result is not provably clean. For preflight that also covers version skew: a condition your rules use that is absent from the proxy’s support matrix means this CLI knows a condition that proxy does not, and those rules cannot fire there. Both walk the same tree with the same collector, so they share one number with one meaning. Outranks warnings-only — exit 1 reads as “warnings, carry on”, which is the green light a half-read tree must not get. A genuine policy error still outranks it.
20pr-scanpr-scan found one or more blocking findings (also 20 with --strict and any warning).
30ExitManifestParseErrorOne or more manifests/lockfiles failed to parse, so dependencies were dropped and the result set is incomplete. Everything that did parse was still scanned; the exit code is what stops CI reading an incomplete scan as a clean one. A real block outranks it. 30 is not unique — see the row below for doctor --strict.
30doctor --strictdoctor --strict reached a public registry directly, which fails enforcement intent even when all local config points at Chainsaw.
40doctor --strictdoctor --strict found an installed package manager Chainsaw has no enforcer for yet.

Configuration precedence

The server URL and auth token each resolve from four sources, highest first:

Server URLAuth token
1--server flag--token flag
2CHAINSAW_SERVERCHAINSAW_TOKEN
3server_url: in the config filetoken: in the config file (legacy)
4the value baked into the binary at build timeOS keyring entry for that server URL

The config file lives at ~/.chainsaw/config.yaml on macOS, $XDG_CONFIG_HOME/chainsaw/config.yaml on Linux (falling back to ~/.config/chainsaw/config.yaml), and %APPDATA%\Chainsaw\config.yaml on Windows. CHAINSAW_CONFIG_HOME overrides all three, and chainsaw status prints the path actually in use. Tokens are never written to it — chainsaw auth login stores them in the OS keyring, and a token found in an older config file is migrated there on the next run.

NO_COLOR (present at any value) disables color and beats an explicit --no-color=false.