Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.fallow.tools/llms.txt

Use this file to discover all available pages before exploring further.

Analyze your project for dead code. Fallow scans entry points, traces all reachable exports, and reports anything that isn’t used.
Running bare fallow now runs all analyses (dead code, duplication, and health). Use fallow dead-code to run dead code analysis only. fallow check remains as a hidden alias for fallow dead-code.
fallow dead-code
fallow check      # Hidden alias for fallow dead-code

Options

Output

FlagDescription
-f, --format <FORMAT>Output format: human (default), json, sarif, compact, markdown, codeclimate, gitlab-codequality, pr-comment-github, pr-comment-gitlab, review-github, review-gitlab
-q, --quietSuppress progress output
--fail-on-issuesExit with code 1 if issues are found
--sarif-file <PATH>Write SARIF output to a file (in addition to --format)
--ciCI mode: sets format to SARIF, enables fail-on-issues, suppresses progress. Individual flags can still override.
--explainAdd metric explanations. In human format, explanations are always shown. In JSON format, adds a _meta object with metric descriptions and docs links.
--group-by <MODE>Group output by owner (CODEOWNERS), directory (first path component), package (workspace package), or section (GitLab CODEOWNERS [Section] headers, with owners metadata). See global flags.
--summaryPrint a one-line summary of issue counts at the end of the run. In JSON format, adds a summary counts object.

Filtering

FlagDescription
--unused-filesOnly report unused files
--unused-exportsOnly report unused exports
--unused-typesOnly report unused types
--private-type-leaksOpt in to private type leak API hygiene findings and only report that issue type
--unused-depsOnly report unused dependencies
--unused-optional-depsOnly report unused optional dependencies
--unused-enum-membersOnly report unused enum members
--unused-class-membersOnly report unused class members
--unresolved-importsOnly report unresolved imports
--unlisted-depsOnly report unlisted dependencies
--duplicate-exportsOnly report duplicate exports
--circular-depsOnly report circular dependencies
--re-export-cyclesOnly report re-export cycles (barrel files re-exporting from each other in a loop, or self-loops). See explanations/dead-code#re-export-cycles
--boundary-violationsOnly report boundary violations
--stale-suppressionsOnly report stale suppression comments and @expected-unused JSDoc tags
--type-only-depsOnly report type-only dependencies
--unused-catalog-entriesOnly report unused pnpm catalog entries
--empty-catalog-groupsOnly report empty named pnpm catalog groups
--unresolved-catalog-referencesOnly report package references to missing pnpm catalog entries
--unused-dependency-overridesOnly report unused pnpm dependency overrides
--misconfigured-dependency-overridesOnly report malformed pnpm dependency overrides
--include-dupesAlso run duplication analysis and cross-reference with dead code

Scoping

FlagDescription
--file <PATH>Scope output to specific files. Accepts multiple values. Only issues in the specified files are reported. Project-wide dependency issues are suppressed. Warns on non-existent paths. Useful for lint-staged integration.
--include-entry-exportsAlso report unused exports in entry files (package.json main/exports, framework pages, etc.). By default, exports in entry files are assumed to be consumed externally. This flag catches typos like meatdata instead of metadata in framework-convention exports. The flag is global, so it works on combined mode (fallow --include-entry-exports) and fallow audit. Configurable persistently via includeEntryExports: true in your fallow config; the CLI flag wins when set.

Incremental

FlagDescription
--changed-since <REF>Only check files changed since a git ref
--baseline <PATH>Compare against a previously saved baseline file
--save-baseline <PATH>Save current results as a baseline file
--productionProduction mode (exclude test/story/dev files)
--top <N>Show only the top N items per issue category in human output

Regression detection

FlagDescription
--fail-on-regressionFail 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
These flags help you understand how fallow resolves your code and where time is spent.
FlagDescription
--trace <FILE:EXPORT>Trace usage of a specific export
--trace-file <PATH>Show all edges for a file
--trace-dependency <PACKAGE>Show where a dependency is used
--performanceShow pipeline timing breakdown
# Why is formatDate reported as unused?
fallow dead-code --trace src/utils.ts:formatDate

# What imports/exports does this file have?
fallow dead-code --trace-file src/utils.ts

# Where is lodash used?
fallow dead-code --trace-dependency lodash

# Pipeline performance breakdown
fallow dead-code --performance

Examples

fallow dead-code

Regression detection

