depcheck vs npm-check-updates vs snyk vs retire
Dependency Health and Security Analysis in JavaScript Projects
depchecknpm-check-updatessnykretireSimilar Packages:
Dependency Health and Security Analysis in JavaScript Projects

depcheck, npm-check-updates, retire, and snyk are CLI tools that help developers maintain healthy, secure, and up-to-date npm dependency trees. While they share the broad goal of improving project hygiene, each targets a distinct aspect: unused dependencies (depcheck), outdated packages (npm-check-updates), known vulnerable libraries in frontend assets (retire), and comprehensive vulnerability scanning with remediation guidance (snyk). Together, they form complementary layers of a modern JavaScript dependency management strategy.

Npm Package Weekly Downloads Trend
3 Years
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
depcheck1,547,5964,940231 kB1162 years agoMIT
npm-check-updates604,22110,0885.83 MB934 days agoApache-2.0
snyk519,8995,35353.9 MB1226 days agoApache-2.0
retire163,5134,031108 kB310 days agoApache-2.0

Dependency Hygiene Deep Dive: depcheck vs npm-check-updates vs retire vs snyk

Managing npm dependencies isn’t just about installing packages — it’s about keeping your project lean, current, and secure. The tools depcheck, npm-check-updates, retire, and snyk each tackle a different slice of this problem. Let’s compare them head-to-head through real engineering scenarios.

🧹 Finding Dead Weight: Unused Dependencies

depcheck analyzes your codebase to find packages listed in package.json that aren’t actually imported or required anywhere.

# Run depcheck to list unused dependencies
npx depcheck

It parses JavaScript, TypeScript, and common config files to trace static imports. However, it won’t detect:

  • Packages used via dynamic require() (e.g., require(someVar))
  • Dependencies referenced only in shell scripts, Dockerfiles, or CI configs
  • Binaries invoked via npx or scripts in package.json

Example output might show:

Unused dependencies
* lodash
* moment

In contrast, npm-check-updates, retire, and snyk do not check for unused code — they assume everything in package.json is needed.

🔄 Keeping Dependencies Fresh: Version Updates

npm-check-updates (often aliased as ncu) tells you which packages have newer versions available and can update package.json for you.

# Show outdated packages
npx npm-check-updates

# Update package.json to latest majors
npx npm-check-updates -u
npm install

It respects your package.json version ranges and can target specific update strategies (e.g., only minors, or latest tags). This is purely a versioning tool — it doesn’t assess security or usage.

The other tools handle updates differently:

  • depcheck: No version checking at all.
  • retire: Reports vulnerable versions but doesn’t suggest non-vulnerable alternatives or update package.json.
  • snyk: Recommends specific safe versions to upgrade to (or patches) based on vulnerability data.
# Snyk shows fixable issues with upgrade paths
npx snyk test
npx snyk fix  # applies safe upgrades automatically

🛡️ Detecting Known Vulnerabilities

This is where the tools diverge sharply in scope.

retire focuses only on client-side JavaScript libraries. It scans your project’s public assets (like dist/ or public/) and node_modules for known vulnerable versions of frontend frameworks.

# Scan for vulnerable JS libraries in ./public
npx retire --js --outputformat json

It uses a local database of CVE-like entries for libraries such as React, Vue, or Handlebars. But it won’t catch vulnerabilities in server-side packages like express or lodash when used in Node.js.

snyk, by comparison, scans your entire dependency tree — including deeply nested transitive dependencies — for vulnerabilities in both frontend and backend contexts. It pulls from a continuously updated vulnerability database and understands exploitability in your specific environment.

# Snyk scans node_modules and lockfile for all vulns
npx snyk test

Output includes CVSS scores, exploit maturity, and whether the vulnerable function is actually reachable in your code.

depcheck and npm-check-updates do not perform any vulnerability detection.

🛠️ Remediation: From Detection to Fix

Finding issues is only half the battle. How easy is it to act?

  • depcheck: You manually remove unused entries from package.json and run npm install.
  • npm-check-updates: Use -u flag to auto-update package.json, then run install.
  • retire: Only reports — you must manually choose a safe version and update yourself.
  • snyk: Offers snyk fix to automatically apply safe upgrades or patches without breaking changes.
