Find dead code, duplication, and complexity hotspots in TypeScript & JavaScript.
Rust-native. Zero config. Sub-second.
npx fallow Dead code 3 unused files, 12 unused exports, 2 unused deps 18ms
Duplication 4 clone groups (2.1% of codebase) 31ms
Complexity 7 functions exceed thresholds 4ms
Total 26 issues across 847 files 53ms
84 framework plugins. No Node.js runtime. No config file needed.
npx fallow # Run without installing
npm install -g fallow # Or install globally (macOS, Linux, Windows)
cargo install fallow-cli # Or via Cargofallow # Run all three analyses
fallow dead-code # Dead code only
fallow dupes # Duplication only
fallow health # Complexity only
fallow fix --dry-run # Preview auto-removal of dead exports and deps
fallow watch # Re-analyze on file changesFinds unused files, exports, dependencies, types, enum members, class members, unresolved imports, unlisted dependencies, duplicate exports, circular dependencies, and type-only dependencies.
fallow dead-code # All dead code issues
fallow dead-code --unused-exports # Only unused exports
fallow dead-code --circular-deps # Only circular dependencies
fallow dead-code --production # Exclude test/dev files
fallow dead-code --changed-since main # Only changed files (for PRs)Finds copy-pasted code blocks across your codebase. Suffix-array algorithm -- no quadratic pairwise comparison.
fallow dupes # Default (mild mode)
fallow dupes --mode semantic # Catch clones with renamed variables
fallow dupes --skip-local # Only cross-directory duplicates
fallow dupes --trace src/utils.ts:42 # Show all clones of code at this locationFour detection modes: strict (exact tokens), mild (default, AST-based), weak (different string literals), semantic (renamed variables and literals).
Surfaces the most complex functions in your codebase and identifies where to spend refactoring effort.
fallow health # Functions exceeding thresholds
fallow health --top 20 # 20 most complex functions
fallow health --file-scores # Per-file maintainability index (0-100)
fallow health --hotspots # Riskiest files (git churn x complexity)
fallow health --targets # Ranked refactoring recommendations
fallow health --changed-since main # Only changed files# GitHub Action
- uses: fallow-rs/fallow@v1
# GitLab CI — include the template and extend
include:
- remote: 'https://raw.githubusercontent.com/fallow-rs/fallow/main/ci/gitlab-ci.yml'
fallow:
extends: .fallow
# Or run directly on any CI
- run: npx fallow --ci--ci enables SARIF output, quiet mode, and non-zero exit on issues. Also supports:
--changed-since main-- analyze only files touched in a PR--baseline/--save-baseline-- fail only on new issues--format sarif-- upload to GitHub Code Scanning- GitLab Code Quality reports (inline MR annotations) via
ci/gitlab-ci.yml --format json/--format markdown-- for custom workflows Adopt incrementally -- surface issues without blocking CI, then promote when ready:
Works out of the box. When you need to customize, create .fallowrc.json or run fallow init:
// .fallowrc.json
{
"$schema": "https://raw.githubusercontent.com/fallow-rs/fallow/main/schema.json",
"entry": ["src/workers/*.ts", "scripts/*.ts"],
"ignorePatterns": ["**/*.generated.ts"],
"ignoreDependencies": ["autoprefixer"],
"rules": {
"unused-files": "error",
"unused-exports": "warn",
"unused-types": "off"
},
"health": {
"maxCyclomatic": 20,
"maxCognitive": 15
}
}TOML also supported (fallow init --toml). Migrating from knip or jscpd? Run fallow migrate.
See the full configuration reference for all options.
84 built-in plugins detect entry points and used exports for your framework automatically.
| Category | Plugins |
|---|---|
| Frameworks | Next.js, Nuxt, Remix, SvelteKit, Gatsby, Astro, Angular, NestJS, Expo, Electron, and more |
| Bundlers | Vite, Webpack, Rspack, Rsbuild, Rollup, Rolldown, Tsup, Tsdown, Parcel |
| Testing | Vitest, Jest, Playwright, Cypress, Storybook, Mocha, Ava |
| Databases | Prisma, Drizzle, Knex, TypeORM, Kysely |
| Monorepos | Turborepo, Nx, Changesets, Syncpack |
Full plugin list -- missing one? Add a custom plugin or open an issue.
- VS Code extension -- tree views, status bar, one-click fixes, auto-download LSP binary (Marketplace)
- LSP server -- real-time diagnostics, hover info, code actions, Code Lens with reference counts
- MCP server -- AI agent integration for Claude Code, Cursor, Windsurf (fallow-skills)
Benchmarked on real open-source projects (median of 5 runs, Apple M5).
| Project | Files | fallow | knip v5 | knip v6 | vs v5 | vs v6 |
|---|---|---|---|---|---|---|
| zod | 174 | 17ms | 577ms | 300ms | 34x | 18x |
| fastify | 286 | 19ms | 791ms | 232ms | 41x | 12x |
| preact | 244 | 20ms | 767ms | 2.02s | 39x | 103x |
| TanStack/query | 901 | 170ms | 2.50s | 1.28s | 15x | 8x |
| svelte | 3,337 | 359ms | 1.73s | 749ms | 5x | 2x |
| next.js | 20,416 | 1.66s | -- | -- | -- | -- |
knip errors out on next.js. fallow completes in under 2 seconds.
| Project | Files | fallow | jscpd | Speedup |
|---|---|---|---|---|
| fastify | 286 | 76ms | 1.96s | 26x |
| vue/core | 522 | 124ms | 3.11s | 25x |
| next.js | 20,416 | 2.89s | 24.37s | 8x |
No TypeScript compiler, no Node.js runtime. How it works | Reproduce benchmarks
// fallow-ignore-next-line unused-export
export const keepThis = 1;
// fallow-ignore-file
// Suppress all issues in this fileAlso supports /** @public */ JSDoc tags for library exports consumed externally.
fallow uses syntactic analysis -- no type information. This is what makes it fast, but type-level dead code is out of scope. Use inline suppression comments or ignoreExports for edge cases.
- Getting started
- Configuration reference
- CI integration guide
- Migrating from knip
- Plugin authoring guide
Missing a framework plugin? Found a false positive? Open an issue.
cargo build --workspace && cargo test --workspaceMIT
{ "rules": { "unused-files": "error", "unused-exports": "warn", "circular-dependencies": "off" } }