These flags are shared across fallow commands. Some commands reject flags that are not meaningful for that surface.
The --dupes-* flags apply to combined mode, fall back to the config value when unset, and mirror the standalone fallow dupes flag of the same name.
| 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. --format json is compact by default; add --pretty for indented output. |
--pretty | Indent --format json output for manual inspection. JSON is compact by default so machine and agent consumers get the same schema with less output; this flag restores human-readable indentation. Applies only to JSON output. SARIF, Code Climate, baselines, snapshots, caches, and other persisted JSON keep their existing presentation regardless of this flag. |
-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) |
--max-file-size <MB> | Skip source files larger than this many megabytes at discovery instead of parsing them (default 5; 0 disables the guard). Guards against the out-of-memory blowup a single multi-megabyte generated, vendored, or bundled file causes on large repositories, and also skips large one-line minified JS assets while the guard is enabled. Declaration files (.d.ts) are always analyzed regardless of size. Skipped files are reported on stderr and in --format json under workspace_diagnostics (kind: "skipped-large-file" or "skipped-minified-file"). Also settable via FALLOW_MAX_FILE_SIZE. |
--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. |
--churn-file <PATH> | Import change history from a fallow-churn/v1 JSON file instead of git log, for projects with no git repository. Affects the churn-backed health signals only. See fallow health › Importing churn from a non-git VCS. |
--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 |
--no-production | Force production mode off for every analysis, overriding a project config's production: true. Conflicts with --production. |
--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. |
--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) |
-o, --output-file <PATH> | Write the report to a file instead of stdout, for any --format (no ANSI codes). Useful on large projects where the terminal scrollback truncates the top. Progress and a Report written to <path> confirmation stay on stderr (suppressed by --quiet). Valid with dead-code, dupes, health, security, and bare invocation; composes with --sarif-file. |
--report-path-prefix <PREFIX> | Override the repository-root offset prepended to every path in the CI-facing formats; an empty string disables rebasing. See Repository-root paths in CI formats. |
--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 |
--coverage <PATH> | Feed Istanbul coverage data to the embedded health analysis in combined mode. Same fallback chain as fallow health --coverage. |
--coverage-root <PATH> | Absolute prefix to strip from Istanbul coverage paths in combined mode. See fallow health --coverage-root. |
--dupes-mode <MODE> | Override duplicate detection mode. |
--dupes-near | Include function-scoped near-miss clones. |
--dupes-threshold <PCT> | Override the duplication percentage failure threshold. |
--dupes-min-tokens <N> | Override the minimum token count for clone detection. |
--dupes-min-lines <N> | Override the minimum line count for clone detection. |
--dupes-min-occurrences <N> | Override the minimum clone occurrences (must be >= 2). |
--dupes-skip-local | Only report cross-directory duplicates. |
--dupes-cross-language | Enable TypeScript to JavaScript duplicate matching. |
--dupes-ignore-imports | Exclude module wiring from duplicate detection (default). |
--dupes-no-ignore-imports | Count module wiring as clone candidates. Conflicts with --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. |
CI platforms resolve file paths against the repository root: GitHub annotations, CodeClimate reports in GitLab, and inline review comments all reject or misplace paths relative to anything else. When --root points at a subdirectory of a git repository (a monorepo package like packages/app/), the CI-facing formats (github-annotations, github-summary, codeclimate, review-github, review-gitlab) therefore emit repository-root-relative paths: fallow detects the offset between --root and the git toplevel and prepends it automatically. --report-path-prefix overrides the detected offset for containerized or vendored checkouts where the git toplevel does not match the CI workspace; an empty string (--report-path-prefix '') disables rebasing entirely and restores --root-relative paths.
Supplied diffs (--diff-file, --diff-stdin, FALLOW_DIFF_FILE) get the same treatment in reverse: fallow detects whether the diff's paths are repository-root-relative or --root-relative and filters findings accordingly. A diff that parses but touches no analyzable files (deletion-only, binary-only, or empty) filters the report to zero findings; only a diff whose paths cannot be placed at all falls back to the full-scope report, with a warning saying so.
When fallow loads a config file (either auto-discovered or via --config), it prints a single line to stderr:
loaded config: /repo/.fallowrc.json
This shows which .fallowrc.json is in effect in monorepos where multiple configs exist. The line is suppressed when:
--quiet is set--format is anything other than human (json, sarif, compact, markdown, codeclimate, gitlab-codequality, pr-comment-github, pr-comment-gitlab, review-github, review-gitlab, badge)For deeper inspection (the resolved config with extends merged), use the dedicated fallow config subcommand.
# Analyze a project in a different directory
fallow dead-code -r /path/to/project
# Use a specific config file
fallow dead-code -c configs/fallow-strict.json
# JSON output with no progress messages
fallow dead-code -f json --quiet
# Limit parallelism to 4 threads
fallow dead-code --threads 4
# Scope to a single workspace package
fallow dead-code -w @myorg/ui
# Scope to whichever workspaces changed since origin/main (CI primitive)
fallow --changed-workspaces origin/main
# Show timing breakdown
fallow dead-code --performance
# Group issues by CODEOWNERS ownership (see Grouped output below)
fallow dead-code --group-by owner
# Health score in combined mode
fallow --score
# Save a snapshot and track trends
fallow --save-snapshot
fallow --trend
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:
# Treat health as production-only, leave dead-code and dupes in full-tree mode
fallow --production-health
# Audit changed files with production-only health
fallow audit --base main --production-health
The matching environment variables 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": {
"deadCode": false,
"health": true,
"dupes": false
}
}
Precedence (highest to lowest): CLI flags (--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.
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 |
With --format json, the output shape changes to a grouped envelope:
{
"kind": "dead-code-grouped",
"grouped_by": "owner",
"total_issues": 12,
"groups": [
{ "key": "@frontend-team", "total_issues": 8, "unused_files": [], "unused_exports": [] },
{ "key": "@backend-team", "total_issues": 4, "unused_exports": [] }
]
}
For --group-by section, each group also carries an owners array with the section's default owners:
{
"kind": "dead-code-grouped",
"grouped_by": "section",
"total_issues": 6,
"groups": [
{
"key": "billing",
"owners": ["@core-reviewers", "@alice", "@bob"],
"total_issues": 2,
"unused_exports": []
},
{
"key": "notifications",
"owners": ["@core-reviewers", "@alice", "@bob"],
"total_issues": 1,
"unused_exports": []
}
]
}
Section and owner groups are not interchangeable: 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.
Set a custom CODEOWNERS path via the codeowners field in .fallowrc.json if your file isn't in a standard location.
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:
Use --performance to see cache hit rates and per-stage timings. This is helpful for diagnosing slow runs.
fallow dead-code --performance
Discovery 12ms (142 files)
Parsing 48ms (23 parsed, 119 cached)
Resolution 15ms
Analysis 8ms
Total 83ms
Use --no-cache to force a full re-parse. This is useful after major refactors or when debugging unexpected results.
fallow dead-code --no-cache
Set cache.dir in the project config or FALLOW_CACHE_DIR in the environment to move the persistent cache out of .fallow/cache.bin. The env var wins when both are present.
FALLOW_CACHE_DIR=/tmp/fallow-cache fallow dead-code