fallow check performs dead code analysis on your JavaScript/TypeScript project. It builds a module graph from your entry points and reports anything that isn’t reachable.
This analysis requires building and traversing a complete module graph. It can’t be approximated by reading files individually. Fallow does this deterministically in milliseconds, giving agents, developers, and CI pipelines the same reliable results.
Issue types
Fallow detects 11 types of dead code:| Issue type | Description |
|---|---|
| Unused files | Files not reachable from any entry point |
| Unused exports | Exported symbols never imported elsewhere |
| Unused types | Type aliases and interfaces never referenced |
| Unused dependencies | Packages in dependencies never imported or used as script binaries |
| Unused devDependencies | Packages in devDependencies never imported or used as script binaries |
| Unused enum members | Enum values never referenced |
| Unused class members | Class methods and properties never referenced |
| Unresolved imports | Import specifiers that cannot be resolved |
| Unlisted dependencies | Imported packages missing from package.json |
| Duplicate exports | Same symbol exported from multiple modules |
| Circular dependencies | Modules that import each other directly or transitively |
$ fallow check
Filtering by issue type
Report only specific issue types:Output formats
- Human (default)
- JSON
- SARIF
- Compact
Colored terminal output designed for readability.
Incremental analysis
Only check files changed since a git ref:$ fallow check --changed-since main
Baseline comparison
Adopt fallow incrementally by saving a baseline of existing issues:Debugging
Trace why an export is or isn’t considered used:How it works
How it works
Fallow uses syntactic analysis only: no TypeScript compiler, no type information. This is what makes it fast.
- Discovery: Walks your project, identifies entry points from
package.jsonand framework plugins - Parsing: Parallel parsing with Oxc and rayon, extracting imports and exports
- Resolution: Resolves import specifiers to file paths using
oxc_resolver - Graph: Builds a module graph with re-export chain propagation through barrel files
- Analysis: Walks the graph from entry points, reports unreachable code
Because fallow uses syntactic analysis only, it works best with projects using
isolatedModules: true (required for esbuild, swc, and Vite). Legacy tsc-only projects may see some false positives on type-only imports.Script binary analysis
Fallow parsespackage.json scripts to detect CLI tool usage, reducing false positives in unused dependency detection. When you have a script like "lint": "eslint src/", fallow recognizes that eslint is a binary provided by the eslint package and marks it as used.
This works in several ways:
- Binary name to package name mapping: Script commands like
tsc,vitest, ornextare mapped back to their parent packages (typescript,vitest,next). This prevents these packages from being reported as unused even when they’re neverimport-ed in source code. --configarguments as entry points: When a script references a config file (e.g.,jest --config jest.e2e.config.ts), fallow treats that config file as an entry point. This ensures config files are not flagged as unused.- File path arguments: Direct file references in scripts (e.g.,
node scripts/seed.js) are also recognized as entry points. - Env wrappers and package manager runners: Commands prefixed with
cross-env,npx,pnpx,yarn dlx, ornode -rare unwrapped to find the actual tool binary underneath.
typescript, vite, vitest, and eslint as used dependencies, and vitest.config.ts as an entry point.
Dynamic import resolution
Fallow resolves dynamic imports that use patterns rather than static strings. When you writeimport(\./locales/$.json`)`, the import target is not known at static analysis time. Fallow converts these patterns into glob expressions and matches them against discovered files.
Supported patterns:
| Pattern | Example | Resolved as |
|---|---|---|
| Template literals | import(`./icons/${name}.svg`) | ./icons/*.svg |
| String concatenation | import("./routes/" + path) | ./routes/* |
import.meta.glob | import.meta.glob("./modules/*.ts") | ./modules/*.ts |
require.context | require.context("./themes", true, /\.css$/) | ./themes/**/*.css |
Dynamic imports with fully runtime-computed paths (e.g.,
import(userInput)) cannot be resolved statically. Use entry in your config to mark those directories as entry points.Re-export chain resolution
Barrel files (index.ts files that re-export from other modules) are common in JavaScript projects. Fallow fully resolves export * chains through multiple levels of barrel files with cycle detection.
add in app.ts through src/index.ts and utils/index.ts back to utils/math.ts. The add export is correctly marked as used across the entire chain.
This resolution handles:
- Multi-level chains: Any depth of
export *re-exports is followed until the original declaration is found. - Cycle detection: Circular re-export chains (e.g.,
are-exports fromb,bre-exports froma) are detected and handled without infinite loops. - Mixed re-exports: Named re-exports (
export { foo } from './bar') and namespace re-exports (export * from './bar') are both tracked.
Cross-reference with duplication
When you runfallow check --include-dupes, fallow cross-references dead code findings with code duplication analysis. Clone instances that appear in unused files or overlap with unused exports are flagged as combined high-priority findings.
--include-dupes to prioritize cleanup: if a block of code is both duplicated and unused, removing it eliminates dead code and reduces duplication at the same time.
The cross-reference identifies:
- Clone instances in unused files: If a file is unreachable from entry points and contains duplicated code, the duplication finding is elevated.
- Clone instances overlapping unused exports: If an unused export contains code that is duplicated elsewhere, both findings are reported together.
See also
CLI: check
Full reference for the
fallow check command and its flags.Rules & Severity
Control which issue types are errors, warnings, or disabled.
Auto-fix
Automatically remove the dead code fallow finds.