Skip to main content

Knip

Static analysis tool that finds unused files, exports, and dependencies in JavaScript and TypeScript projects. Supports monorepos, auto-detects 50+ frameworks via plugins, and can automatically remove dead code with the --fix flag.

✓ Unused files & exports ✓ Unused dependencies ✓ Monorepo support ✓ 50+ framework plugins ✓ Auto-fix mode ✓ Zero dependencies

What is Knip?

Knip (a Dutch word for "snip" or "cut") is an open-source static analysis tool for JavaScript and TypeScript codebases. It traces your project's dependency graph starting from configured entry points and identifies everything that is never imported or consumed: unused source files, unused exported symbols, and packages listed in package.json that are never actually used.

As projects grow, dead code accumulates silently. Developers rename functions without removing old versions, split files without deleting originals, or install packages that a feature pivot made redundant. Knip surfaces all of this in a single report so you can cut what no longer serves the codebase — reducing bundle size, speeding up builds, and lowering cognitive load for future maintainers.

Key Features

Installation

# Install Knip as a dev dependency
npm add -D knip

# Or run without installing
npx knip

# Auto-fix issues (removes unused exports, unlinks files, removes deps)
knip --fix

# Use the compact reporter for terse output
knip --reporter compact

# Check only specific issue types
knip --include files,dependencies

# Run in watch mode during development
knip --watch

Basic Configuration and Output

Create a knip.json at the project root with entry (known start files) and project (all source files to consider) glob patterns, then run npx knip.

// knip.json — minimal config at the project root
{
  "entry": ["src/index.ts", "src/cli.ts"],
  "project": ["src/**/*.ts"]
}

// Then run:
// npx knip
//
// Sample output:
// Unused files (2)
//   src/utils/legacy-helper.ts
//   src/types/old-types.ts
//
// Unused exports (3)
//   src/utils/format.ts: formatDate, formatTime
//   src/api/client.ts: legacyFetch
//
// Unlisted dependencies (1)
//   lodash (used in src/utils/sort.ts but not in package.json)
//
// Unused devDependencies (2)
//   @types/node, ts-node

Monorepo Configuration

Use the workspaces key to configure each package independently. Knip understands cross-workspace imports and will not flag symbols that are consumed by sibling packages.

// knip.json — monorepo workspace configuration
{
  "workspaces": {
    ".": {
      "entry": ["scripts/*.ts"],
      "project": ["scripts/**/*.ts"]
    },
    "packages/ui": {
      "entry": ["src/index.ts"],
      "project": ["src/**/*.ts"]
    },
    "packages/api": {
      "entry": ["src/index.ts", "src/routes/*.ts"],
      "project": ["src/**/*.ts"]
    },
    "apps/web": {
      "entry": ["src/app/**/*.{ts,tsx}", "src/pages/**/*.{ts,tsx}"],
      "project": ["src/**/*.{ts,tsx}"]
    }
  }
}

Framework Plugins

Knip ships with plugins for 50+ tools. Plugins are auto-activated based on what is installed in your project. They extend the entry patterns so framework-specific files (page routes, config files, test suites) are correctly recognized as entry points rather than reported as unused.

// knip.json — using plugins for popular frameworks
{
  "entry": ["src/index.ts"],
  "project": ["src/**/*.ts"],
  // Knip auto-detects and activates plugins for installed tools.
  // You can override plugin config explicitly:
  "next": {
    "entry": ["src/app/**/*.{ts,tsx}", "src/pages/**/*.{ts,tsx}"]
  },
  "vitest": {
    "entry": ["src/**/*.test.ts", "src/**/*.spec.ts"]
  },
  "eslint": {
    "config": [".eslintrc.json"]
  }
}

// Knip ships plugins for 50+ tools including:
// Next.js, Remix, Astro, SvelteKit, Vite, Vitest, Jest,
// ESLint, Prettier, Tailwind CSS, Storybook, Playwright,
// TypeScript, tsup, Rollup, Webpack, esbuild, and more.

CI Integration

Add Knip to your CI pipeline to catch dead code on every pull request. The process exits with a non-zero code when issues are found, blocking merges until the dead code is removed or explicitly ignored.

# .github/workflows/knip.yml
name: Knip — Dead Code Check

on:
  pull_request:
  push:
    branches: [main]

jobs:
  knip:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - name: Run Knip
        run: npx knip --reporter compact

