Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Audit and reduce JavaScript package dependency footprint across npm, pnpm, Yarn, and Bun projects. Use when asked to remove unused dependencies, deduplicate workspace dependency versions, lockfiles or node_modules, analyze direct dependencies' transitive lockfile closure, find low-risk upgrades that reduce dependency trees, inline trivial dependencies, or apply e18e dependency replacement recommendations.
.claude/skills/asymmetric-al-npm-deps-cleanup/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 53% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 31% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 126% | 0% |
| case-18 | ✗→✓ | ▲ Improved | 42% | 0% |
| case-20 | ✓→✗ | ▼ Worse | -21% | 0% |
Reduce JavaScript dependency footprint. Preserve the existing package manager, lockfile, workspace layout, and dependency range style unless there is a concrete reason to change them.
Use the repo's existing package manager. Prefer explicit package metadata before lockfiles:
packageManager in the root package.json.devEngines.packageManager.name in the root package.json.When devEngines.packageManager is present, use its name for npm, pnpm, Yarn, or Bun detection. Treat its version and onFail fields as policy signals, not as permission to change package managers.
Infer from lockfiles only when package metadata does not identify the package manager:
| Signal | Package manager | | -------------------------------------------- | --------------- | | package-lock.json or npm-shrinkwrap.json | npm | | pnpm-lock.yaml | pnpm | | yarn.lock | Yarn | | bun.lock or bun.lockb | Bun |
Use the matching command family:
| Action | npm | pnpm | Yarn | Bun | | ---------------------------- | ----------------------------- | -------------------------- | ------------------------------ | ------------------------------- | | Install/update lockfile | npm install | pnpm install | yarn install | bun install | | Remove direct dependency | npm uninstall <pkg> | pnpm remove <pkg> | yarn remove <pkg> | bun remove <pkg> | | Add/update direct dependency | npm install <pkg>@<version> | pnpm add <pkg>@<version> | yarn add <pkg>@<version> | bun add <pkg>@<version> | | Explain dependency | npm explain <pkg> | pnpm why <pkg> | yarn why <pkg> | bun pm why <pkg> if available | | Dedupe lockfile | npm dedupe | pnpm dedupe | yarn dedupe if available | reinstall and inspect | | One-off tools | npx <tool> | pnpm dlx <tool> | yarn dlx <tool> if available | bunx <tool> |
peerDependencies, optionalDependencies, package bin usage, test fixtures, and published package manifests as higher risk.node_modules size when available.Collect:
package.json files and workspace boundaries.dependencies, devDependencies, peerDependencies, optionalDependencies.Record baseline metrics before edits:
shgit status --short wc -l <lockfile>
If node_modules is installed, also estimate installed footprint with platform-appropriate filesystem tools. Do not make footprint cleanup depend on node_modules being present; lockfile reductions are the primary metric.
Use a static analyzer as a starting point, not as proof. Good candidates include knip, depcheck, or repo-native tooling if already configured. Run them through the detected package manager's one-off executor when they are not installed.
For each candidate:
If usage is only in a script or config, consider moving between dependencies and devDependencies instead of removing.
In monorepos, look for the same direct dependency declared with multiple versions/ranges across package manifests. Use existing policy first: exact pins, caret ranges, catalog/protocol usage, workspace protocol, or central constraints.
Good approaches:
syncpack list-mismatches or equivalent package-manager-neutral tooling for discovery.After deduping, reinstall and inspect both manifest and lockfile diffs.
Then consider the package manager's native lockfile dedupe command: npm dedupe, pnpm dedupe, or yarn dedupe when available. Bun has no direct equivalent; run bun install and inspect whether the lockfile converges. Apply these commands carefully because they may change transitive dependency resolution and introduce breakage even without manifest edits.
For each important direct dependency, estimate its closure: the set of transitive lockfile entries reachable from that direct dependency.
Report both:
Prefer deterministic measurement over guesses. Package-manager-neutral fallback:
Use npm explain, pnpm why, yarn why, or available package-manager graph commands to understand why large transitive packages exist. Rank dependencies by impact and risk, not just raw size.
Use closure rankings to target direct dependencies whose newer minor/patch versions reduce transitive dependencies.
For each candidate:
Avoid major upgrades unless the user explicitly accepts the migration risk.
Use closure rankings to find direct dependencies with small, obvious usage in the codebase but large transitive cost.
Inline only when all are true:
Prefer native APIs over new replacement dependencies when the required behavior is simple.
Consult e18e for additional removal and replacement candidates:
sh<runner> @e18e/cli analyze <runner> @e18e/cli migrate --dry-run
Replace <runner> with the detected one-off executor: npx, pnpm dlx, yarn dlx, or bunx.
Also check the e18e module replacements list at https://e18e.dev/docs/replacements/ for known alternatives. Treat recommendations as candidates, not mandates; verify bundle/runtime behavior and run tests.
Summarize outcomes with measured impact:
node_modules reduction when available.Call out risk explicitly when a removal depends on static analysis rather than runtime coverage.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 4,358 | 5,248 | +20% | 1 | 1 | 0% | 145 | 2,342 | +1515% | 0 | 0 | — |
case-02 | fail→fail | 8,131 | 4,464 | -45% | 1 | 1 | 0% | 1,254 | 2,338 | +86% | 0 | 0 | — |
case-03 | pass→pass | 9,792 | 3,050 | -69% | 1 | 1 | 0% | 1,560 | 2,704 | +73% | 0 | 0 | — |
case-04 | fail→pass | 12,117 | 6,440 | -47% | 1 | 1 | 0% | 2,028 | 3,111 | +53% | 0 | 0 | — |
case-05 | fail→fail | 8,635 | 9,365 | +8% | 1 | 1 | 0% | 1,383 | 3,791 | +174% | 0 | 0 | — |
case-06 | fail→fail | 12,218 | 15,601 | +28% | 1 | 1 | 0% | 2,238 | 4,969 | +122% | 0 | 0 | — |
case-07 | fail→pass | 18,248 | 12,686 | -30% | 1 | 1 | 0% | 3,328 | 4,345 | +31% | 0 | 0 | — |
case-08 | pass→pass | 11,099 | 5,482 | -51% | 1 | 1 | 0% | 1,844 | 3,106 | +68% | 0 | 0 | — |
case-09 | pass→pass | 7,939 | 3,733 | -53% | 1 | 1 | 0% | 1,258 | 2,790 | +122% | 0 | 0 | — |
case-10 | fail→pass | 7,103 | 2,726 | -62% | 1 | 1 | 0% | 1,090 | 2,459 | +126% | 0 | 0 | — |
case-11 | pass→pass | 9,517 | 6,642 | -30% | 1 | 1 | 0% | 1,600 | 3,176 | +99% | 0 | 0 | — |
case-12 | pass→pass | 11,123 | 6,737 | -39% | 1 | 1 | 0% | 1,842 | 3,230 | +75% | 0 | 0 | — |
case-13 | pass→pass | 10,119 | 6,300 | -38% | 1 | 1 | 0% | 1,715 | 3,093 | +80% | 0 | 0 | — |
case-14 | pass→pass | 5,715 | 3,445 | -40% | 1 | 1 | 0% | 940 | 2,662 | +183% | 0 | 0 | — |
case-15 | pass→pass | 12,083 | 9,649 | -20% | 1 | 1 | 0% | 1,978 | 3,594 | +82% | 0 | 0 | — |
case-16 | pass→pass | 8,089 | 7,334 | -9% | 1 | 1 | 0% | 1,407 | 3,394 | +141% | 0 | 0 | — |
case-17 | pass→pass | 15,130 | 10,853 | -28% | 1 | 1 | 0% | 2,385 | 3,791 | +59% | 0 | 0 | — |
case-18 | fail→pass | 10,364 | 3,272 | -68% | 1 | 1 | 0% | 1,854 | 2,629 | +42% | 0 | 0 | — |
case-19 | pass→pass | 13,801 | 4,394 | -68% | 1 | 1 | 0% | 2,249 | 2,864 | +27% | 0 | 0 | — |
case-20 | pass→fail | 17,605 | 5,869 | -67% | 1 | 1 | 0% | 3,217 | 2,552 | -21% | 0 | 0 | — |
case-21 | pass→pass | 9,017 | 11,135 | +23% | 1 | 1 | 0% | 1,678 | 4,235 | +152% | 0 | 0 | — |
case-22 | pass→pass | 19,809 | 18,553 | -6% | 1 | 1 | 0% | 3,554 | 5,614 | +58% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 19 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +14 percentage points is the difference between those two pass rates over the 19 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.