
Knip Deadcode
- 296 installs
- 191 repo stars
- Updated July 24, 2026
- pproenca/dot-skills
knip-deadcode is a Knip dead-code detection skill that configures analysis and CI cleanup for developers who need to find unused exports and dependencies in JavaScript or TypeScript codebases.
About
knip-deadcode from pproenca/dot-skills is a comprehensive guide for detecting and removing dead code in JavaScript and TypeScript projects using Knip. It contains 43 rules across 8 priority categories: Configuration Foundations, Entry Point Strategy, Workspace and Monorepo, Dependency Analysis, Export Detection, CI Integration, Auto-Fix Workflow, and Performance Optimization. The skill triggers on knip.json setup, unused exports, unused dependencies, bundle optimization, and suspected false positives. It recommends concrete entry-point strategies, monorepo workspace handling, dependency tracing, CI gating patterns, and safe auto-fix workflows for single-repo and monorepo setups. Developers reach for knip-deadcode when adopting Knip for the first time, tuning knip.json, adding dead-code checks to CI, or investigating why Knip flags certain files. Install via npx add-skill pproenca/dot-skills --skill knip-deadcode.
- knip-deadcode
Knip Deadcode by the numbers
- 296 all-time installs (skills.sh)
- +11 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #1,361 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/pproenca/dot-skills --skill knip-deadcodeAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 296 |
|---|---|
| repo stars | ★ 191 |
| Last updated | July 24, 2026 |
| Repository | pproenca/dot-skills ↗ |
How do you configure Knip for dead code cleanup?
Use knip-deadcode for development tasks
Who is it for?
JavaScript or TypeScript developers adopting Knip in single-repo or monorepo projects who need reliable dead-code detection and CI integration.
Skip if: Codebases without npm-style module graphs or teams that only need runtime profiling instead of static unused-export analysis.
When should I use this skill?
A developer mentions knip.json, dead code, unused exports, unused dependencies, or bundle optimization in a JS/TS project.
What you get
Tuned knip.json config, prioritized dead-code findings report, CI gate setup, and safe auto-fix workflow for unused exports and dependencies.
- knip.json configuration
- CI dead-code gate
- prioritized cleanup report
By the numbers
- Contains 43 Knip dead-code rules across 8 priority categories
- Covers 8 categories from config foundations through performance optimization
Files
Community Knip Dead Code Detection Best Practices
Comprehensive guide for detecting and removing dead code in JavaScript and TypeScript projects using Knip. Contains 43 rules across 8 categories, prioritized by impact to guide configuration, CI integration, and cleanup workflows.
When to Apply
Reference these guidelines when:
- Configuring Knip for a new project or monorepo
- Investigating false positives or false negatives
- Setting up CI pipelines to prevent dead code regressions
- Using auto-fix to clean up unused code
- Optimizing Knip performance for large codebases
Rule Categories by Priority
| Priority | Category | Impact | Prefix |
|---|---|---|---|
| 1 | Configuration Foundations | CRITICAL | config- |
| 2 | Entry Point Strategy | CRITICAL | entry- |
| 3 | Workspace & Monorepo | HIGH | workspace- |
| 4 | Dependency Analysis | HIGH | deps- |
| 5 | Export Detection | MEDIUM-HIGH | exports- |
| 6 | CI Integration | MEDIUM | ci- |
| 7 | Auto-Fix Workflow | MEDIUM | fix- |
| 8 | Performance Optimization | LOW-MEDIUM | perf- |
Quick Reference
1. Configuration Foundations (CRITICAL)
- `config-avoid-broad-ignore` - Avoid broad ignore patterns
- `config-configure-path-aliases` - Configure path aliases in Knip
- `config-enable-plugins-explicitly` - Enable framework plugins explicitly
- `config-run-without-config` - Run without config first for baseline
- `config-separate-entry-project` - Separate entry files from project files
- `config-use-json-schema` - Use JSON schema for configuration validation
- `config-use-negation-patterns` - Use negation patterns for exclusions
- `config-use-production-mode` - Use production mode for shipping code analysis
2. Entry Point Strategy (CRITICAL)
- `entry-add-dynamic-imports` - Add dynamic import targets as entry points
- `entry-exclude-test-files` - Exclude test files from production entries
- `entry-include-all-entry-points` - Include all application entry points
- `entry-include-bin-scripts` - Include binary scripts as entry points
- `entry-use-compilers` - Use compilers for non-standard file types
- `entry-use-plugin-entries` - Use plugin entry points for frameworks
- `entry-verify-with-debug` - Verify entry points with debug mode
3. Workspace & Monorepo (HIGH)
- `workspace-configure-root-workspace` - Configure root workspace explicitly
- `workspace-ignore-specific` - Ignore specific workspaces when needed
- `workspace-isolate-for-strict` - Isolate workspaces for strict dependency checking
- `workspace-list-cross-deps` - List cross-workspace dependencies explicitly
- `workspace-per-workspace-plugins` - Configure plugins per workspace
- `workspace-use-workspace-globs` - Use workspace globs for consistent configuration
4. Dependency Analysis (HIGH)
- `deps-add-unlisted-deps` - Add unlisted dependencies to package.json
- `deps-avoid-transitive-reliance` - Avoid relying on transitive dependencies
- `deps-configure-plugin-deps` - Configure plugins for tool-specific dependencies
- `deps-fix-files-first` - Fix unused files before dependencies
- `deps-ignore-conditional-deps` - Ignore conditionally loaded dependencies
- `deps-remove-obsolete-types` - Remove obsolete type definition packages
5. Export Detection (MEDIUM-HIGH)
- `exports-check-class-members` - Check class members for unused code
- `exports-enable-entry-exports` - Enable entry export checking for private packages
- `exports-handle-reexports` - Handle re-exports in barrel files
- `exports-ignore-same-file` - Ignore exports used in same file
- `exports-tag-public-api` - Tag public API exports with JSDoc
- `exports-trace-usage` - Trace export usage before removal
- `exports-use-include-libs` - Use include libs for type-based consumption
6. CI Integration (MEDIUM)
- `ci-add-to-pipeline` - Add Knip to CI pipeline
- `ci-separate-production-check` - Separate production and default mode checks
- `ci-use-cache` - Enable cache for faster CI runs
- `ci-use-max-issues` - Use max issues for gradual adoption
- `ci-use-reporters` - Use appropriate reporters for CI output
- `ci-watch-mode-local` - Use watch mode for local development
7. Auto-Fix Workflow (MEDIUM)
- `fix-allow-remove-files` - Explicitly allow file removal
- `fix-format-after-fix` - Format code after auto-fix
- `fix-review-before-commit` - Review auto-fix changes before commit
- `fix-update-deps-after` - Update package manager after dependency fix
- `fix-use-fix-type` - Use fix type for targeted cleanup
8. Performance Optimization (LOW-MEDIUM)
- `perf-filter-issue-types` - Filter issue types for focused analysis
- `perf-limit-output` - Limit output for large codebases
- `perf-profile-performance` - Profile performance for slow analysis
- `perf-use-bun-runtime` - Use Bun runtime for faster analysis
- `perf-use-cache-flag` - Enable cache for repeated analysis
- `perf-use-workspace-filter` - Filter workspaces for faster monorepo analysis
How to Use
Read individual reference files for detailed explanations and code examples:
- Section definitions - Category structure and impact levels
- Rule template - Template for adding new rules
Reference Files
| File | Description |
|---|---|
| references/_sections.md | Category definitions and ordering |
| assets/templates/_template.md | Template for new rules |
| metadata.json | Version and reference information |
{Rule Title}
{1-3 sentences explaining WHY this matters. Focus on dead code detection implications.}
Incorrect ({what's wrong}):
{Bad configuration example}{Bad code example if relevant}Correct ({what's right}):
{Good configuration example}{Good code example if relevant}{Optional sections as needed:}
Alternative ({context}): {Alternative approach when applicable}
When NOT to use this pattern:
- {Exception 1}
- {Exception 2}
Benefits:
- {Benefit 1}
- {Benefit 2}
Reference: [{Reference Title}]({Reference URL})
{
"name": "knip-deadcode",
"version": "1.1.7",
"organization": "Community",
"technology": "Knip",
"date": "January 2026",
"abstract": "Comprehensive guide for detecting and removing dead code in JavaScript and TypeScript projects using Knip. Contains 43 rules across 8 categories, prioritized by impact from critical (configuration and entry points) to incremental (performance optimization). Each rule includes detailed explanations, real-world examples comparing incorrect vs. correct configurations, and specific guidance for monorepos, CI integration, and auto-fix workflows.",
"references": [
"https://knip.dev",
"https://github.com/webpro-nl/knip",
"https://knip.dev/reference/configuration",
"https://knip.dev/guides/handling-issues",
"https://knip.dev/features/monorepos-and-workspaces",
"https://knip.dev/features/auto-fix",
"https://knip.dev/guides/using-knip-in-ci",
"https://effectivetypescript.com/2023/07/29/knip/"
]
}
Sections
This file defines all sections, their ordering, impact levels, and descriptions. The section ID (in parentheses) is the filename prefix used to group rules.
---
1. Configuration Foundations (config)
Impact: CRITICAL Description: Proper entry and project file configuration prevents false positives and ensures all dead code is detected. Misconfiguration is the #1 cause of missed issues.
2. Entry Point Strategy (entry)
Impact: CRITICAL Description: Entry files determine the analysis scope. Missing entries cause missed dead code; incorrect entries cause false positives across the entire codebase.
3. Workspace & Monorepo (workspace)
Impact: HIGH Description: Monorepo misconfiguration causes cross-workspace false positives and missed dependencies. Each workspace requires explicit configuration.
4. Dependency Analysis (deps)
Impact: HIGH Description: Detecting unused dependencies reduces bundle size, install time, and security surface. Proper plugin configuration catches tool-specific dependencies.
5. Export Detection (exports)
Impact: MEDIUM-HIGH Description: Unused exports inflate bundles and obscure codebases. Correct configuration catches dead exports while respecting intentional public APIs.
6. CI Integration (ci)
Impact: MEDIUM Description: CI integration prevents dead code regressions. Proper setup ensures fast feedback without blocking legitimate changes.
7. Auto-Fix Workflow (fix)
Impact: MEDIUM Description: Safe auto-fix workflows prevent accidental code loss while maximizing cleanup efficiency. Always review changes before committing.
8. Performance Optimization (perf)
Impact: LOW-MEDIUM Description: Caching, filtering, and mode selection optimize analysis speed for large codebases. Essential for monorepos with 100k+ files.
Add Knip to CI Pipeline
Run Knip in CI to catch dead code before it merges. This prevents accumulation of unused files, dependencies, and exports.
Incorrect (no CI check, dead code accumulates):
# No Knip step in CI
name: CI
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm testCorrect (Knip check in CI):
name: CI
on: push
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci --ignore-scripts
- run: npx knipAdd to package.json scripts:
{
"scripts": {
"knip": "knip",
"lint": "eslint . && knip"
}
}Reference: Using Knip in CI
Separate Production and Default Mode Checks
Run both production mode and default mode in CI. Production catches shipping code issues; default catches dev tooling waste.
Incorrect (single mode misses issues):
- run: npx knip --production
# Misses unused test utilities, dev dependenciesCorrect (both modes for comprehensive analysis):
jobs:
knip-production:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci
- run: npx knip --production
name: Check production code
knip-all:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci
- run: npx knip
name: Check all code including devPriority order: 1. Production mode failures are critical (affects users) 2. Default mode failures are important (affects developers)
Reference: Production Mode
Enable Cache for Faster CI Runs
Enable Knip's built-in cache for 10-40% faster analysis on subsequent runs. Cache persists analysis results between CI runs.
Incorrect (full analysis every run):
- run: npx knipCorrect (cache enabled for speed):
- name: Cache Knip results
uses: actions/cache@v4
with:
path: node_modules/.cache/knip
key: knip-${{ hashFiles('**/package-lock.json') }}
restore-keys: knip-
- run: npx knip --cacheSet custom cache location:
knip --cache --cache-location .cache/knipIn configuration:
{
"cache": true
}Note: Cache invalidates when dependencies change. The cache key should include lock file hash for correctness.
Reference: Knip CLI
Use Max Issues for Gradual Adoption
Use --max-issues to set a threshold for acceptable issues. This enables gradual adoption without blocking existing PRs while preventing new dead code.
Incorrect (all-or-nothing blocks adoption):
- run: npx knip # Fails with 500 existing issues
# Team disables Knip because it blocks all PRsCorrect (threshold allows gradual cleanup):
- run: npx knip --max-issues 100
# Passes if issues ≤ 100, fails if new dead code addedGradual reduction strategy:
# Week 1: Baseline
- run: npx knip --max-issues 500
# Week 2: After cleanup sprint
- run: npx knip --max-issues 300
# Week 4: Target achieved
- run: npx knip --max-issues 0Alternative: Warn without blocking:
- run: npx knip --no-exit-code
# Reports issues but doesn't fail the buildReference: Knip CLI
Use Appropriate Reporters for CI Output
Choose the right reporter for your CI environment. Different reporters optimize for different use cases.
Incorrect (default output hard to parse in CI):
- run: npx knip
# Long list, hard to find relevant issuesCorrect (reporter optimized for CI):
# GitHub Actions annotations
- run: npx knip --reporter github-actions
# Compact for quick overview
- run: npx knip --reporter compact
# JSON for programmatic processing
- run: npx knip --reporter json > knip-report.jsonAvailable reporters:
symbols(default) - Grouped by issue type with symbolscompact- One line per issuegithub-actions- GitHub annotations on filesjson- Machine-readable outputmarkdown- Documentation formatcodeowners- Grouped by code owners
Combine with max-show-issues:
- run: npx knip --reporter compact --max-show-issues 20Reference: Knip CLI
Use Watch Mode for Local Development
Use --watch during development to get instant feedback on dead code. Knip re-analyzes when files change.
Incorrect (manual runs after each change):
# Make changes
knip
# Make more changes
knip
# Repeat...Correct (continuous analysis with watch):
knip --watchOutput updates as you save files:
Watching for file changes...
[12:34:56] Change detected: src/utils.ts
[12:34:57] ✓ No issues found
[12:35:10] Change detected: src/legacy.ts
[12:35:11] Found 2 unused exports
- formatLegacyDate
- parseLegacyStringCombine with filters for focused feedback:
knip --watch --include exports
# Only watches for unused exportsWhen to use watch mode:
- During refactoring sessions
- When cleaning up dead code
- When learning codebase structure
Note: Watch mode is for local development, not CI.
Reference: Knip CLI
Avoid Broad Ignore Patterns
Broad ignore patterns hide legitimate issues along with false positives. Use targeted ignores with specific options instead.
Incorrect (hides all issues in generated files):
{
"ignore": ["src/generated/**"]
}Hides unused files, exports, dependencies, and all other issues in generated files.
Correct (only unused files hidden, other issues still reported):
{
"ignoreFiles": ["src/generated/**"]
}Only hides unused file reports; unused exports and dependencies in generated files are still caught.
Alternative (suppress specific issue type per pattern):
{
"ignoreIssues": {
"exports": ["src/generated/**/*.ts"]
}
}Available targeted ignore options:
ignoreDependencies: Suppress unused dependency reportsignoreFiles: Exclude from unused files detection onlyignoreBinaries: Exclude missing binariesignoreMembers: Exclude class/enum membersignoreUnresolved: Exclude unresolved importsignoreIssues: Suppress specific issue types per pattern
Reference: Knip Configuration
Configure Path Aliases in Knip
Configure path aliases in knip.json to match your tsconfig.json or bundler config. Unresolved aliases cause false positive unused file reports.
Incorrect (aliases not configured, imports unresolved):
{
"entry": ["src/index.ts"],
"project": ["src/**/*.ts"]
}Correct (aliases match tsconfig.json):
{
"paths": {
"@lib": ["./src/lib/index.ts"],
"@lib/*": ["./src/lib/*"],
"@components/*": ["./src/components/*"],
"@utils/*": ["./src/utils/*"]
},
"entry": ["src/index.ts"],
"project": ["src/**/*.ts"]
}Alternative (use tsconfig directly):
knip --tsConfig tsconfig.jsonNote: Knip reads paths from tsconfig.json by default. Only add paths to knip.json if they differ or tsconfig is not in the root.
Reference: Knip Configuration - Paths
Enable Framework Plugins Explicitly
Knip auto-detects many plugins, but explicit configuration ensures correct entry points for your framework and prevents missed dead code.
Incorrect (relying on auto-detection, missing custom config paths):
{
"entry": ["src/index.ts"]
}Correct (explicit plugin configuration):
{
"next": {
"entry": ["pages/**/*.tsx", "app/**/*.tsx", "middleware.ts"]
},
"jest": {
"config": "jest.config.ts",
"entry": ["**/*.test.ts", "**/*.spec.ts"]
},
"storybook": {
"entry": [".storybook/main.ts", "**/*.stories.tsx"]
}
}Disable unused plugins:
{
"webpack": false,
"rollup": false
}Reference: Knip Plugins
Run Without Config First for Baseline
Run Knip without configuration first to see what it detects automatically. This establishes a baseline before adding custom configuration.
Incorrect (over-configuring immediately):
{
"entry": ["src/**/*.ts"],
"project": ["src/**/*.ts"],
"ignore": ["src/legacy/**"],
"ignoreDependencies": ["lodash", "react"]
}Correct (baseline first, then configure):
# Step 1: Run without config
npx knip
# Step 2: Observe auto-detected plugins
# "Enabled plugins: next, jest, eslint"
# Step 3: Note false positives
# Check if they're config issues or real unused code
# Step 4: Add minimal configuration only for actual issues{
"$schema": "https://unpkg.com/knip@5/schema.json"
}Use debug to see what Knip detects:
knip --debugShows: enabled plugins, detected entries, workspace configs.
Reference: Configuration
Separate Entry Files from Project Files
Entry files define starting points for dependency resolution. Project files define the full scope of files to check for unused status. Mixing them causes false positives.
Incorrect (tests included in entry, production code appears used):
{
"entry": ["src/**/*.ts"],
"project": ["src/**/*.ts"]
}Correct (entry for production, project for all files):
{
"entry": ["src/index.ts", "src/cli.ts"],
"project": ["src/**/*.ts", "!src/**/*.test.ts"]
}Note: Files in project but not reachable from entry are reported as unused. This is the intended behavior for detecting orphaned files.
Reference: Configuring Project Files
Use JSON Schema for Configuration Validation
Add JSON schema to your knip.json for IDE autocompletion and instant validation of configuration options.
Incorrect (no validation, typos undetected):
{
"enrty": ["src/index.ts"],
"projetc": ["src/**/*.ts"]
}Correct (schema validates configuration):
{
"$schema": "https://unpkg.com/knip@5/schema.json",
"entry": ["src/index.ts"],
"project": ["src/**/*.ts"]
}Alternative (JSONC with comments):
{
"$schema": "https://unpkg.com/knip@5/schema-jsonc.json",
// Entry points for analysis
"entry": ["src/index.ts"],
"project": ["src/**/*.ts"]
}Reference: Knip Configuration
Use Negation Patterns for Exclusions
Use ! prefix in glob patterns to exclude specific files from entry or project patterns. This is more precise than using ignore.
Incorrect (broad ignore hides legitimate issues):
{
"entry": ["src/**/*.ts"],
"ignore": ["src/generated/**"]
}Correct (negation in pattern, scoped exclusion):
{
"entry": ["src/**/*.ts", "!src/generated/**/*.ts"],
"project": ["src/**/*.ts", "!src/**/*.generated.ts"]
}When to use `ignore` vs negation:
- Negation patterns: Exclude from specific entry/project arrays
ignore: Suppress all issue types for matching files globally
Reference: Knip Configuration
Use Production Mode for Shipping Code Analysis
Production mode analyzes only the code you ship, excluding tests, stories, and dev tooling. This catches dead code that affects bundle size and user experience.
Incorrect (default mode includes test dependencies):
knipCorrect (production mode for shipping code):
knip --productionConfiguration with production markers:
{
"entry": [
"src/index.ts!",
"src/cli.ts!"
],
"project": [
"src/**/*.ts!",
"!src/**/*.test.ts"
]
}The ! suffix marks patterns for production mode. Only these patterns are analyzed when running --production.
Strict production mode:
knip --production --strictStrict mode also enforces workspace isolation and includes peer dependencies.
Reference: Production Mode
Add Unlisted Dependencies to Package.json
Knip reports unlisted dependencies - packages imported in code but not in package.json. Add these to prevent runtime errors.
Incorrect (unlisted dependency works by accident):
// src/utils.ts
import dayjs from 'dayjs' // Not in package.jsonKnip reports: dayjs is unlisted.
Correct (dependency explicitly listed):
npm install dayjs{
"dependencies": {
"dayjs": "^1.11.0"
}
}Why unlisted dependencies are dangerous:
- May work locally due to hoisting or transitive deps
- Will fail in production or on other machines
- Package version is unpredictable
Auto-fix cannot help:
knip --fix
# Does NOT add unlisted dependencies
# Knip doesn't know if it should be in dependencies or devDependenciesYou must manually add unlisted dependencies.
Reference: Handling Issues
Avoid Relying on Transitive Dependencies
Direct imports of transitive dependencies (packages installed as dependencies of your dependencies) may break when those dependencies update. Add explicit dependencies for all directly imported packages.
Incorrect (importing transitive dependency):
// src/utils.ts
import debug from 'debug' // Not in package.json
// Works because 'express' depends on 'debug'{
"dependencies": {
"express": "^4.18.0"
}
}Knip reports: debug is unlisted.
Correct (explicit dependency):
{
"dependencies": {
"debug": "^4.3.0",
"express": "^4.18.0"
}
}Why this matters:
- Express may remove debug as a dependency in future versions
- Transitive dependencies may have different versions than expected
- Package managers may not install expected transitive dependencies
Reference: Handling Issues
Configure Plugins for Tool-Specific Dependencies
Tools like ESLint, Jest, and Webpack reference dependencies in config files. Enable and configure plugins so Knip detects these references.
Incorrect (plugin not configured, eslint plugins appear unused):
{
"devDependencies": {
"eslint": "^8.0.0",
"eslint-plugin-react": "^7.0.0",
"@typescript-eslint/parser": "^6.0.0"
}
}Knip reports: eslint-plugin-react, @typescript-eslint/parser unused.
Correct (ESLint plugin enabled and configured):
{
"eslint": {
"config": [".eslintrc.js", "eslint.config.js"]
}
}Knip reads the ESLint config and detects plugin/parser references.
Common plugins to configure:
eslint- ESLint plugins and parsersjest- Transform and setup fileswebpack- Loaders and pluginsbabel- Presets and plugins
Reference: Knip Plugins
Fix Unused Files Before Dependencies
Dependencies imported in unused files appear as unused dependencies. Fix unused file issues first, then re-run Knip to get accurate dependency reports.
Incorrect (fixing dependencies while files are unused):
knip
# Reports: unused files: src/old-feature.ts
# Reports: unused dependencies: lodash (imported only in src/old-feature.ts)
# User removes lodash from package.json
# Result: src/old-feature.ts still exists, may cause runtime errorsCorrect (fix files first, then dependencies):
knip --files
# Fix or remove unused files first
knip --dependencies
# Now dependency report is accurateFilter for focused analysis:
# Step 1: Fix unused files
knip --include files
# Step 2: Fix unused dependencies
knip --include dependencies
# Step 3: Fix unused exports
knip --include exportsReference: Handling Issues
Ignore Conditionally Loaded Dependencies
Dependencies loaded conditionally at runtime (based on environment, platform, or feature flags) may appear unused. Use ignoreDependencies for these cases.
Incorrect (conditional dependency reported as unused):
// src/database.ts
let driver
if (process.env.DB_TYPE === 'postgres') {
driver = require('pg')
} else {
driver = require('mysql2')
}Knip reports: pg or mysql2 unused (depending on static analysis path).
Correct (conditional dependencies ignored):
{
"ignoreDependencies": ["pg", "mysql2"]
}Production-only ignore:
{
"ignoreDependencies": ["pg!", "mysql2!"]
}The ! suffix applies the ignore only in production mode.
Better alternative (when possible):
Use dynamic imports with known paths that Knip can add as entries:
{
"entry": ["src/drivers/*.ts"]
}Reference: Knip Configuration
Remove Obsolete Type Definition Packages
Many packages now include bundled TypeScript types. Remove separate @types/ packages when the main package includes types to avoid conflicts and reduce dependencies.
Incorrect (separate types package when types are bundled):
{
"dependencies": {
"axios": "^1.6.0"
},
"devDependencies": {
"@types/axios": "^0.14.0"
}
}Knip reports: @types/axios is unused (axios includes types).
Correct (remove obsolete @types package):
{
"dependencies": {
"axios": "^1.6.0"
}
}Check if types are bundled:
1. Look for types or typings field in package.json 2. Check for .d.ts files in the package 3. Run knip - it detects unused @types packages
When to keep @types packages:
- Package has no bundled types
- You need a different version of types than bundled
Reference: Unused Dependencies
Add Dynamic Import Targets as Entry Points
Knip cannot statically analyze dynamic imports with computed paths. Add dynamically imported modules as explicit entry points.
Incorrect (dynamic imports unresolved, modules appear unused):
// src/plugins/index.ts
const loadPlugin = async (name: string) => {
const module = await import(`./plugins/${name}`) // Knip can't resolve
return module.default
}{
"entry": ["src/index.ts"]
}Correct (dynamic targets added as entries):
{
"entry": [
"src/index.ts",
"src/plugins/*.ts"
]
}Alternative (use ignoreDependencies for external dynamic imports):
{
"ignoreDependencies": ["@plugins/*"]
}Note: Static dynamic imports like import('./known-module') are resolved correctly. Only computed paths require explicit configuration.
Reference: Handling Issues - Dynamic Imports
Exclude Test Files from Production Entries
Test files import production code, which marks it as "used". Separate test entries from production entries to detect truly unused production code.
Incorrect (tests in same entry array, dead code hidden):
{
"entry": ["src/**/*.ts"]
}Correct (test entries via plugin, production entries separate):
{
"entry": ["src/index.ts", "src/cli.ts"],
"jest": {
"entry": ["**/*.test.ts", "**/*.spec.ts"]
}
}For production mode analysis:
{
"entry": ["src/index.ts!", "src/cli.ts!"],
"project": ["src/**/*.ts!", "!src/**/*.test.ts"]
}Run with --production to analyze only shipping code and catch dead code that tests artificially keep alive.
Reference: Production Mode
Include All Application Entry Points
Include all entry points in your configuration: main files, CLI scripts, server files, and worker files. Missing entries cause cascading false positives.
Incorrect (only main entry, CLI and workers unreachable):
{
"entry": ["src/index.ts"]
}Correct (all entry points included):
{
"entry": [
"src/index.ts",
"src/cli.ts",
"src/server.ts",
"src/worker.ts",
"scripts/*.ts"
]
}Check package.json for entry points:
{
"main": "dist/index.js",
"bin": {
"mycli": "dist/cli.js"
},
"exports": {
".": "./dist/index.js",
"./server": "./dist/server.js"
}
}Knip reads these fields automatically, but custom scripts in scripts/ need explicit configuration.
Reference: Entry Files
Include Binary Scripts as Entry Points
Binary scripts in package.json bin field are entry points. Knip reads these automatically, but verify they're detected and add custom scripts explicitly.
Incorrect (custom scripts not in bin, appear unused):
{
"entry": ["src/index.ts"]
}// scripts/migrate.ts is reported as unusedCorrect (scripts added as entries):
{
"entry": [
"src/index.ts",
"scripts/*.ts",
"bin/*.js"
]
}Verify package.json bin is detected:
{
"bin": {
"mycli": "./dist/cli.js",
"migrate": "./dist/migrate.js"
}
}Knip automatically includes files from bin. If source files are in src/, ensure the entry points to source:
{
"entry": ["src/cli.ts", "src/migrate.ts"]
}Reference: Entry Files
Use Compilers for Non-Standard File Types
Knip supports TypeScript and JavaScript by default. Use compilers for Vue SFCs, Svelte components, and other file types with embedded scripts.
Incorrect (Vue files not analyzed, imports missed):
{
"entry": ["src/main.ts"],
"project": ["src/**/*.ts"]
}Vue component imports not tracked.
Correct (Vue plugin handles SFC compilation):
{
"vue": true
}The Vue plugin automatically compiles .vue files and extracts imports.
Custom compiler for unsupported format:
// knip.config.ts
import type { KnipConfig } from 'knip'
const config: KnipConfig = {
compilers: {
mdx: (source) => {
// Extract imports from MDX
const imports = source.match(/import .+ from ['"].+['"]/g)
return imports?.join('\n') ?? ''
}
}
}
export default configBuilt-in compiler support:
- Vue (via plugin)
- Svelte (via plugin)
- Astro (via plugin)
Reference: Knip Configuration
Use Plugin Entry Points for Frameworks
Frameworks like Next.js, Remix, and Astro have non-standard entry patterns. Enable plugins to detect these automatically instead of manual configuration.
Incorrect (manual Next.js entries, incomplete coverage):
{
"entry": [
"pages/**/*.tsx",
"app/**/*.tsx"
]
}Correct (plugin handles all Next.js entry patterns):
{
"next": true
}The Next.js plugin automatically includes:
pages/**/*.{js,jsx,ts,tsx}app/**/*.{js,jsx,ts,tsx}middleware.{js,ts}instrumentation.{js,ts}- API routes, loading, error, and layout files
Override plugin entries when needed:
{
"next": {
"entry": ["app/**/*.tsx", "!app/**/not-a-page.tsx"]
}
}Reference: Knip Plugins
Verify Entry Points with Debug Mode
Use --debug to verify which entry files Knip discovered. Missing entries in debug output explain false positive unused file reports.
Incorrect (investigating false positives without verifying entries):
# User sees unused files, adds ignore patterns
knip
# Result: Real issues hidden, problem not solvedCorrect (verify entries first):
knip --debug 2>&1 | grep "entry"Output shows discovered entries:
[DEBUG] Included entry files: src/index.ts, src/cli.ts
[DEBUG] Plugin entry files: pages/index.tsx, pages/api/auth.tsIf entries are missing, add them:
{
"entry": [
"src/index.ts",
"src/cli.ts",
"src/missing-entry.ts"
]
}Check workspace configurations:
knip --debug 2>&1 | grep "workspace"Reference: Knip CLI - Debug
Check Class Members for Unused Code
Knip can detect unused class members (methods, properties). Enable with --include classMembers to catch dead code within classes.
Incorrect (unused class members undetected):
// src/service.ts
export class UserService {
private cache: Map<string, User> = new Map()
getUser(id: string) { return this.cache.get(id) }
setUser(id: string, user: User) { this.cache.set(id, user) }
deleteUser(id: string) { this.cache.delete(id) } // Never called
}Default Knip run doesn't report deleteUser as unused.
Correct (class members analyzed):
knip --include classMembersNow Knip reports: deleteUser is unused.
Configuration:
{
"rules": {
"classMembers": "error"
}
}Exclude enum members if too noisy:
knip --include classMembers --exclude enumMembersReference: Rules & Filters
Enable Entry Export Checking for Private Packages
By default, Knip doesn't report unused exports from entry files (they may be consumed externally). Enable includeEntryExports for private packages and monorepo workspaces.
Incorrect (unused entry exports hidden):
{
"entry": ["src/index.ts"]
}// src/index.ts
export const usedFunction = () => {}
export const unusedFunction = () => {} // Not reportedCorrect (entry exports included for private package):
{
"includeEntryExports": true,
"entry": ["src/index.ts"]
}Now Knip reports unusedFunction as unused.
Per-workspace configuration:
{
"workspaces": {
"packages/internal-lib": {
"includeEntryExports": true
},
"packages/public-sdk": {
"includeEntryExports": false
}
}
}When NOT to enable:
- Public npm packages (exports are the API)
- Packages consumed by external projects
Reference: Unused Exports
Handle Re-exports in Barrel Files
Knip tracks re-exports through barrel files. Unused items in re-export chains are reported. Configure properly to avoid false positives.
Incorrect (barrel file makes all exports appear used):
// src/index.ts
export * from './utils'
export * from './helpers'
export * from './constants'All exports appear used because they're re-exported.
Correct (use includeEntryExports for internal barrels):
{
"includeEntryExports": true
}Now Knip reports unused items even if re-exported.
Trace re-export chain:
knip --trace-export unusedHelperShows the re-export path:
unusedHelper
← re-exported from src/helpers.ts
← re-exported from src/index.ts
← NOT imported elsewhereAuto-fix removes from chain:
knip --fix-type exportsRemoves unused items from re-export statements.
Reference: Unused Exports
Ignore Exports Used in Same File
Exports used only within the same file (for testing or organization) can be excluded from reports using ignoreExportsUsedInFile.
Incorrect (internal helpers reported as unused exports):
// src/math.ts
export const add = (a: number, b: number) => a + b
export const multiply = (a: number, b: number) => a * b
// Only used in this file for complex calculations
export const complexCalc = (x: number) => multiply(add(x, 1), 2)Knip reports: add, multiply unused (only used internally).
Correct (same-file usage ignored):
{
"ignoreExportsUsedInFile": true
}Now add and multiply are not reported because they're used within math.ts.
Fine-grained control:
{
"ignoreExportsUsedInFile": {
"interface": true,
"type": true
}
}Ignores only type-level exports used in the same file.
Reference: Knip Configuration
Tag Public API Exports with JSDoc
Use JSDoc tags to mark intentionally public exports. Configure Knip to exclude tagged exports from unused export reports.
Incorrect (public API reported as unused):
// src/index.ts
/** This is part of the public API */
export const publicUtil = () => {}Knip reports: publicUtil is unused.
Correct (tagged export excluded):
// src/index.ts
/**
* This is part of the public API
* @public
*/
export const publicUtil = () => {}{
"tags": ["-public"]
}The - prefix excludes exports with the @public tag.
Include only specific tags:
{
"tags": ["+internal", "+deprecated"]
}Reports only exports with @internal or @deprecated tags.
Reference: Rules & Filters
Trace Export Usage Before Removal
Use --trace-export to investigate where an export is used before removing it. This catches usage patterns Knip may not detect.
Incorrect (removing without investigation):
knip
# Reports: formatDate is unused
# User removes formatDate
# Breaks: dynamic import that uses formatDateCorrect (trace before removal):
knip --trace-export formatDateOutput shows:
Tracing export: formatDate
- Not found in static imports
- Not found in re-exports
- Consider checking dynamic importsTrace file usage:
knip --trace-file src/utils/date.tsShows which files import from date.ts.
Trace dependency usage:
knip --trace-dependency lodashShows where lodash is imported.
When tracing is essential:
- Large codebases with dynamic imports
- Exports used in config files
- Exports consumed by external packages
Reference: Knip CLI
Use Include Libs for Type-Based Consumption
External libraries may consume your exports through type definitions. Use --include-libs to analyze external library types and detect these usages.
Incorrect (type-consumed exports appear unused):
// src/plugin.ts
export interface PluginConfig {
name: string
version: string
}
export const definePlugin = (config: PluginConfig) => configExternal library uses PluginConfig type but Knip reports it unused.
Correct (include external library types):
knip --include-libsNow Knip analyzes type definitions from node_modules and detects PluginConfig usage.
Performance note: This flag adds significant memory usage and processing time. Use sparingly for specific investigations:
# Trace specific export first
knip --trace-export PluginConfig
# If truly unused, it won't be found
# If used in libs, --include-libs reveals itReference: Unused Exports
Explicitly Allow File Removal
File removal requires explicit opt-in with --allow-remove-files. This prevents accidental deletion of files that may be used through patterns Knip cannot detect.
Incorrect (trying to remove files without flag):
knip --fix
# Unused files are not removed
# User confused why files remainCorrect (explicitly enable file removal):
# First, review what would be removed
knip --include files
# If all listed files are truly unused, enable removal
knip --fix --allow-remove-filesSafer workflow with backup:
# Create backup branch
git checkout -b backup/before-knip-cleanup
# Return to main branch
git checkout main
# Remove files with confidence
knip --fix --allow-remove-files
# Review removals
git status
git diff --cached
# If something wrong, restore from backup
git checkout backup/before-knip-cleanup -- path/to/file.tsReference: Auto-fix
Format Code After Auto-Fix
Run your code formatter after Knip auto-fix to clean up formatting artifacts. Use --format for automatic formatting.
Incorrect (unformatted code after removal):
knip --fix
# Leaves trailing commas, inconsistent spacing// Before fix
export { used, unused, another } from './utils'
// After fix (unformatted)
export { used, another } from './utils'
// ^^ extra spaceCorrect (auto-format after fix):
knip --fix --formatOr format manually:
knip --fix
npx prettier --write .
# or
npm run formatSupported formatters:
- Prettier (detected automatically)
- Biome
- dprint
- deno fmt
Configuration for specific formatter:
KNIP_FORMATTER=biome knip --fix --formatReference: Auto-fix
Review Auto-Fix Changes Before Commit
Always review auto-fix changes using git diff before committing. Knip may remove code that's used through dynamic patterns it cannot detect.
Incorrect (blind commit after auto-fix):
knip --fix
git add -A && git commit -m "Remove unused code"
# May have removed dynamically used codeCorrect (review changes first):
knip --fix
git diff
# Review each removal
# Verify no dynamic imports were broken
# Check for pattern-based usage
git add -A && git commit -m "Remove verified unused code"Staged review workflow:
# Step 1: See what would be removed (dry run)
knip
# Step 2: Apply fixes
knip --fix
# Step 3: Review changes
git diff --stat # Quick overview
git diff # Detailed review
# Step 4: Test
npm test
# Step 5: Commit
git add -A && git commit -m "Remove unused code verified by Knip"Reference: Auto-fix
Update Package Manager After Dependency Fix
After Knip removes dependencies from package.json, run your package manager to update the lock file and node_modules.
Incorrect (lock file out of sync):
knip --fix-type dependencies
# package.json updated, but package-lock.json still has old depsCorrect (update lock file after fix):
knip --fix-type dependencies
npm install # Updates package-lock.json and node_modulesFor different package managers:
# npm
npm install
# pnpm
pnpm install
# yarn
yarn installComplete workflow:
# 1. Fix dependencies
knip --fix-type dependencies
# 2. Update lock file
npm install
# 3. Verify project still works
npm test
# 4. Commit both files
git add package.json package-lock.json
git commit -m "Remove unused dependencies"Reference: Auto-fix
Use Fix Type for Targeted Cleanup
Use --fix-type to fix specific issue types incrementally. This reduces risk and makes review easier.
Incorrect (fixes everything at once):
knip --fix
# Removes exports, dependencies, files all at once
# Large diff, hard to reviewCorrect (fix one type at a time):
# Step 1: Fix unused exports
knip --fix-type exports
git diff && npm test && git commit -m "Remove unused exports"
# Step 2: Fix unused dependencies
knip --fix-type dependencies
git diff && npm install && npm test && git commit -m "Remove unused dependencies"
# Step 3: Fix unused types
knip --fix-type types
git diff && npm test && git commit -m "Remove unused types"Available fix types:
exports- Remove unused exportstypes- Remove unused type exportsdependencies- Remove from package.jsonenumMembers- Remove unused enum valuesclassMembers- Remove unused class members
Reference: Auto-fix
Filter Issue Types for Focused Analysis
Use --include or --exclude to analyze only specific issue types. This reduces output noise and can speed up analysis.
Incorrect (analyzing everything when focused on exports):
knip
# 500 lines of output across all issue types
# Hard to find export issuesCorrect (focused on specific issue type):
# Only exports
knip --include exports
# Only dependencies
knip --include dependencies
# Exports and types
knip --include exports,typesUse shorthands for common patterns:
# All dependency-related issues
knip --dependencies
# All export-related issues
knip --exports
# Only file issues
knip --filesExclude noisy issue types:
# Skip enum members and duplicates
knip --exclude enumMembers,duplicatesReference: Rules & Filters
Limit Output for Large Codebases
Use --max-show-issues to limit output when dealing with many issues. This prevents terminal overflow and makes output actionable.
Incorrect (thousands of issues overwhelm terminal):
knip
# 5000 lines of output, terminal buffer exceeded
# Can't scroll back to see important issuesCorrect (limited output with counts):
knip --max-show-issues 50
# Shows first 50 issues per type
# Displays total count for contextProgressive cleanup workflow:
# Step 1: See scope of problem
knip --max-show-issues 10
# "Showing 10 of 500 unused exports"
# Step 2: Fix a batch
knip --fix-type exports --max-show-issues 50
# Step 3: Repeat until clean
knip --max-show-issues 10
# "No issues found"Combine with filtering:
knip --include exports --max-show-issues 20
# Focus on exports, limit to 20Reference: Knip CLI
Profile Performance for Slow Analysis
Use --performance to identify which operations are slow. This helps optimize configuration for faster analysis.
Incorrect (slow analysis without investigation):
knip # Takes 5 minutes, unclear whyCorrect (profile to find bottlenecks):
knip --performanceOutput shows:
Performance:
findWorkspaces: 50ms
resolveModules: 2500ms <- Bottleneck
analyzeExports: 1200ms
resolveTypes: 800msProfile specific function:
knip --performance-fn resolveModulesMemory profiling:
knip --memory
# Shows peak memory usage
knip --memory-realtime
# Streams memory usage during executionCommon causes of slow analysis:
- Large node_modules with
--include-libs - Too many entry patterns matching files
- Missing cache (
--cachenot enabled) - Analyzing generated files
Reference: Knip CLI
Use Bun Runtime for Faster Analysis
Run Knip with Bun instead of Node.js for significantly faster startup and execution, especially on large codebases.
Incorrect (Node.js runtime, slower startup):
npx knip # Uses Node.jsCorrect (Bun runtime for speed):
bunx knip
# or if installed globally
knip-bunInstall Bun:
# macOS/Linux
curl -fsSL https://bun.sh/install | bash
# Windows
powershell -c "irm bun.sh/install.ps1 | iex"Performance comparison (typical large project):
- Node.js: ~30 seconds
- Bun: ~12 seconds
CI configuration:
- uses: oven-sh/setup-bun@v1
- run: bunx knipNote: Bun compatibility is generally excellent, but test in your project before switching CI.
Reference: Knip CLI
Enable Cache for Repeated Analysis
Enable Knip's built-in cache for faster repeated analysis. The cache stores module resolution results between runs.
Incorrect (full analysis every time):
knip # 30 seconds
knip # 30 seconds againCorrect (cached analysis):
knip --cache # 30 seconds (builds cache)
knip --cache # 18-20 seconds (uses cache)Permanent configuration:
{
"$schema": "https://unpkg.com/knip@5/schema.json",
"cache": true
}Custom cache location:
{
"cache": true,
"cacheLocation": ".cache/knip"
}Clear cache when needed:
rm -rf node_modules/.cache/knipWhen cache helps most:
- Large monorepos with many packages
- Repeated local development runs
- CI with cached node_modules
Reference: Knip CLI
Filter Workspaces for Faster Monorepo Analysis
Use --workspace to analyze specific packages in a monorepo. This dramatically speeds up analysis when working on a single package.
Incorrect (analyzing entire monorepo for single package change):
knip # Analyzes all 50 packages, takes 5 minutesCorrect (analyze affected workspace only):
knip --workspace packages/auth
# Analyzes only the auth package, takes 10 secondsMultiple workspaces:
knip --workspace packages/auth --workspace packages/api
# or
knip -W packages/auth -W packages/apiGlob patterns:
knip --workspace "packages/ui-*"
# Analyzes all ui- prefixed packagesCI optimization for changed packages:
- name: Get changed packages
id: changed
run: echo "packages=$(git diff --name-only HEAD~1 | grep '^packages/' | cut -d'/' -f2 | uniq | tr '\n' ',')" >> $GITHUB_OUTPUT
- name: Run Knip on changed packages
run: |
for pkg in $(echo "${{ steps.changed.outputs.packages }}" | tr ',' '\n'); do
npx knip --workspace "packages/$pkg"
doneReference: Knip CLI
Configure Root Workspace Explicitly
In monorepos, root-level entry and project options are ignored. Configure the root workspace using workspaces["."] to analyze root scripts and shared tooling.
Incorrect (root entries ignored in monorepo):
{
"entry": ["scripts/*.ts"],
"project": ["scripts/**/*.ts"],
"workspaces": {
"packages/*": {}
}
}Correct (root workspace configured explicitly):
{
"workspaces": {
".": {
"entry": ["scripts/*.ts"],
"project": ["scripts/**/*.ts"]
},
"packages/*": {
"entry": ["{index,cli}.ts"],
"project": ["**/*.ts"]
}
}
}Note: The "." key represents the root workspace. Without it, root-level files are not analyzed in monorepo mode.
Reference: Monorepos & Workspaces
Ignore Specific Workspaces When Needed
Use ignoreWorkspaces to exclude specific packages from analysis. This is useful for third-party forks, generated packages, or packages with incompatible structures.
Incorrect (analyzing incompatible workspace causes noise):
{
"workspaces": {
"packages/*": {
"entry": ["index.ts"]
}
}
}Correct (incompatible workspace excluded):
{
"ignoreWorkspaces": [
"packages/legacy-fork",
"packages/generated-api"
],
"workspaces": {
"packages/*": {
"entry": ["index.ts"]
}
}
}When to ignore workspaces:
- Third-party code forks with different conventions
- Generated code packages
- Packages scheduled for removal
- Packages with their own Knip configuration
Reference: Knip Configuration
Isolate Workspaces for Strict Dependency Checking
Use --strict or --isolate-workspaces to enforce that each workspace only uses its declared dependencies. This catches implicit dependencies that would break when published.
Incorrect (workspaces share dependencies implicitly):
knip// packages/api/src/handler.ts
import lodash from 'lodash' // Not in packages/api/package.json
// Works in development due to hoistingCorrect (isolated workspaces catch missing dependencies):
knip --strictOr in configuration:
{
"workspaces": {
"packages/*": {
"entry": ["index.ts"]
}
}
}knip --isolate-workspacesKnip reports lodash as unlisted in packages/api because it's not in that workspace's package.json.
Reference: Production Mode
List Cross-Workspace Dependencies Explicitly
List other workspaces as dependencies in each package.json instead of using relative imports or path aliases. This helps Knip track cross-workspace usage correctly.
Incorrect (path alias crosses workspaces, import untracked):
// packages/api/src/auth.ts
import { User } from '@packages/shared/types' // Path alias{
"paths": {
"@packages/*": ["../*/src"]
}
}Correct (workspace listed as dependency):
{
"name": "@myorg/api",
"dependencies": {
"@myorg/shared": "workspace:*"
}
}// packages/api/src/auth.ts
import { User } from '@myorg/shared/types' // Package importBenefits:
- Knip tracks the dependency relationship correctly
- Package manager validates workspace links
- Clearer dependency graph for developers
Reference: Monorepos & Workspaces
Configure Plugins Per Workspace
Configure plugins at the workspace level when packages use different tools. Root-level plugins apply globally; workspace-level plugins override or extend them.
Incorrect (global plugin config, misses package-specific tools):
{
"jest": true,
"workspaces": {
"packages/*": {}
}
}Package using Vitest instead of Jest: Vitest config entries missed.
Correct (workspace-specific plugin config):
{
"workspaces": {
"packages/app": {
"vitest": true,
"jest": false
},
"packages/api": {
"jest": {
"config": "jest.config.ts"
}
},
"packages/shared": {
"vitest": true
}
}
}Disable inherited plugins:
{
"eslint": true,
"workspaces": {
"packages/legacy": {
"eslint": false
}
}
}Legacy package doesn't use ESLint; disabling prevents false positives.
Reference: Monorepos & Workspaces
Use Workspace Globs for Consistent Configuration
Use glob patterns for workspace configuration to apply consistent entry and project patterns across all packages. Override specific workspaces when needed.
Incorrect (individual workspace configs, inconsistent):
{
"workspaces": {
"packages/auth": { "entry": ["index.ts"] },
"packages/api": { "entry": ["index.ts"] },
"packages/ui": { "entry": ["index.ts"] }
}
}Correct (glob pattern for consistent config):
{
"workspaces": {
"packages/*": {
"entry": ["{index,main}.ts"],
"project": ["src/**/*.ts", "!src/**/*.test.ts"]
},
"packages/cli": {
"entry": ["bin/cli.ts"]
}
}
}Knip matches workspaces from package.json or pnpm-workspace.yaml. Specific workspace configs override glob patterns.
Reference: Monorepos & Workspaces
Related skills
How it compares
Use knip-deadcode for systematic Knip setup; a generic refactor skill lacks the 43 prioritized Knip-specific rules and CI patterns.
FAQ
How many rules does knip-deadcode include?
knip-deadcode includes 43 rules organized into 8 priority categories from Configuration Foundations through Performance Optimization. Each rule links to a focused reference with examples and expected outcomes for Knip setup and cleanup.
Does knip-deadcode support monorepos?
knip-deadcode dedicates a Workspace and Monorepo category with HIGH priority rules for entry-point strategy, workspace handling, and dependency tracing. Guidance covers both single-repo and monorepo Knip adoption paths.