Unused Code Is a Maintenance Problem
Most codebases accumulate unused files, exports, and dependencies over time. The trouble is that they are genuinely difficult to spot. Searching globally for a dependency name or right-clicking a file to find references in your editor is tedious, and it only works when you already suspect something is unused. As projects grow, tracking these artifacts by hand becomes impractical.
Existing tools like ts-prune, depcheck, and unimported address parts of the problem, but they each have limits. Some require heavy configuration and still report too many false positives. Others are in maintenance mode and lack support for monorepos. No single tool covered the full breadth of what was needed across a project's files, imports, exports, and dependencies.
Knip is a project linter designed to fill that gap. It works at the repository level, connecting the dots between files, imports, exports, and dependencies to report what is actually unused.
How Knip Tracks Usage
Knip starts from one or more entry files and walks the dependency tree. Any file not reached from those entry points is reported as unused. It simultaneously tracks imported external packages, comparing them against the dependencies listed in package.json. This reveals both unused dependencies and dependencies that are used but never declared. It does the same for internal modules, flagging exports that no other file imports.
The default mode analyzes the whole repository, including tests, configuration files, and Storybook stories. A stricter production mode restricts entry files to production code only, and it only considers regular dependencies, ignoring devDependencies. This mode surfaces items used exclusively by test files, which often means both the export and its tests can be deleted.
Beyond Source Files: Scripts and Tooling
Command-line tools invoked from package.json scripts reference dependencies by their binary name. Knip resolves those dependencies and reports when a tool is present but not invoked, or when a script calls a binary whose package is not listed.
This extends to CI configuration files such as Azure Pipelines or GitHub Actions, where YAML may call the same binaries. Knip also parses custom scripts that spawn child processes via Node.js APIs or libraries like zx and execa. Parsing these files is non-trivial, often involving string-referenced packages and files.
Plugins handle the configurability of the wider JavaScript ecosystem. Many tools refer to dependencies by name in config options like ESLint's extends and plugins, or Storybook's implicit builder: "webpack5" requirement. Plugins expand Knip's reach so it understands these references without manual configuration for each project. Knip's compiler support lets it parse nonstandard syntax from Vue, Svelte, MDX, and Astro files so they can be included in analysis as well.
Performance, Reporting, and Configuration
Knip version 2 dropped ts-morph in favor of working directly with the TypeScript back end. This was done to handle monorepos and custom compilers while keeping performance predictable. One advantage of the rewrite is that Knip can traverse a file's abstract syntax tree only once to extract everything it needs.
When Knip reports a false positive, you can configure it to ignore that item. Later, if the item stops being reported, Knip explicitly notes that the ignore entry is now unnecessary and can be removed.
Several output formats are available beyond the default reporter, including compact, JSON, and one that annotates results with code owners from a CODEOWNERS file. Custom reporters let you pipe results elsewhere, such as writing them to a file or feeding a tracking service.
Planned Features
Knip's roadmap includes a --fix option similar to ESLint's, intended to automate cleanup. The goal is for it to remove the export keyword from unused exports, uninstall unused dependencies, install unlisted ones, and delete unused files.
More plugins are planned to reduce configuration overhead across different projects. The guiding idea is that fewer false positives mean fewer manual overrides. Integrations, such as a VS Code extension or a GitHub Action, are also under consideration as collaborative opportunities.



