Back

Removing Unused Files and Dependencies with Knip

Removing Unused Files and Dependencies with Knip

Every JavaScript and TypeScript project accumulates clutter over time: a dependency installed for a quick experiment, a utility file left behind after a refactor, an exported function nobody imports anymore. Individually, these feel harmless. Collectively, they slow down builds, inflate node_modules, create security noise, and make codebases harder to navigate.

The traditional response is a manual audit: grep for package names, search for file references, cross-check package.json by hand. It works, but it doesn’t scale. This is where Knip comes in.

Key Takeaways

  • Unused dependencies and dead code increase build times, bloat bundles, and create security and licensing noise.
  • Knip analyzes your entire repository as a project-level linter, reporting unused files, exports, dependencies, and unlisted imports.
  • The --fix flag applies automatic cleanups, while --allow-remove-files extends this to deleting unused files.
  • Running Knip in CI helps prevent dead code from accumulating and complements ESLint and your formatter.

Why Unused Dependencies and Dead Code Are Worth Fixing

Unused packages in package.json aren’t just cosmetic noise. They:

  • Add to install time and node_modules disk usage
  • Can end up in production bundles if your bundler doesn’t tree-shake them properly
  • Trigger false security alerts in tools like Dependabot
  • May carry restrictive licenses that technically apply to your project
  • Bring transitive dependencies with the same problems

Dead code carries similar costs. Unused exports and unreferenced files make it harder to understand what a codebase actually does, and they slow down linters and type checkers that have to process them anyway.

What Knip Does Differently

Tools like depcheck and ts-prune addressed parts of this problem, but both projects were archived in 2025. Knip emerged as a modern replacement that combines dependency, export, and file analysis in a single actively maintained tool.

Think of Knip as a project-level linter. Where ESLint checks individual files, Knip analyzes the entire repository: entry points, import graphs, exports, and package.json together. It reports unused files, unused exports, unused dependencies, and packages that are imported but missing from package.json.

Knip works with npm, pnpm, Yarn, and Bun, and requires Node.js 20.19+ or Bun to run.

Getting Started in Five Minutes

Initialize Knip in your project with:

npm init @knip/config

This creates a knip.json config file with sensible defaults. Then run the analysis:

npx knip

Knip outputs a report grouped by issue type: unused files, unused exports, unused dependencies, and unlisted dependencies. On a first run in an older project, the list can be long—that’s expected.

Applying Fixes Safely

Once you’ve reviewed the report and it looks accurate, Knip can apply reviewable automatic fixes:

npx knip --fix

This removes export keywords from unused exports, cleans up package.json, and handles re-exports and TypeScript enum members. To also delete unused files:

npx knip --fix --allow-remove-files

Always review changes in Git before committing. Knip is conservative by design, but auto-fix modifies real files. A quick git diff before staging is a good habit.

You can also target specific issue types to keep changes small and reviewable:

npx knip --fix-type dependencies
npx knip --fix-type exports,types

When Knip Needs a Little Help

Knip isn’t a perfect black box. A few situations require manual configuration:

  • Dynamic imports (import(someVariable)) can’t be statically resolved
  • Framework conventions (Next.js page files, Vite virtual modules) may need plugin configuration or ignore rules
  • Generated files should typically be excluded from analysis
  • Monorepos work well out of the box, but cross-workspace references sometimes need explicit configuration

If you’re seeing false positives, add an ignore or ignoreDependencies entry to knip.json rather than disabling whole sections of the analysis.

Making Cleanup a Habit

The most effective use of Knip isn’t a one-time audit—it’s running it regularly. Add it to your CI pipeline alongside your linter and type checker:

npx knip --reporter compact

A clean report on every pull request helps keep dead code from accumulating in the first place. Pair Knip with ESLint (for unused variables within files) and your formatter of choice, and you have a solid, automated maintenance loop that keeps your JavaScript and TypeScript projects lean without manual detective work.

Conclusion

Knip turns the tedious task of hunting down unused files, exports, and dependencies into a repeatable, automated step. By treating cleanup as part of your regular workflow rather than an occasional spring cleaning, you keep your project lean, your builds fast, and your dependency surface small. Start with a single npx knip run, fold the results into your CI, and let the tool do the detective work you used to do by hand.

FAQs

Yes, Knip only reports issues by default and makes no changes unless you pass the --fix flag. Run it first to review the report, then apply fixes incrementally using --fix-type to target one category at a time. Always review the Git diff before committing, especially when using --allow-remove-files.

Knip combines the responsibilities of both tools in a single actively maintained package. Depcheck focuses on dependencies and ts-prune on unused TypeScript exports, but Knip analyzes files, exports, and dependencies together across workspaces, producing more accurate results for modern projects.

False positives usually come from dynamic imports, framework conventions, or generated files that Knip cannot resolve statically. Check whether a Knip plugin exists for your framework, then add ignore or ignoreDependencies entries in knip.json for the remaining cases. Avoid disabling entire analysis sections to preserve coverage.

Yes, and that is where it provides the most value. Add npx knip --reporter compact to your CI pipeline so every pull request is checked for new dead code. Combined with ESLint and your formatter, this creates an automated maintenance loop that helps prevent unused files and dependencies from accumulating between releases.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay