depcheck vs knip vs npm-check
Dependency Audit and Cleanup Tools for JavaScript Projects
depcheckknipnpm-check

Dependency Audit and Cleanup Tools for JavaScript Projects

depcheck, knip, and npm-check are command-line tools designed to help JavaScript developers manage project dependencies by identifying unused, missing, or outdated packages. depcheck analyzes source code to detect dependencies listed in package.json that aren’t actually imported or required. knip provides a more comprehensive audit, checking not only unused dependencies but also missing ones, unused files, and dead exports across the entire codebase. npm-check focuses on interactive dependency management, showing outdated or unused packages and allowing selective updates through a terminal user interface.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
depcheck04,936231 kB1163 years agoMIT
knip011,2111.6 MB213 days agoISC
npm-check06,64894.1 kB232-MIT

Dependency Auditing Tools Compared: depcheck vs knip vs npm-check

When maintaining modern JavaScript projects, keeping dependencies lean and relevant is critical for performance, security, and long-term maintainability. Three popular tools—depcheck, knip, and npm-check—help identify unused or problematic packages, but they differ significantly in scope, architecture, and workflow integration. Let’s examine how each works under real-world conditions.

🔍 Core Functionality: What Each Tool Actually Checks

depcheck focuses exclusively on detecting unused dependencies listed in package.json. It parses your source code (JavaScript, TypeScript, JSX, etc.) and compares required modules against declared dependencies. If a package is in dependencies or devDependencies but never imported or required, it flags it.

# Basic usage
npx depcheck

It does not check for missing dependencies, outdated versions, or interactive updates.

knip takes a broader approach: it identifies unused files, exports, and dependencies, plus missing dependencies and unlisted binaries. It scans your entire codebase—including configuration files—and validates that everything referenced is properly declared.

# Basic usage
npx knip

For example, if you use eslint in a script but forget to list it in devDependencies, knip will catch it.

npm-check emphasizes interactive dependency management: it shows which packages are outdated, unused, or missing, and lets you selectively update or remove them via an interactive TUI.

# Check for issues
npx npm-check

# Interactive update mode
npx npm-check -u

Unlike the others, npm-check provides a visual interface for decision-making, making it beginner-friendly but less suited for CI pipelines.

🧪 Detection Accuracy: False Positives and Edge Cases

All three tools can produce false positives, but their handling differs.

depcheck may miss dynamically required modules (e.g., require(someVar)) or dependencies used only in non-JS files (like Webpack configs). You can configure it with --ignores or custom parsers:

// .depcheckrc
{
  "ignores": ["@types/*", "typescript"]
}

knip reduces false positives by supporting custom entry points and project types. For example, it understands that next uses next.config.js and won’t flag next as unused:

// knip.jsonc
{
  "$schema": "https://unpkg.com/knip@latest/schema.json",
  "entry": ["src/index.ts", "next.config.js"]
}

It also checks for unused TypeScript exports and dead files—features the others lack.

npm-check often flags packages as unused if they’re only used in build scripts or CLI contexts (e.g., prettier called via npm run format). It doesn’t deeply analyze source code structure, relying instead on static string matching of require/import statements.

⚙️ Integration into Developer Workflows

depcheck is designed for automation. Its JSON output integrates cleanly into CI:

# Fail CI if unused deps found
npx depcheck --json | jq -e '.dependencies | length == 0'

No interactive mode exists—it’s purely a linter.

knip supports both CI and local development. It offers machine-readable output (--reporter json) and can auto-fix some issues (e.g., removing unused files):

# Run in CI with strict exit code
npx knip --fail-on-unused

Its plugin system supports frameworks like Next.js, Remix, and Vite out of the box.

npm-check is primarily a local development tool. The interactive update mode (-u) modifies package.json and runs npm install automatically—great for one-off cleanups, but risky in automated environments.

🛑 Maintenance Status and Future Outlook

As of 2024:

  • depcheck is actively maintained, with recent releases addressing ESM and TypeScript parsing.
  • knip is under active, rapid development, frequently adding support for new tooling ecosystems.
  • npm-check has not seen a release since 2021 and shows signs of stagnation. While not officially deprecated, its GitHub repository has unresolved issues and lacks support for modern module systems.

⚠️ Important: npm-check should not be used in new projects due to lack of maintenance and compatibility gaps with current Node.js and npm features.

🆚 Side-by-Side Feature Comparison

Capabilitydepcheckknipnpm-check
Detects unused dependencies
Detects missing dependencies✅ (limited)
Outdated package detection
Interactive update interface
Unused file/export detection
CI/automation friendly
Modern JS/TS support✅ (with config)✅ (built-in)⚠️ (partial)
Active maintenance

