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.
Install
Commands
Dead code
Finds unused files, exports, dependencies, types, enum members, class members, unresolved imports, unlisted dependencies, duplicate exports, circular dependencies, and type-only dependencies.
Duplication
Finds copy-pasted code blocks across your codebase. Suffix-array algorithm -- no quadratic pairwise comparison.
Four detection modes: strict (exact tokens), mild (default, AST-based), weak (different string literals), semantic (renamed variables and literals).
Complexity
Surfaces the most complex functions in your codebase and identifies where to spend refactoring effort.
CI integration
# 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--format codeclimate-- GitLab Code Quality inline MR annotations--format annotations-- GitHub Actions inline PR annotations (no Action required)--format json/--format markdown-- for custom workflows
Both the GitHub Action and GitLab CI template auto-detect your package manager (npm/pnpm/yarn) from lock files, so install/uninstall commands in review comments match your project.
Adopt incrementally -- surface issues without blocking CI, then promote when ready:
{ "rules": { "unused-files": "error", "unused-exports": "warn", "circular-dependencies": "off" } }
GitLab CI rich MR comments
The GitLab CI template can post rich comments directly on merge requests -- summary comments with collapsible sections and inline review discussions with suggestion blocks.
| Variable | Default | Description |
|---|---|---|
FALLOW_COMMENT |
"false" |
Post a summary comment on the MR with collapsible sections per analysis |
FALLOW_REVIEW |
"false" |
Post inline MR discussions at the relevant lines, with suggestion blocks for unused exports |
FALLOW_MAX_COMMENTS |
"50" |
Maximum number of inline review comments |
In MR pipelines, --changed-since is set automatically to scope analysis to changed files. Previous fallow comments are cleaned up on re-runs.
The comment merging pipeline groups unused exports per file and deduplicates clone reports, keeping MR threads readable.
A GITLAB_TOKEN (PAT with api scope) is recommended for full features (suggestion blocks, cleanup of previous comments). CI_JOB_TOKEN works for posting but cannot delete comments from prior runs.
# .gitlab-ci.yml — full example with rich MR comments
include:
- remote: 'https://raw.githubusercontent.com/fallow-rs/fallow/main/ci/gitlab-ci.yml'
fallow:
extends: .fallow
variables:
FALLOW_COMMENT: "true" # Summary comment with collapsible sections
FALLOW_REVIEW: "true" # Inline discussions with suggestion blocks
FALLOW_MAX_COMMENTS: "30" # Cap inline comments (default: 50)
FALLOW_FAIL_ON_ISSUES: "true"
Configuration
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.
Framework plugins
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.
Editor & AI support
- 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)
Performance
Benchmarked on real open-source projects (median of 5 runs, Apple M5).
Dead code: fallow vs knip
| 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.
Duplication: fallow vs jscpd
| 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
Suppressing findings
// fallow-ignore-next-line unused-export
export const keepThis = 1;
// fallow-ignore-file
// Suppress all issues in this file
Also supports /** @public */ JSDoc tags for library exports consumed externally.
Limitations
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.
Documentation
- Getting started
- Configuration reference
- CI integration guide
- Migrating from knip
- Plugin authoring guide
Contributing
Missing a framework plugin? Found a false positive? Open an issue.
&&
License
MIT