Find and safely remove unused ("dead") npm dependencies in RedisInsight using a grep + leaf-check + build-gate recipe. Use when cleaning up dependencies, investigating whether a package is still used, removing a suspected leftover, or when the user mentions dead deps, unused dependencies, dependency cleanup, leftover packages, or "is this safe to remove". Complements the weekly vulnerability audit (`scripts/dependency-audit-report.mjs`), which only reports vulnerabilities.
74
91%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Identify and safely remove unused npm dependencies. This is a local, interactive workflow — a scheduled report can only ever guess; confirming a dependency is dead requires grepping real usage and running the build.
Static tools over-report badly in this repo and must not be trusted blindly:
package.json is a mega-manifest (UI + desktop + build + test
import: webpack loaders
and eslint/jest/babel plugins by string in config, tools invoked from
package.json scripts, runtime -r preloads, dynamic require, and
ambient @types/*.The reliable signal is: grep for usage → confirm it's a leaf → remove it and
run the build gate. That is exactly how jsonpath was confirmed dead and
removed (worked example at the bottom).
PKG=jsonpath # the dependency to check
grep -rn "$PKG" \
redisinsight configs scripts tests .storybook \
--include=*.ts --include=*.tsx --include=*.js --include=*.jsx \
--include=*.mjs --include=*.cjs --include=*.json \
2>/dev/null | grep -v node_modulesLook for import ... from '$PKG', require('$PKG'), import('$PKG'), and
bare references. Ignore unrelated substring hits (e.g. nestjs-form-data when
checking form-data, or a package name appearing only in tutorial/manifest
text). Zero real references → candidate for the next steps.
A clean grep is necessary but not sufficient. Check the ways a package is
used without an import:
.eslintrc.js, configs/webpack.config.*.ts,
redisinsight/ui/vite.config.mjs, jest.config.cjs, babel.config.cjs,
electron-builder.json, .mocharc*. eslint plugins, webpack loaders, and
jest/mocha reporters live here.package.json scripts — a tool like concurrently, lint-staged, or a
reporter is "used" if a scripts entry (any workspace) invokes it.node -r <pkg>, require(variable), or a
wasm/worker loader with a computed path.npm ls "$PKG" # in the workspace that declares itConfirm nothing else in the tree depends on it, and note any transitive deps it
uniquely pulls (removing jsonpath also dropped underscore).
| Situation | Action |
|---|---|
| Plain runtime/dev dep, zero references anywhere | Delete (after the gate below) |
@types/x where base x bundles its own types (node_modules/x/package.json has types/typings) | Delete — the DefinitelyTyped package is obsolete |
@types/x that's ambient/global-only (e.g. @types/webpack-env) | Keep — never imported by design |
Declared in more than one workspace (package.json), used in only one | Relocate/dedupe — remove the unused declaration, never the used copy |
Shadows a Node builtin (buffer, assert, …) | Keep — usually a false positive |
Referenced only in a config/scripts (step 2 hit) | Keep |
Remove it, reinstall (per the repo's dependency rules — never hand-edit
package.json/lockfile, never --ignore-scripts), and verify the affected
area builds:
npm uninstall "$PKG" # in the declaring workspace; updates the lockfile
npm run type-check # or the affected workspace's type-check
npm run test # / test:api, as relevant
npm run build # if it's a build-time depGreen across the relevant checks = safe. Commit the package.json +
package-lock.json change (see the git-safety / dependency rules in
CLAUDE.md). If anything goes red, it wasn't dead — restore it.
To triage the whole surface rather than one package, list declared deps and grep each for an import, then apply steps 2–5 to the ones with zero hits:
node -e "const p=require('./package.json');console.log([...Object.keys(p.dependencies||{}),...Object.keys(p.devDependencies||{})].join('\n'))" \
| while read PKG; do
hits=$(grep -rl --include=*.ts --include=*.tsx --include=*.js --include=*.jsx --include=*.mjs \
-e "from ['\"]$PKG" -e "require(['\"]$PKG" redisinsight configs scripts tests 2>/dev/null | grep -vc node_modules)
[ "$hits" = "0" ] && echo "candidate: $PKG"
doneThis is a first filter only — every candidate still goes through steps 2–5. Expect false positives (config/string/dynamic/ambient use). Never delete straight from this list.
jsonpathmanifest.json; no import/require.npm ls jsonpath → a leaf; it was also the sole reason underscore was
installed.jsonpath + @types/jsonpath, npm install, npm run type-check
→ green. Confirmed dead; committed. (underscore dropped with it.)6029714
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.