💡 Practical Recommendations

  • Use knip if you want a comprehensive, future-proof solution that covers dependencies, dead code, and configuration hygiene. It’s especially valuable in monorepos or complex setups.
  • Use depcheck if you need a lightweight, focused tool just for unused dependencies and already have other systems for version checking.
  • Avoid npm-check in new projects. Its interactive model doesn’t scale, and lack of updates makes it unreliable with modern toolchains.

In short: knip is the most capable and forward-looking; depcheck is a reliable specialist; npm-check is best left in legacy projects.

How to Choose: depcheck vs knip vs npm-check

  • depcheck:

    Choose depcheck if you need a lightweight, focused tool that strictly identifies unused dependencies in your package.json based on static code analysis. It’s ideal for CI pipelines where you want deterministic, non-interactive output and already handle version updates and missing dependency checks through other means.

  • knip:

    Choose knip if you want a holistic solution that not only finds unused dependencies but also detects missing ones, unused files, and dead exports across your entire project—including config files and framework-specific patterns. It’s best for teams seeking deep codebase hygiene with strong support for modern tooling like TypeScript, Next.js, and Vite.

  • npm-check:

    Avoid npm-check in new projects. While it offers an interactive interface for updating or removing dependencies, it hasn’t been actively maintained since 2021 and lacks support for modern JavaScript ecosystems. Use it only for quick audits in legacy projects where interactivity is preferred over accuracy or automation.

README for depcheck

depcheck

Depcheck is a tool for analyzing the dependencies in a project to see: how each dependency is used, which dependencies are useless, and which dependencies are missing from package.json.

Status

Build Status Financial Contributors on Open Collective Build status codecov.io

Dependencies

Installation

npm install -g depcheck

Or simply using npx which is a package runner bundled in npm:

$ npx depcheck

Notice: depcheck needs node.js >= 10.

Syntax Support

Depcheck not only recognizes the dependencies in JavaScript files, but also supports these syntaxes:

To get the syntax support by external dependency, please install the corresponding package explicitly. For example, for TypeScript user, install depcheck with typescript package:

npm install -g depcheck typescript

Special

The special component is used to recognize the dependencies that are not generally used in the above syntax files. The following scenarios are supported by specials:

  • babel - Babel presets and plugins
  • bin - Dependencies used in npm commands, Travis scripts or other CI scripts
  • commitizen - Commitizen configuration adaptor
  • eslint - ESLint configuration presets, parsers and plugins
  • feross-standard - Feross standard format parser
  • gatsby - Gatsby configuration parser
  • gulp-load-plugins - Gulp-load-plugins lazy loaded plugins
  • husky - Husky configuration parser
  • istanbul - Istanbul nyc configuration extensions
  • jest - Jest properties in Jest Configuration
  • karma - Karma configuration frameworks, browsers, preprocessors and reporters
  • lint-staged - Lint-staged configuration parser
  • mocha - Mocha explicit required dependencies
  • prettier - Prettier configuration module
  • tslint - TSLint configuration presets, parsers and plugins
  • ttypescript - ttypescript transformers
  • webpack - Webpack loaders
  • serverless- Serverless plugins

The logic of a special is not perfect. There might be false alerts. If this happens, please open an issue for us.

Usage

depcheck [directory] [arguments]

The directory argument is the root directory of your project (where the package.json file is). If unspecified, defaults to current directory.

All of the arguments are optional:

--ignore-bin-package=[true|false]: A flag to indicate if depcheck ignores the packages containing bin entry. The default value is false.

--skip-missing=[true|false]: A flag to indicate if depcheck skips calculation of missing dependencies. The default value is false.

--json: Output results in JSON. When not specified, depcheck outputs in human friendly format.

--oneline: Output results as space separated string. Useful for copy/paste.

--ignores: A comma separated array containing package names to ignore. It can be glob expressions. Example, --ignores="eslint,babel-*".

--ignore-dirs: DEPRECATED, use ignore-patterns instead. A comma separated array containing directory names to ignore. Example, --ignore-dirs=dist,coverage.

--ignore-path: Path to a file with patterns describing files to ignore. Files must match the .gitignore spec. Example, --ignore-path=.eslintignore.

--ignore-patterns: Comma separated patterns describing files to ignore. Patterns must match the .gitignore spec. Example, --ignore-patterns=build/Release,dist,coverage,*.log.

--quiet: Suppress the "No depcheck issue" log. Useful in a monorepo with multiple packages to focus only on packages with issues.

--help: Show the help message.

--parsers, --detectors and --specials: These arguments are for advanced usage. They provide an easy way to customize the file parser and dependency detection. Check the pluggable design document for more information.

--config=[filename]: An external configuration file (see below).

Usage with a configuration file