# Snyk can patch without version bumps
npx snyk fix
# Applies a targeted patch to vulnerable code

This makes snyk uniquely valuable in regulated or high-compliance environments where audit trails and minimal-change fixes matter.

🔍 Scope of Analysis: What Each Tool Actually Checks

ToolScans package.jsonAnalyzes Source CodeChecks node_modulesScans Public AssetsUnderstands Transitive Deps
depcheck✅ (static imports)
npm-check-updates
retire✅ (frontend libs only)⚠️ (limited)
snyk⚠️ (via deps)

💡 Note: snyk uses your package-lock.json or yarn.lock to reconstruct the full dependency graph, including transitive dependencies that may not appear in package.json.

🧪 Real-World Workflow Integration

Scenario: Preparing for a Production Release

  1. Clean dead code: Run depcheck to remove unused deps → reduces bundle size and attack surface.
  2. Update safely: Run npm-check-updates -u to bump to latest non-breaking versions.
  3. Scan frontend: Run retire to catch vulnerable client-side libraries missed by other tools.
  4. Deep security audit: Run snyk test to find and snyk fix to patch remaining vulnerabilities.

This layered approach catches issues no single tool can address alone.

Scenario: Emergency Patch After Zero-Day Disclosure

  • Skip depcheck and npm-check-updates — they don’t understand exploit context.
  • Run snyk test immediately: it will tell you if you’re affected and how to fix it.
  • Use snyk monitor to get alerts on future vulnerabilities.

retire might help if the zero-day affects a frontend library, but it lacks remediation guidance.

⚠️ Limitations and Gotchas

  • depcheck may falsely flag packages used in non-standard ways (e.g., ESLint plugins, Webpack loaders). Use --ignores to suppress false positives.
  • npm-check-updates doesn’t guarantee compatibility — always test after major upgrades.
  • retire’s database is less comprehensive than Snyk’s and hasn’t seen frequent updates in recent years. Verify its findings against official advisories.
  • snyk requires authentication for full features (snyk auth), and the free tier has monthly scan limits. Offline mode is limited.

📊 When to Use Which Tool

GoalBest Tool(s)
Remove unused dependenciesdepcheck
Update to latest package versionsnpm-check-updates
Find vulnerable frontend JS librariesretire
Comprehensive security scanning & fixingsnyk
Routine dependency maintenancenpm-check-updates + snyk
Reducing bundle sizedepcheck

💡 Final Recommendation

Think of these tools as layers in a defense-in-depth strategy:

  • Start with depcheck to keep your dependency list honest.
  • Use npm-check-updates regularly to stay current.
  • Layer retire if you ship a lot of third-party frontend code.
  • Anchor everything with snyk for security-critical projects.

No single tool replaces the others — together, they give you visibility into usage, freshness, and risk across your entire JavaScript stack.

How to Choose: depcheck vs npm-check-updates vs snyk vs retire
  • depcheck:

    Choose depcheck when you need to identify and remove unused or extraneous npm dependencies from your project. It’s especially useful during refactoring, tech debt cleanup, or before major version upgrades to slim down package.json. However, be aware it may miss dynamically required modules (e.g., via require(variable)) or dependencies used only in build scripts or non-JavaScript files like CSS imports.

  • npm-check-updates:

    Choose npm-check-updates when your primary goal is to update dependencies to their latest compatible or major versions. It excels at showing what’s outdated and can automatically update package.json, making it ideal for routine maintenance. Use it before security scans to ensure you’re not fixing vulnerabilities in versions that could simply be upgraded.

  • snyk:

    Choose snyk when you require deep, actionable security intelligence across both frontend and backend JavaScript dependencies, including transitive ones. It identifies vulnerabilities with severity context, suggests precise upgrade paths or patches, and integrates into CI/CD pipelines. Note that full remediation features require authentication and may involve usage limits under the free tier.

  • retire:

    Choose retire if you specifically need to scan frontend JavaScript files (including those in node_modules) for known vulnerabilities in client-side libraries like jQuery, Bootstrap, or Angular. It’s lightweight and focused on browser-facing code but does not analyze server-side Node.js dependencies or provide fix recommendations beyond version updates.

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.