Understand why your dependencies are bloated β and fix them safely.
Modern JavaScript projects silently accumulate multiple versions of the same package. After a few months of adding dependencies, you might have lodash@4.17.19 and lodash@4.17.21 installed simultaneously β pulled in by different tools like eslint, jest, or next.
This leads to:
- π’ Slower installs β
npm install/ CI pipelines download and extract duplicate packages - π¦ Larger bundles β your end users download the bloat too
- π Subtle runtime bugs β packages that check
instanceofsilently break when two versions exist
npm dedupe tells you what is duplicated. depopsy tells you why β and fixes it safely.
Zero install required. Run it at the root of any npm, yarn, or pnpm project:
npx depopsyFor a quick 3-line summary:
npx depopsy --simpleAnalyzing large dependency graph...
Detected Package Manager: npm
π¦ Dependency Health Report
ββββββββββββββββββββββββββββββββββββββββββββββββββ
π¨ Problem:
You have 19 duplicate dependencies
β ~1.89 MB wasted on disk
β Slower installs, larger bundles, subtle runtime bugs
π₯ Top Root Causes (you can act on)
These are the packages pulling in most duplicate dependencies.
1. jest β 19 duplicate packages
β These top root causes account for ~89% of your duplication.
π― Why this matters
Β· Multiple versions of the same package increase bundle size
Β· Slows npm install / pnpm install / CI pipelines
Β· Can cause subtle runtime bugs when packages check instanceof
π§ What you should do
βΆ jest
Confidence: LOW β manual review required
Introduces: ansi-styles, chalk, ansi-regex, semver (+15 more)
β Test tooling often bundles its own utility versions.
β Upgrade jest to latest β may resolve 19 duplicate chains.
β‘ Quick Fix
Run: npx depopsy fix
(applies 0 SAFE fixes automatically β no breaking changes)
π Summary
ββββββββββββββββββββββββββββββββββββββββββββββββββ
β SAFE issues: 0 (auto-fixable)
β RISKY issues: 19 (manual review)
ββββββββββββββββββββββββββββββββββββββββββββββββββ
π‘ Tip: Even well-maintained projects have duplicates.
This tool explains *why* β not just what.
| Command | Description |
|---|---|
npx depopsy |
Full dependency health report |
npx depopsy --simple |
Top 3 root causes only |
npx depopsy --verbose |
Full breakdown of every group |
npx depopsy --top <n> |
Limit root cause output to top N groups |
npx depopsy --json |
JSON output for CI/CD pipelines |
npx depopsy --ci |
Minimal JSON with correct exit codes |
npx depopsy fix |
Dry-run: preview safe deduplication fixes |
npx depopsy fix --yes |
Apply fixes directly to package.json |
npx depopsy trace <pkg> |
Trace which top-level dep introduces <pkg> |
| Code | Meaning |
|---|---|
0 |
Success β no duplicates found |
1 |
Duplicates found |
2 |
Fatal error (no lockfile, parse failure, etc.) |
1. Parses your lockfile β package-lock.json, yarn.lock, or pnpm-lock.yaml
2. Builds a dependency graph β maps every package to its introducers
3. Detects duplicates β packages installed at multiple versions
4. Identifies root causes β which top-level dep (eslint, jest, next) is responsible
5. Suggests safe fixes β only semver-compatible consolidations
The attribution engine uses a 3-layer priority system to find the most actionable signal:
roots[]β Pre-computed top-level introducers via graph traversal (most accurate)parents[]β Immediate dependents (closer signal than full ancestor chain)ancestors[]β Full flattened chain (last resort, only when no better signal exists)
Low-level utility packages (chalk, semver, minimatch, glob, etc.) are automatically suppressed from root cause output β they are always indirect symptoms, never causes.
| Feature | Detail |
|---|---|
| β Multi-lockfile | npm (package-lock.json), yarn (yarn.lock), pnpm (pnpm-lock.yaml) |
| β Root cause analysis | Identifies which top-level dep pulls in each duplicate |
| β Safe fixes only | Backs up package.json before writing; never touches RISKY diffs |
| β CI/CD ready | --json and --ci flags with correct exit codes |
| β Zero config | Works instantly in any project root β no setup required |
| β Monorepo aware | Skips internal workspace packages (link:, workspace:, file:) |
| β Disk waste measurement | Actual on-disk byte measurement of duplicate package directories |
| β Package manager detection | Auto-detects npm / yarn / pnpm from lockfile presence |
| β Yarn v1 + v2+ | Handles both classic and modern Yarn lockfile formats |
| β pnpm v5βv9 | Handles all pnpm lockfile versions including v9 snapshots |
depopsy fix only touches SAFE duplicates β packages where all versions share the same major version (semver-compatible).
# Preview what would change (no files modified)
npx depopsy fix
# Apply changes to package.json
npx depopsy fix --yesAfter running fix --yes, you must reinstall to apply the overrides to your lockfile:
npm install # or yarn install / pnpm install| Package manager | What gets written |
|---|---|
| npm | "overrides" in package.json |
| yarn | "resolutions" in package.json |
| pnpm | "pnpm.overrides" in package.json |
A backup of your original package.json is saved to .depopsy-backup/ before any write.
Trace exactly which top-level dependencies are responsible for pulling in a given package:
npx depopsy trace semverTracing "semver" through dependency graph...
π Trace: semver
ββββββββββββββββββββββββββββββββββββββββββββββββββ
Versions found: 5.7.2, 7.5.4, 7.6.0
Safety: RISKY
semver is introduced by:
βΆ jest
βΆ eslint
βΆ @babel/core
Per-version breakdown:
5.7.2 β required by: node-semver, validate-npm-package-version
7.5.4 β required by: jest-runner, jest-resolve
7.6.0 β required by: eslint, @babel/core
ββββββββββββββββββββββββββββββββββββββββββββββββββ
β No auto-fix available β versions span multiple majors.
- name: Check for duplicate dependencies
run: npx depopsy --ci
# Exits 1 if duplicates found, 0 if cleannpx depopsy --json > dep-report.json{
"summary": {
"total": 19,
"safe": 4,
"risky": 15,
"wasteKB": "1934.22"
},
"rootCauses": [...],
"duplicates": [...],
"suggestions": [...]
}Q: How is this different from npm dedupe?
npm dedupe reorganizes node_modules at install time but doesn't prevent the problem from recurring. depopsy analyzes your lockfile to explain the root cause and writes overrides/resolutions to your package.json β so the deduplication survives a fresh npm install.
Q: Is it safe to run on production projects?
Yes. The analyze and trace commands are fully read-only. The fix command defaults to a dry-run β you must explicitly pass --yes to make changes, and it always creates a backup first.
Q: Does it work with workspaces / monorepos?
Yes. It automatically detects workspace packages and excludes them from root cause attribution (they use link:, workspace:, or file: version strings in lockfiles).
Q: Why does it show "RISKY" for some duplicates?
RISKY means the duplicate versions span multiple major versions (e.g., react@17 and react@18). These cannot be safely auto-aligned because major version bumps can include breaking changes. Use depopsy trace <pkg> to understand which dependency is causing it.
Q: Why don't I see semver or chalk as root causes?
These are leaf utility packages β they are always pulled in transitively, never directly causing bloat. depopsy suppresses them from root cause output to keep results actionable. Use --verbose or trace to inspect them.
- Node.js
>= 18.0.0 - A project with at least one lockfile:
package-lock.json,yarn.lock, orpnpm-lock.yaml
git clone https://github.com/zmrishh/depopsy
cd depopsy
npm install
npm testPlease open an issue before submitting a pull request for significant changes.
MIT Β© 2026 depopsy contributors