Adopt Knip gradually
On a large or legacy codebase the first run can report a lot. Reaching zero in one sitting is then the wrong goal. Get a trustworthy signal first, then ratchet the codebase toward clean and keep it there.
Actionable baseline
Section titled “Actionable baseline”Most of the noise on a first run comes from gaps in what Knip can reach: a dependency that Knip does not have a plugin for yet, an entry point it can’t resolve, a phantom dependency. Fix the gaps before you delete anything:
- Address configuration hints.
- Tune entry and project files so Knip analyzes the right set of files.
- Tune configuration for your tools’ plugins.
Read the output from the top. One unused file hides its exports and dependencies, so files come first.
Once the report reflects real findings instead of gaps, you have an actionable baseline.
Focus one issue type at a time
Section titled “Focus one issue type at a time”Don’t fix everything at once. Narrow the report with filters:
knip --files # unused files only (the major cascade!)knip --dependencies # then dependenciesknip --exports # then exports and typesClear one type, commit, move to the next.
Stage by rules
Section titled “Stage by rules”Rules set a severity per issue type. Start by setting all types to
"warn", and then the types you’ve cleaned to "error". Warnings are printed
in gray, and they don’t fail the run. Example:
{ "rules": { "files": "error", "dependencies": "error", "exports": "warn", "duplicates": "off" }}As each "warn" type reaches zero, set it to "error". Keep iterating and
prune the codebase to perfection.
Gate CI without blocking the team
Section titled “Gate CI without blocking the team”Add Knip to CI as soon as you have a baseline, so new clutter is caught in review. A few ways to stage it:
- Mark cleaned types
"error"and the rest"warn", so CI fails only on the types you’ve finished. - Workspace by workspace: in a monorepo, scope passes with
--workspace(accepts multiple workspaces and glob patterns). - Production first:
--productionlimits analysis to shipped code, so you can clean what matters most and defer tests and tooling. - Set a budget, so CI fails only when the count exceeds the number (e.g.
knip --max-issues 50). This blocks regressions while you burn down the rest. - Run report-only with
--no-exit-codewhile you’re still triaging.
Suppress only what’s justified
Section titled “Suppress only what’s justified”When something is genuinely fine as-is, prefer a specific, documented signal
over a blanket ignore, for example:
- tag an export with e.g.
@lintignoreor@internal - use
ignoreExportsUsedInFilefor internal-only exports - list known exceptions in
ignoreDependencies
Resolving reported issues covers the right tool for each case.
ISC License © 2026 Lars Kappert