Save a regression baseline on your main branch, then compare on subsequent runs (e.g., in PR checks) to prevent issue count from growing. Workflow:
  1. Save a regression baseline on main:
    fallow dead-code --save-regression-baseline
    
    This writes issue counts to .fallow/regression-baseline.json (or a custom path).
  2. On each PR, compare against the baseline:
    fallow dead-code --fail-on-regression
    
    Exits with code 1 if the total issue count exceeds the baseline plus the configured tolerance.
  3. Optionally set a tolerance to allow small fluctuations:
    fallow dead-code --fail-on-regression --tolerance 2%   # percentage
    fallow dead-code --fail-on-regression --tolerance 5     # absolute
    
When --fail-on-regression is used with --format json, the output includes an optional regression object:
{
  "regression": {
    "status": "pass",
    "baseline_total": 42,
    "current_total": 45,
    "delta": 3,
    "tolerance": 2.0,
    "tolerance_kind": "percentage",
    "exceeded": false
  }
}
FieldDescription
statuspass, exceeded, or skipped
baseline_totalIssue count from the baseline file
current_totalIssue count from the current run
deltacurrent_total - baseline_total
toleranceConfigured tolerance value
tolerance_kindpercentage or absolute
exceededWhether the delta exceeds the tolerance
reasonOnly present when status is skipped (e.g., baseline file not found)
These flags also work with fallow dupes and bare fallow (all analyses). The regression check compares total issue counts across all enabled analyses.

Example output

$ fallow dead-code --format compact
unused-file:src/server/jobs/worker.ts
unused-file:src/features/savings/hooks/usePotGroups.ts
unused-file:src/server/jobs/cron.ts
unused-export:src/server/jobs/queue.ts:61:enqueueJobDelayed
unused-export:src/server/jobs/queue.ts:206:sweepStuckProcessingJobs
unused-export:src/components/Card/index.ts:1:CardFooter
re-export-cycle:src/api/index.ts:src/api/index.ts <-> src/api/internal/index.ts
re-export-cycle:src/utils/index.ts:src/utils/index.ts (self-loop)
Re-export cycles ship under their own field in --format json with the cycle’s structural shape:
$ fallow dead-code --format json (excerpt)
{
  "re_export_cycles": [
    {
      "files": ["src/api/index.ts", "src/api/internal/index.ts"],
      "kind": "multi-node",
      "actions": [
        {
          "type": "fix",
          "kind": "refactor-re-export-cycle",
          "auto_fixable": false,
          "description": "Remove one `export * from` (or `export { ... } from`) statement on any one member to break the cycle"
        },
        {
          "type": "suppress-file",
          "kind": "suppress-file",
          "auto_fixable": false,
          "comment": "// fallow-ignore-file re-export-cycle"
        }
      ]
    },
    {
      "files": ["src/utils/index.ts"],
      "kind": "self-loop",
      "actions": [...]
    }
  ]
}
files is sorted lexicographically; the multi-node shape carries two or more entries, the self-loop shape exactly one. See explanations/dead-code#re-export-cycles for the structural rationale.

Grouped output

Use --group-by to partition issues by ownership or directory. This works with all output formats.
# Group by CODEOWNERS (auto-probes CODEOWNERS, .github/CODEOWNERS, .gitlab/CODEOWNERS, docs/CODEOWNERS)
fallow dead-code --group-by owner

# Group by first directory component
fallow dead-code --group-by directory

# Group by workspace package
fallow dead-code --group-by package

# Group by GitLab CODEOWNERS section (requires a file with [Section] headers)
fallow dead-code --group-by section
With --format json, grouped output wraps the normal structure:
{
  "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": [...]
    }
  ]
}
Set a custom CODEOWNERS path via the codeowners field in .fallowrc.json if your file isn’t in a standard location.

Fix suggestions in JSON output