Knip vs ESLint no-unused-vars

Feature Knip ESLint no-unused-vars
Unused filesYesNo
Unused exports (cross-file)YesNo (file-scoped only)
Unused npm dependenciesYesNo
Monorepo workspace supportYesNo
Auto-fixYes (--fix flag)Partial (remove vars)
Framework plugins50+ pluginsNone

Pros and Cons

Pros

  • ✓ Finds dead code ESLint cannot: unused files and cross-file unused exports
  • ✓ Audits npm dependencies — catches packages you forgot to remove
  • ✓ 50+ framework plugins auto-activate with zero manual config
  • ✓ First-class monorepo support with correct cross-workspace resolution
  • ✓ Zero runtime dependencies — fast install, minimal supply chain risk
  • ✓ Auto-fix mode automates the cleanup work

Cons

  • ✗ First run on a large legacy codebase can produce hundreds of reports
  • ✗ Requires accurate entry/project config — misconfiguration leads to false positives
  • ✗ Dynamic imports and runtime reflection can confuse the static analysis
  • ✗ --fix is conservative; some cleanup still requires manual intervention
  • ✗ Younger ecosystem than ESLint — fewer community resources

Frequently Asked Questions

What is Knip?▼

Knip is an open-source static analysis tool for JavaScript and TypeScript projects that finds unused files, exports, and dependencies. It reads your project's entry points, traces the dependency graph, and reports anything that is never imported or used. This helps you reduce bundle size, lower maintenance overhead, and keep codebases clean as they evolve.

What types of unused code does Knip find?▼

Knip reports: unused files (never imported anywhere), unused exports (exported symbols that are never imported by another module), unused types and interfaces, unlisted dependencies (used in code but missing from package.json), unused dependencies (listed in package.json but never imported), unused devDependencies, and exports that are only used in test files or type-only positions. Each category is reported separately so you can address them incrementally.

How does Knip handle monorepos?▼

Knip has first-class monorepo support via the workspaces key in knip.json. You define entry and project globs per workspace package, and Knip analyzes each package in context — understanding that a symbol exported from packages/ui may be consumed by apps/web. It correctly distinguishes between truly unused exports and cross-workspace references, so you do not get false positives for shared packages.

Can Knip auto-fix issues?▼

Yes. Running knip --fix applies safe automated fixes: it removes unused export keywords from source files, deletes files that are entirely unused, and removes unused entries from package.json dependencies and devDependencies. The fix mode is conservative and does not delete files that might have side effects. Always review the changes in a diff before committing — treat --fix as a productivity boost, not a blind autopilot.

How do I configure Knip for my project?▼

Create a knip.json (or knip.ts) at the project root with entry and project glob patterns. entry files are the known starting points of your app (index.ts, CLI entry points, page routes). project defines all source files Knip should consider. Knip auto-detects 50+ plugins based on your installed tools (Next.js, Vite, ESLint, etc.) and extends the entry pattern automatically. For most projects a minimal config — just entry and project — is enough to start.

Does Knip support TypeScript?▼

Yes, TypeScript is a first-class citizen in Knip. It uses the TypeScript compiler API to resolve imports and trace exports, so it correctly understands type-only imports, interface re-exports, declaration merging, and path aliases defined in tsconfig.json. Knip also reports unused TypeScript types and interfaces separately from runtime exports, giving you full visibility into dead TS code.

Share this tool: X / Twitter LinkedIn
✓ 60,000+ developers use DevPlaybook ★★★★★ 4.8 / 5 on Gumroad ✓ MIT licensed · Instant download ✓ No login required

Related Products

on Gumroad

You Might Also Need

More Free Tools

Enjoying this tool? Get more like it.

Weekly developer tool guides, productivity playbooks & AI tricks. Free. No spam.

DevPlaybook Pro 7 days free

Unlock AI-Powered Dev Tools

  • ⚡ AI Code Review, Doc Generator & SQL Builder
  • ⚡ All premium templates & early access
  • ⚡ Member discounts on Gumroad products
Start Free Trial →

$9/mo after trial · Cancel anytime

Want the full toolkit?

Get DevPlaybook Pro

Every template, guide, boilerplate, and automation script in one bundle. 13 premium products — grab them all at once and save big.

$79
$241 separately Save $162 (67% off)
Get DevPlaybook Pro — $79 →

MIT licensed · Instant download · No subscription

See what's included → Browse all deals →