Plate 45
Should You Leave Depcheck? 26 Files Knip Caught
Knip 6.39.0 vs depcheck 1.4.7 on 95 JS files: median wall 574.574 ms vs 581.463 ms (wash). Knip: 26 unused files, 8 unused deps, 56 unused exports. Depcheck: 8 unused deps only. Both agreed on unused production deps.
Aditya Challa4 min read
On a 95-file JavaScript fixture, Knip 6.39.0 took a median 575 ms and depcheck 1.4.7 took 581 ms. Wall time was a wash. Knip also reported 26 unused files and 56 unused exports that depcheck does not look for, plus the same 8 unused production dependencies.
Short answer: leave depcheck for Knip when unused files and unused exports matter as much as unused packages. Keep depcheck when you only want a small package.json unused-deps check and nothing else. No affiliate links in this post.
What I tested
- Machine: 8 vCPU Intel Xeon / 15 GB RAM Linux cloud box, Node 20.19.2, tested 5 Oct 2026 (about 23:05 to 23:15 IST). Shared box; tools interleaved each round.
- Fixture: 95 files under
src/andscripts/(libs, pages, dead orphans, a CLI entry). Production dependencies included used packages (lodash-es,chalk,ms) and eight deliberately unused ones (moment,left-pad,is-odd,bluebird,request,jquery,axios, and one more unused util package). - Tools:
knip6.39.0 withknip.jsonentry pointssrc/index.jsandscripts/cli.js;depcheck1.4.7 with defaults. Timed via directnodeon each package bin. - Timing: one warmup each, then five interleaved warm runs. Median wall-clock of the full CLI call.
- Findings: Knip unused files 26, unused dependencies 8, unused exports 56 (exit 1). Depcheck unused dependencies 8 (exit 255). Both tools agreed on the unused production dependency set.
- One surprise: speed was effectively tied, so the leave-depcheck case is coverage, not milliseconds.
- Not tested: TypeScript project references, monorepo workspaces, Next.js / Nuxt plugin presets, unused types, unused class members, CI baseline ignore files, Windows/macOS, false-positive rates on a real production repo.
Does Knip find more than depcheck?
| Tool | Median | Runs (ms) | Unused deps | Unused files | Unused exports |
|---|---|---|---|---|---|
| Knip 6.39.0 | 575 ms | 570 / 562 / 586 / 582 / 575 | 8 | 26 | 56 |
| depcheck 1.4.7 | 581 ms | 712 / 683 / 563 / 581 / 581 | 8 | n/a | n/a |
On this fixture both CLIs finished in about 0.58 s. Depcheck answered the package.json question. Knip answered that plus unused files and unused exports. If your backlog is dead modules and dead exports, depcheck alone will not surface them.
Dead-code cleanup pairs with lint and format work. The Biome vs ESLint + Prettier post and the oxlint vs ESLint post are the related quality-gate decisions on this site; this post is the unused-code inventory step. Package install speed is a separate question covered in the pnpm vs npm vs Bun post.
What do you lose leaving depcheck?
depcheck is smaller and single-purpose. Teams that only gate on unused dependencies, and that already ignore unused files elsewhere, may not want Knip's broader report noise. Knip also needs entry and project globs; a wrong entry list can mark live files as unused.
Also expect to maintain an ignore list. Orphan scripts, intentional barrels, and generated clients often need explicit allow rules before Knip is green in CI. Re-run both tools on your own tree before deleting packages or files.
Should you leave depcheck for Knip?
| Situation | My pick |
|---|---|
| You care about unused files and unused exports, not only packages | Switch to Knip; keep an ignore list |
| You only want unused dependencies in package.json | Keep depcheck |
| Monorepo with clear entry points already listed for Knip | Knip is the better fit to evaluate |
| CI already fails on any unused-export noise you cannot afford | Stay on depcheck, or adopt Knip with a tight ignore |
| First PR would delete 26 orphan files without review | Inventory with Knip, then delete in small batches |
Bottom line: on 95 files, Knip and depcheck both took about 0.58 s, and Knip also found 26 unused files and 56 unused exports. Who should not switch yet: teams that only want a package.json unused-deps gate. Everyone else cleaning dead modules should measure their own tree the same way.
How this was made: I built the fixture, ran interleaved Knip and depcheck on the ShopperCove test box, and kept the timing JSON; the write-up was drafted with AI help and checked against that output.
Sources
- https://knip.dev/
- https://github.com/webpro-nl/knip
- https://github.com/depcheck/depcheck
- https://www.npmjs.com/package/knip
- https://www.npmjs.com/package/depcheck
Related
- https://www.shoppercove.com/blog/biome-vs-eslint-prettier
- https://www.shoppercove.com/blog/oxlint-vs-eslint
- https://www.shoppercove.com/blog/eslint-10-12-release-october-2026
- https://www.shoppercove.com/blog/pnpm-vs-npm-vs-bun
- https://www.shoppercove.com/blog/dprint-vs-prettier
- https://www.shoppercove.com/blog/typescript-7-should-you-upgrade
- https://www.shoppercove.com/blog/jest-vs-vitest
- https://www.shoppercove.com/blog/turborepo-2-11-7-sdkroot-oidc-cache-october-2026
Lab evidence
What I found running this
Hands-on on ShopperCove box 5 Oct 2026 ~23:05-23:15 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 20.19.2). Fixture: 95 files under src/ and scripts/ (libs, pages, dead orphans, CLI entry). Used deps: lodash-es, chalk, ms. Eight unused production deps planted. Versions: knip 6.39.0 (knip.json entries src/index.js + scripts/cli.js); depcheck 1.4.7 defaults. Timed via direct node on package bins. Wall medians (5 interleaved after warmup): knip 574.574 ms (570.489/561.889/586.158/581.712/574.574); depcheck 581.463 ms (711.614/683.255/562.828/581.463/581.206). Findings: knip unused files 26, unused deps 8, unused exports 56 (exit 1); depcheck unused deps 8 (exit 255). Raw: /workspace/bench-knip/res-knip.json. Not tested: TS project references, monorepo workspaces, Next/Nuxt presets, unused types, Windows/macOS, false-positive rate on a production repo. No affiliate.
Related links
Plate 16
ESLint v10.12.0: SourceCode tokens/comments types + rule fixes (2 Oct 2026)
ESLint published v10.12.0 on 2 October 2026 as a minor release: documentation and TypeScript types for SourceCode#getText(), getLoc(), and getRange() now accept tokens and comments (matching runtime behavior), plus multiple rule fixes including astral/Unicode letter handling and autofix edge cases. npm latest confirmed 10.12.0; ShopperCove docs checklist only; no affiliate.
5 Oct 2026
Plate 75
Turbo vs Lage: 1.97s vs 3.01s Cold Build
Turbo 2.11.7 vs Lage 2.17.0 on a 4-package diamond npm workspace (250k-iter build scripts): cold wall medians 1,974 ms vs 3,007 ms (~1.5x); Turbo warm 4/4 cache hits ~0.50 s; Lage warm ~1.49 s. Lage required git init.
5 Oct 2026
Plate 74
ncu vs npm outdated: 4 Majors Beyond Wanted
npm-check-updates 23.1.0 vs npm outdated on 7 stale deps (axios/eslint/lodash/prettier/react/typescript/vite): ncu proposed 4 majors (React 19, Vite 8, TypeScript 7, ESLint 10) while npm Wanted stayed in-range; wall medians 863 ms vs 783 ms.
5 Oct 2026