unused-package-deps
Check whether dependencies declared in package.json are actually used in this Citado monorepo. Use whenever the task is to audit unused dependencies, clean up package manifests, decide whether a package belongs in dependencies or devDependencies, confirm Knip results, or explain why a dependency should stay, move, or be removed. Also use for prompts like “检查未使用依赖”, “哪些依赖可以删”, “package.json 里有没有没用到的包”, or “为什么 Knip 报这个依赖没用”.
| Name | unused-package-deps |
|---|---|
| Path | unused-package-deps |
| Version | 1.0.0 |
| Origin | local |
| Source | SkillHub |
| Author | seekthought |
| Project | citado |
| Tags | dependencies knip monorepo cleanup package-json |
| License | MIT |
Install
skillctl install -r skillhub unused-package-deps
Purpose
Audit package.json dependencies with evidence. Do not blindly delete packages based on a single tool report.
In this repo, dependency-cruiser is already used for module-boundary and import-graph checks, but it is not the primary tool for detecting unused package.json dependencies. For manifest-level auditing, prefer Knip and then verify each candidate with source/config searches.
Primary references
- Knip docs: https://knip.dev/
- Repo scripts in root
package.json:dep:check,dep:check:viewer,skill:validate
What counts as “used”?
A dependency is used if any of these are true:
- imported from runtime source files;
- imported from test files;
- imported from config files such as
vite.config.*,eslint.config.*,vitest.config.*,playwright.config.*; - referenced by package scripts or related hook files like
.husky/*; - imported from CSS, for example
@import 'tw-animate-css';; - required by the package as a direct dependency even if the monorepo root also declares it.
Important repo-specific rules
- Do not treat root
pnpm dep:checkas proof that a dependency is unused. Those commands check import graph constraints, not manifest necessity. - Prefer package-scoped analysis first, for example a single workspace such as
packages/fe. - Search
src,tests, and config files before trusting a tool result. - Ignore
distunless you are explaining why bundle output still contains a package. - In this monorepo, root dependencies can hide missing package-local declarations. Knip
--strictis useful for surfacing that.
Standard workflow
1. Read the target package manifest
- Read the target
package.json. - Read nearby config files and scripts that might consume tooling dependencies.
At minimum, check whether the package has:
vite.config.*eslint.config.*vitest.config.*playwright.config.*.husky/*- CSS entry files with
@import
2. Run Knip for declared dependency usage
Use package-scoped analysis first.
pnpm dlx knip --dependencies --workspace packages/fe
If runtime-vs-build classification matters, also run:
pnpm dlx knip --production --strict --dependencies --workspace packages/fe
Interpretation:
Unused dependencies: likely removable or misplaced runtime deps.Unused devDependencies: likely removable or declared in the wrong package.Unlisted dependencies: used in code/config but not declared directly in that package.Unresolved imports: may indicate alias/config issues and can reduce confidence; investigate separately.
3. Verify each hit with search
For every flagged package, search the workspace for actual usage.
Preferred checks:
- source import search
- test import search
- config file import search
- script and hook search
- CSS
@importsearch
Typical commands:
rg "@tailwindcss/vite|vite-plugin-raw|wrangler" packages/fe
rg "@trpc/client|superjson" packages/fe
rg "shadcn|husky|lint-staged" packages/fe
4. Classify findings before editing
Each candidate should end in exactly one bucket:
remove: declared but not used anywhere relevantkeep: actually usedmove to dependencies: used by runtime code or CSS importsmove to devDependencies: only used by config, build, test, or scriptsadd missing direct dependency: used by the package but only declared elsewherefalse positive: tool limitation or incomplete monorepo/plugin configuration
5. Edit only after classification is clear
When the user asks to clean the manifest:
- remove only high-confidence
removeitems; - move packages between
dependenciesanddevDependencieswhen the usage type is wrong; - add missing direct dependencies when source/config imports prove the package is required.
6. Re-run checks after changes
- Re-run the same Knip command for the target workspace.
- Run the package-local gate, usually
pnpm run checkinside the touched package.
High-value heuristics
Runtime/build split
- Imported by application source or CSS entrypoint: usually
dependencies. - Imported only by Vite, ESLint, Vitest, Playwright, scripts, or hooks: usually
devDependencies.
Common false positives
Be careful with these:
- Vite plugins imported only in
vite.config.ts - ESLint plugins imported only in
eslint.config.* - CLI tools used only in
package.jsonscripts - Husky and lint-staged referenced through hook files and script names
- CSS-only packages imported through
@import - Monorepo root deps that hide a package-local missing direct dependency
- Path alias and test setup issues causing unrelated Knip noise
Citado-specific examples
Example: config-only dependency is still used
If @tailwindcss/vite appears in vite.config.ts, it is used. It belongs in devDependencies, not removal.
Example: CSS import counts as runtime usage
If src/App.css contains @import 'tw-animate-css';, then tw-animate-css is a used dependency and should not be removed.
Example: root declaration does not excuse a missing package-local declaration
If packages/fe/src/shared/api/client/trpc-client.ts imports @trpc/client and superjson, but packages/fe/package.json does not declare them, classify them as add missing direct dependency for packages/fe.
Example: lint plugin should have an import site
If eslint-plugin-react is declared but eslint.config.* does not import or reference it, it is a strong removal candidate.
Fallback when Knip cannot run cleanly
If pnpm dlx knip is blocked by network, auth, or registry issues:
- Inspect package scripts and config files manually.
- Search imports with
rg. - Use
pnpm why <pkg>for install-path context. - Report that the audit is manual and lower confidence than a Knip-backed result.
Output expectations
When reporting findings, use this order:
- High-confidence removable dependencies.
- Dependencies that should stay.
- Dependencies that are declared in the wrong section.
- Missing direct dependencies that should be added.
- False positives or confidence caveats.
- Commands run and whether package checks passed.
Success criteria
The task is not complete until you have done both:
- a tool-backed scan, preferably with Knip;
- a manual verification pass for every dependency you recommend removing or moving.