Depcheck can be used with an rc configuration file. In order to do so, create a .depcheckrc file in your project's package.json folder, and set the CLI keys in YAML, JSON, and JavaScript formats. For example, the CLI arguments --ignores="eslint,babel-*" --skip-missing=true would turn into:

.depcheckrc

ignores: ["eslint", "babel-*"]
skip-missing: true

Important: if provided CLI arguments conflict with configuration file ones, the CLI ones will take precedence over the rc file ones.

The rc configuration file can also contain the following extensions: .json, .yaml, .yml.

API

Similar options are provided to depcheck function for programming:

import depcheck from 'depcheck';

const options = {
  ignoreBinPackage: false, // ignore the packages with bin entry
  skipMissing: false, // skip calculation of missing dependencies
  ignorePatterns: [
    // files matching these patterns will be ignored
    'sandbox',
    'dist',
    'bower_components',
  ],
  ignoreMatches: [
    // ignore dependencies that matches these globs
    'grunt-*',
  ],
  parsers: {
    // the target parsers
    '**/*.js': depcheck.parser.es6,
    '**/*.jsx': depcheck.parser.jsx,
  },
  detectors: [
    // the target detectors
    depcheck.detector.requireCallExpression,
    depcheck.detector.importDeclaration,
  ],
  specials: [
    // the target special parsers
    depcheck.special.eslint,
    depcheck.special.webpack,
  ],
  package: {
    // may specify dependencies instead of parsing package.json
    dependencies: {
      lodash: '^4.17.15',
    },
    devDependencies: {
      eslint: '^6.6.0',
    },
    peerDependencies: {},
    optionalDependencies: {},
  },
};

depcheck('/path/to/your/project', options).then((unused) => {
  console.log(unused.dependencies); // an array containing the unused dependencies
  console.log(unused.devDependencies); // an array containing the unused devDependencies
  console.log(unused.missing); // a lookup containing the dependencies missing in `package.json` and where they are used
  console.log(unused.using); // a lookup indicating each dependency is used by which files
  console.log(unused.invalidFiles); // files that cannot access or parse
  console.log(unused.invalidDirs); // directories that cannot access
});

Example

The following example checks the dependencies under /path/to/my/project folder:

$> depcheck /path/to/my/project
Unused dependencies
* underscore
Unused devDependencies
* jasmine
Missing dependencies
* lodash

It figures out:

  • The dependency underscore is declared in the package.json file, but not used by any code.
  • The devDependency jasmine is declared in the package.json file, but not used by any code.
  • The dependency lodash is used somewhere in the code, but not declared in the package.json file.

Please note that, if a subfolder has a package.json file, it is considered another project and should be checked with another depcheck command.

The following example checks the same project, however, outputs as a JSON blob. Depcheck's JSON output is in one single line for easy pipe and computation. The json command after the pipe is a node.js program to beautify the output.

$> depcheck /path/to/my/project --json | json
{
  "dependencies": [
    "underscore"
  ],
  "devDependencies": [
    "jasmine"
  ],
  "missing": {
    "lodash": [
      "/path/to/my/project/file.using.lodash.js"
    ]
  },
  "using": {
    "react": [
      "/path/to/my/project/file.using.react.jsx",
      "/path/to/my/project/another.file.using.react.jsx"
    ],
    "lodash": [
      "/path/to/my/project/file.using.lodash.js"
    ]
  },
  "invalidFiles": {
    "/path/to/my/project/file.having.syntax.error.js": "SyntaxError: <call stack here>"
  },
  "invalidDirs": {
    "/path/to/my/project/folder/without/permission": "Error: EACCES, <call stack here>"
  }
}
  • The dependencies, devDependencies and missing properties have the same meanings in the previous example.
  • The using property is a lookup indicating each dependency is used by which files.
  • The value of missing and using lookup is an array. It means the dependency may be used by many files.
  • The invalidFiles property contains the files having syntax error or permission error. The value is the error details. However, only one error is stored in the lookup.
  • The invalidDirs property contains the directories having permission error. The value is the error details.

False Alert

Depcheck just walks through all files and tries to find the dependencies according to some predefined rules. However, the predefined rules may not be enough or may even be wrong.

There may be some cases in which a dependency is being used but is reported as unused, or a dependency is not used but is reported as missing. These are false alert situations.

If you find that depcheck is reporting a false alert, please open an issue with the following information to let us know:

  • The output from depcheck --json command. Beautified JSON is better.
  • Which dependencies are considered as false alert?
  • How are you using those dependencies, what do the files look like?

Changelog

We use the GitHub release page to manage changelog.

Contributors

Code Contributors

This project exists thanks to all the people who contribute. [Contribute].

Financial Contributors

Become a financial contributor and help us sustain our community. [Contribute]

Individuals

Organizations

Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]

License

MIT License.