dead-code, check, dupes, health, flags, security, fix, watch, list, init, migrate). Some commands reject flags that are not meaningful for that surface.
Reference
| Flag | Description |
|---|---|
-r, --root <PATH> | Project root directory (default: current working directory) |
-c, --config <PATH> | Path to config file (default: auto-detected) |
-f, --format <FORMAT> | Output format: human (default), json, sarif, compact, markdown, codeclimate, gitlab-codequality, pr-comment-github, pr-comment-gitlab, review-github, review-gitlab, badge. Alias: --output |
-q, --quiet | Suppress progress bars and status messages |
--no-cache | Disable incremental caching (force full re-parse) |
--threads <N> | Number of parser threads (default: available parallelism) |
--changed-since <REF> (alias: --base) | Only report issues in files changed since this git ref |
--diff-file <PATH> | Path to a unified diff (e.g. git diff --unified=0 main...HEAD) used to narrow source-anchored findings to lines inside an added hunk. Point findings (unused-export, unresolved-import, boundary-violation, etc.) drop when their source line is not in the diff; range findings (complexity hotspots, clone families) drop when their [start_line, end_line] does not overlap the diff. Project-level findings (unused deps, catalog entries, dependency overrides) bypass the analysis filter because they anchor at fixed package.json / pnpm-workspace.yaml lines a PR rarely touches even when it semantically caused them. Sticky PR/MR summaries can set FALLOW_SUMMARY_SCOPE=diff to filter those project-level findings too. Also drives line-level scoping of the runtime-coverage hot-path-touched verdict. Pass - as the path or use --diff-stdin to read the diff from stdin (gh pr diff | fallow audit --diff-file -). When combined with --changed-since, the diff filter wins for line-level filtering and --changed-since still scopes file discovery; a one-line stderr note records the precedence. Falls back to the FALLOW_DIFF_FILE env var when omitted. |
--diff-stdin | Read the unified diff from stdin instead of a file. Equivalent to --diff-file -. Mutually exclusive with a non-stdin --diff-file PATH value. Useful for piping gh pr diff or git diff directly into fallow. |
--baseline <PATH> | Compare against a previously saved baseline file |
--save-baseline <PATH> | Save the current results as a baseline file |
--fail-on-regression | Fail if issue count increased beyond tolerance vs a regression baseline |
--tolerance <N> | Allowed increase: "2%" (percentage) or "5" (absolute). Default: "0" |
--regression-baseline <PATH> | Path to regression baseline file (default: .fallow/regression-baseline.json) |
--save-regression-baseline <PATH> | Save current issue counts as a regression baseline |
--production | Production mode: exclude test/story/dev files, only start/build scripts |
--production-dead-code | Per-analysis production mode for dead-code in bare combined runs and fallow audit. See Per-analysis production mode. |
--production-health | Per-analysis production mode for health in bare combined runs and fallow audit. |
--production-dupes | Per-analysis production mode for duplication in bare combined runs and fallow audit. |
-w, --workspace <PATTERNS> | Scope output to one or more workspaces. Accepts exact names, globs matched against both the package name AND the workspace path (apps/*, @scope/*), and !-prefixed negations (!apps/legacy). Values can be comma-separated (-w web,admin) or the flag can be repeated. Quote patterns containing ! or glob chars to avoid shell expansion. |
--changed-workspaces <REF> | Git-derived monorepo CI scoping: scope output to workspaces containing any file changed since REF (e.g. origin/main, HEAD~1). Auto-derives the workspace set from git diff so CI jobs don’t hand-maintain a --workspace list. Mutually exclusive with --workspace. A missing ref or non-git directory is a hard error (exit 2), not a silent full-scope fallback. Root-only diffs map to 0 workspaces and exit 0 with no issues. |
--performance | Show pipeline timing breakdown |
--explain | In human format, prints a Description: line under each section header. In JSON format, includes metric definitions in the output _meta object. Always enabled for MCP. |
--legacy-envelope | Emit the previous typed JSON root envelope without the top-level kind discriminator. Use only while migrating older consumers; new integrations should branch on kind. |
--ci | CI mode: equivalent to --format sarif --fail-on-issues --quiet |
--fail-on-issues | Exit with code 1 if issues are found |
--sarif-file <PATH> | Write SARIF output to a file (in addition to the primary --format output) |
--group-by <MODE> | Group output by CODEOWNERS ownership (owner), first directory component (directory), workspace package (package), or GitLab CODEOWNERS section (section). When active, all output formats partition issues into labeled groups. |
--summary | Print a one-line summary of issue counts at the end of the run. In JSON format, adds a summary counts object to the output. |
--only <check,dupes,health> | Run only specific analyses when no subcommand is given |
--skip <check,dupes,health> | Skip specific analyses when no subcommand is given |
--dupes-mode <MODE> | Override duplicate detection mode in combined mode. Falls back to the config value when unset. Mirrors the standalone fallow dupes --mode. |
--dupes-threshold <PCT> | Override the duplication percentage failure threshold in combined mode. Falls back to the config value when unset. Mirrors the standalone fallow dupes --threshold. |
--dupes-min-tokens <N> | Override the minimum token count for clone detection in combined mode. Falls back to the config value when unset. Mirrors the standalone fallow dupes --min-tokens. |
--dupes-min-lines <N> | Override the minimum line count for clone detection in combined mode. Falls back to the config value when unset. Mirrors the standalone fallow dupes --min-lines. |
--dupes-min-occurrences <N> | Override the minimum clone occurrences in combined mode (must be >= 2). Falls back to the config value when unset. Mirrors the standalone fallow dupes --min-occurrences. |
--dupes-skip-local | Only report cross-directory duplicates in combined mode. Falls back to the config value when unset. Mirrors the standalone fallow dupes --skip-local. |
--dupes-cross-language | Enable TypeScript to JavaScript duplicate matching in combined mode. Falls back to the config value when unset. Mirrors the standalone fallow dupes --cross-language. |
--dupes-ignore-imports | Exclude import declarations from duplicate detection in combined mode. Falls back to the config value when unset. Mirrors the standalone fallow dupes --ignore-imports. |
--score | Compute health score (0-100 with letter grade) in combined mode. Enables the health delta header in PR comments. Also available on fallow health. |
--trend | Compare current health metrics against the most recent saved snapshot. Implies --score. Also available on fallow health. |
--save-snapshot [PATH] | Save a vital signs snapshot for trend tracking. Default path: .fallow/snapshots/<timestamp>.json. Forces file-scores and hotspot computation. Also available on fallow health. |
--include-entry-exports | Report unused exports in entry files instead of auto-marking them as used. Catches typos in framework exports (e.g. meatdata instead of metadata). Also configurable via includeEntryExports: true in your fallow config; the CLI flag wins when set. |
Loaded config disclosure
When fallow loads a config file (either auto-discovered or via--config), it prints a single line to stderr:
.fallowrc.json is in effect, especially in monorepos where multiple configs may exist. The line is suppressed when:
--quietis set--formatis anything other thanhuman(json,sarif,compact,markdown,codeclimate,gitlab-codequality,pr-comment-github,pr-comment-gitlab,review-github,review-gitlab,badge)
extends merged), use the dedicated fallow config subcommand.
Examples
Per-analysis production mode
Bare combined runs (fallow with no subcommand) and fallow audit accept three per-analysis production flags so you can enable production mode for one analysis without forcing it on the others:
FALLOW_PRODUCTION_DEAD_CODE, FALLOW_PRODUCTION_HEALTH, and FALLOW_PRODUCTION_DUPES accept the same set of values as FALLOW_PRODUCTION (true, false, 1, 0, yes, no, on, off). The production config field also accepts a per-analysis object:
--production, --production-{dead-code,health,dupes}), per-analysis env var (FALLOW_PRODUCTION_HEALTH, etc.), global env var (FALLOW_PRODUCTION), config (production: { ... } or production: true). The legacy boolean form (--production, production: true, FALLOW_PRODUCTION=true) is unchanged and still applies to every analysis.
The per-analysis CLI flags are rejected when used with a subcommand other than audit (e.g. fallow dead-code --production-health errors). Use the bare command or the per-analysis env vars in that case.
Grouped output
The--group-by flag partitions all issues into labeled groups. This works with every output format and every subcommand.
| Mode | Grouping | Requires |
|---|---|---|
owner | CODEOWNERS file ownership. Auto-probes CODEOWNERS, .github/CODEOWNERS, .gitlab/CODEOWNERS, docs/CODEOWNERS. First owner on multi-owner lines wins. | A CODEOWNERS file (or set codeowners in config) |
directory | First path component (e.g. src/utils/foo.ts groups under src) | Nothing |
package | Workspace package name (e.g. @myorg/ui). Issues are grouped by the package they belong to. | A monorepo with workspace packages |
section | GitLab CODEOWNERS [Section] header name. Distinct sections stay in distinct groups even when they share a default reviewer, so teams with one shared lead reviewer across many sections get per-section triage instead of one giant bucket. | A GitLab-style CODEOWNERS file with at least one [Section] header |
--format json, the output shape changes to a grouped envelope:
--group-by section, each group also carries an owners array with the section’s default owners:
owner collapses all sections that share a lead reviewer into a single bucket, while section preserves the [Section] headers as stable group keys across reviewer rotation.
Incremental caching
Fallow caches parsed file data between runs to skip unchanged files. On the second run, only modified files are re-parsed. The rest are loaded from cache. How it works:- Each file is hashed with xxh3 (extremely fast, non-cryptographic)
- If the hash matches the cached version, parsing is skipped entirely
- The module graph is rebuilt from cached + freshly-parsed data
--no-cache to force a full re-parse. This is useful after major refactors or when debugging unexpected results.
See also
Environment variables
Set defaults for format and quiet mode via environment variables.
Configuration
Full config file reference for project-level settings.