When using --format json, every issue includes an actions array with machine-actionable fix and suppress hints. This lets agents and CI scripts programmatically decide how to resolve each finding.
{
  "path": "src/utils.ts",
  "export_name": "helperFn",
  "line": 10,
  "actions": [
    {
      "type": "remove-export",
      "auto_fixable": true,
      "description": "Remove the unused export from the public API"
    },
    {
      "type": "suppress-line",
      "auto_fixable": false,
      "description": "Suppress with an inline comment above the line",
      "comment": "// fallow-ignore-next-line unused-export"
    }
  ]
}
Each action has:
FieldDescription
typeOne of 14 fix action types in kebab-case (e.g. remove-export, remove-file, suppress-line, add-to-config)
auto_fixabletrue when fallow fix can handle this action automatically. Evaluated per finding, not per action type: the same type may carry true on one finding and false on another (e.g. remove-catalog-entry flips on hardcoded_consumers, the primary dependency action flips between remove-dependency / move-dependency on used_in_workspaces). Filter on this bool of each individual action, not on type. See Auto-fix for the full list of per-instance flips.
descriptionHuman-readable explanation of the action
comment(optional) The inline suppression comment to add
note(optional) Additional context for non-auto-fixable items
config_key(optional) The config key to modify, e.g. "ignoreDependencies" for dependency issues
value(optional) Value to write at config_key. Scalar for keys like ignoreDependencies; array of { file, exports } rule objects for ignoreExports
value_schema(optional) URL pointing at the JSON Schema fragment that describes value. Agents that want to validate the payload before writing it into a user’s config can fetch the linked schema and apply it
scope(optional) Present on duplicate_exports suppress actions as "per-location" since those span multiple files
Re-export findings include a warning note about public API surface impact. Dependency issues use add-to-config suppress (not inline comments) with the concrete package name and config_key: "ignoreDependencies".

Additional JSON fields

When using --format json, the output may include these additional top-level objects:

entry_points

Lists all resolved entry point files that root the module graph:
{
  "entry_points": [
    "src/index.ts",
    "src/cli.ts",
    "src/workers/sync.ts"
  ]
}

summary

When --summary is used, a summary counts object is included:
{
  "summary": {
    "unused_files": 3,
    "unused_exports": 12,
    "unused_types": 2,
    "private_type_leaks": 0,
    "unused_dependencies": 1,
    "unresolved_imports": 0,
    "circular_dependencies": 1,
    "total_issues": 19
  }
}
private_type_leaks is present in JSON output for schema stability, but the rule is off by default. It is populated only when enabled with --private-type-leaks or with private-type-leaks set to warn or error in configuration.

used_in_workspaces

Unused dependency findings can include used_in_workspaces when a package is unused in the declaring workspace but imported elsewhere in the monorepo:
{
  "unused_dependencies": [
    {
      "package_name": "lodash-es",
      "location": "dependencies",
      "path": "packages/shared/package.json",
      "line": 5,
      "used_in_workspaces": ["packages/consumer"]
    }
  ]
}
In human, markdown, GitHub, and GitLab output this appears as “imported in” or an “Imported elsewhere” column. Treat these as workspace placement issues: move the dependency to the consuming workspace instead of auto-removing it.

baseline_deltas

When --baseline is used, a baseline_deltas object shows changes since the baseline:
{
  "baseline_deltas": {
    "added": 3,
    "removed": 5,
    "unchanged": 14
  }
}

Stale suppression detection

Fallow detects // fallow-ignore comments and /** @expected-unused */ JSDoc tags that no longer match any issue. This prevents suppression comments from accumulating after the underlying issues are resolved.
# Only report stale suppressions
fallow dead-code --stale-suppressions

# JSON output includes stale_suppressions array
fallow dead-code --format json --stale-suppressions
Two types of staleness are detected:
OriginWhen it’s stale
// fallow-ignore-next-line / // fallow-ignore-fileThe suppression no longer matches any issue on the target line or in the file
/** @expected-unused */ JSDoc tagThe tagged export is now imported by another module
The stale-suppressions rule defaults to warn. Promote to error for CI enforcement:
{
  "rules": {
    "stale-suppressions": "error"
  }
}
When using --format json, stale suppressions appear in the stale_suppressions array:
{
  "stale_suppressions": [
    {
      "path": "src/utils.ts",
      "line": 5,
      "col": 0,
      "origin": {
        "type": "inline_comment",
        "issue_type": "unused-export",
        "is_file_level": false
      }
    },
    {
      "path": "src/lib.ts",
      "line": 10,
      "col": 0,
      "origin": {
        "type": "jsdoc_tag",
        "export_name": "createWidget"
      }
    }
  ]
}
Use /** @expected-unused */ instead of // fallow-ignore-next-line when you want fallow to alert you if a suppressed export later becomes used. Both are tracked for staleness, but @expected-unused communicates intent more clearly.

See also

Dead code analysis

How fallow detects dead code.

Rules configuration

Configure severity and thresholds per rule.

Production mode

Analyze only shipping code.