About knip
knip is a repository guidance skill for configuring Knip to detect unused files, exports, and dependencies while limiting false positives. It helps developers review Knip findings and keep checks meaningful without broadly disabling them.
Key features
- 01Guidance for knip.jsonc configuration
- 02Rules for preserving export checks
- 03Handling generated shadcn/ui files
- 04Managing CSS-imported dependencies
- 05Ordered approach to reducing noise
Use cases
- 01Setting up Knip in a repository
- 02Reviewing and responding to Knip findings
- 03Auditing ignore entries and exclusions
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ liaoann/ skills --skill knipAfter installing, type/knipin Claude Code to confirm it loaded.
Details
From the project READMEKnip
Setting up Knip (unused files / exports / dependencies detector) so it keeps catching real dead code without drowning you in false positives.
Scope
Use when the change touches a Knip config or responds to Knip output. Guidance, not a procedure.
Rules
Config lives in knip.jsonc
Not knip.json, not knip.ts, not a package.json key. JSONC allows comments, and every ignore entry needs a written reason next to it — a bare package name in ignoreDependencies is unreviewable a month later.
{
"$schema": "https://unpkg.com/knip@6/schema-jsonc.json",
"entry": ["src/index.ts"],
"project": ["src/**/*.{ts,tsx}"]
}
Only use knip.ts when the config needs a compilers function, which cannot be expressed as data.
Never set ignoreExportsUsedInFile
An exported type/interface that only its own file's functions use is a local type wearing an export keyword. Knip's default (false) reports it — that is the finding you want. Setting it to true, or granularly to { "interface": true, "type": true }, deletes the check. Same for excluding the types issue type to make CI green.
The fix for such a finding is to remove the export keyword. If one export genuinely must stay public, tag that symbol (/** @public */ plus "tags": ["-public"]) rather than relaxing the global option.
shadcn/ui: ignore the generated directory
{
// Generated by shadcn/ui — not hand-authored, do not prune.
"ignore": ["src/components/ui/**"]
}
Those files are vendored and ship with unused variants; pruning them just loses the next shadcn add. Match the path to the project's components.json alias.
Consequence: ignore drops the files from the graph, so packages used only there (radix, class-variance-authority, clsx, tailwind-merge, lucide-react, …) now report as unused — add the ones the project has to ignoreDependencies. If that list gets long, use "entry": ["src/components/ui/**"] instead: exports go unreported and imports still count.
CSS-imported packages go in ignoreDependencies
Tailwind v4 is wired from CSS (@import "tailwindcss"), which Knip does not scan, so it reports a false positive.
{
"ignoreDependencies": [
// Imported from CSS, invisible to the module graph.
"tailwindcss",
"tw-animate-css"
]
}
Grep the stylesheets before deleting any dependency Knip flags.
Fix noise in this order
entry/project globs → plugin config → targeted ignores (ignoreDependencies, ignoreFiles, a tag) → ignore last. Never quiet a finding by widening top-level exclude; that kills the check repo-wide to hide one instance.
Completion Criterion
- Config is
knip.jsoncwith theschema-jsonc.json$schema(unlesscompilersforcesknip.ts). ignoreExportsUsedInFileis unset, andtypesis not excluded.- Every
ignore/ignoreFiles/ignoreDependenciesentry has a comment saying why. - shadcn's
components/ui/**is ignored or set asentry; if ignored, its exclusive dependencies are listed. - CSS-imported packages are in
ignoreDependencies, not removed frompackage.json. knipruns clean with no check disabled repo-wide.