SuperAPI AI Directory

knip

Coding & development

View repository

Updated 10-15 12:45

About this skill

Knip Dead Code Detection

Knip is a comprehensive tool for finding unused code, dependencies, and exports in JavaScript and TypeScript projects. It helps maintain clean codebases and catch dead code before it accumulates.

Core Expertise

What is Knip?

  • Unused detection: Files, dependencies, exports, types, enum members
  • Plugin system: Supports 80+ frameworks and tools
  • Fast: Analyzes large codebases in seconds
  • Actionable: Clear reports with file locations
  • CI-ready: Exit codes for failing builds

Key Capabilities

  • Detect unused dependencies (npm, workspace packages)
  • Find unused exports and types
  • Identify unused files
  • Discover unused enum members and class members
  • Detect re-exports that aren't used
  • Plugin support for frameworks (React, Next.js, Vue, Svelte)
  • Integration with monorepos and workspaces

Installation

Examples below use npx. Equivalent commands work with bun/bunx or yarn/yarn dlx.

# Project-local (recommended)
npm install --save-dev knip

# Verify installation
npx knip --version

Basic Usage

# Run Knip (scans entire project)
npx knip

# Show only unused dependencies
npx knip --dependencies

# Show only unused exports
npx knip --exports

# Show only unused files
npx knip --files

# Production mode (only check production dependencies)
npx knip --production

# Exclude specific issue types
npx knip --exclude-exports-used-in-file

# Output JSON (for CI)
npx knip --reporter json

# Debug mode (show configuration)
npx knip --debug

Configuration

Auto-detection (Zero Config)

Knip automatically detects:

  • Entry points (package.json main, exports, bin)
  • Frameworks (Next.js, Vite, Remix, etc.)
  • Test runners (Vitest, Jest, Playwright)
  • Build tools (ESLint, TypeScript, PostCSS)

No configuration needed for standard projects.

knip.json (Explicit Configuration)

{
  "$schema": "https://unpkg.com/knip@latest/schema.json",
  "entry": ["src/index.ts", "src/cli.ts"],
  "project": ["src/**/*.ts"],
  "ignore": ["**/*.test.ts", "scripts/**"],
  "ignoreDependencies": ["@types/*"],
  "ignoreBinaries": ["npm-check-updates"]
}

knip.ts (TypeScript Configuration)

// knip.ts
import type { KnipConfig } from 'knip';

const config: KnipConfig = {
  entry: ['src/index.ts', 'src/cli.ts'],
  project: ['src/**/*.ts', 'scripts/**/*.ts'],
  ignore: ['**/*.test.ts', '**/*.spec.ts', 'tmp/**'],
  ignoreDependencies: [
    '@types/*', // Type definitions
    'typescript', // Always needed
  ],
  ignoreExportsUsedInFile: true,
  ignoreWorkspaces: ['packages/legacy/**'],
};

export default config;

Recommended Production Setup

// knip.ts
import type { KnipConfig } from 'knip';

const config: KnipConfig = {
  // Entry points
  entry: [
    'src/index.ts',
    'src/cli.ts',
    'scripts/**/*.ts', // Include scripts
  ],

  // Project files
  project: ['src/**/*.{ts,tsx}', 'scripts/**/*.ts'],

  // Ignore patterns
  ignore: [
    '**/*.test.ts',
    '**/*.spec.ts',
    '**/__tests__/**',
    '**/__mocks__/**',
    'dist/**',
    'build/**',
    'coverage/**',
    '.next/**',
  ],

  // Dependencies to ignore
  ignoreDependencies: [
    '@types/*', // Type definitions used implicitly
    'typescript', // Always needed for TS projects
    'tslib', // TypeScript helper library
    '@biomejs/biome', // Used via CLI
    'prettier', // Used via CLI
  ],

  // Binaries to ignore (used in package.json scripts)
  ignoreBinaries: ['npm-check-updates', 'semantic-release'],

  // Ignore exports used in the same file
  ignoreExportsUsedInFile: true,

  // Workspace configuration (for monorepos)
  workspaces: {
    '.': {
      entry: ['src/index.ts'],
    },
    'packages/*': {
      entry: ['src/index.ts', 'src/cli.ts'],
    },
  },
};

export default config;

Plugin System

Knip automatically detects and configures plugins for popular tools:

Framework Plugins

Framework Auto-detected Entry Points
Next.js next.config.js pages/, app/, middleware.ts
Vite vite.config.ts index.html, config plugins
Remix remix.config.js app/root.tsx, app/entry.*
Astro astro.config.mjs src/pages/, config integrations
SvelteKit svelte.config.js src/routes/, src/app.html
Nuxt nuxt.config.ts app.vue, pages/, layouts/

Test Runner Plugins

Tool Auto-detected Entry Points
Vitest vitest.config.ts **/*.test.ts, config files
Jest jest.config.js **/*.test.js, setup files
Playwright playwright.config.ts tests/**/*.spec.ts
Cypress cypress.config.ts cypress/e2e/**/*.cy.ts

Build Tool Plugins

Tool Auto-detected Entry Points
TypeScript tsconfig.json Files in include
ESLint .eslintrc.js Config files, plugins
PostCSS postcss.config.js Config plugins
Tailwind tailwind.config.js Config plugins, content files

Plugin Configuration Override

// knip.ts
const config: KnipConfig = {
  // Disable specific plugins
  eslint: false,
  prettier: false,

  // Override plugin config
  vitest: {
    entry: ['vitest.config.ts', 'test/setup.ts'],
    config: ['vitest.config.ts'],
  },

  next: {
    entry: [
      'next.config.js',
      'pages/**/*.tsx',
      'app/**/*.tsx',
      'middleware.ts',
      'instrumentation.ts',
    ],
  },
};

Ignoring Issues

Ignore Patterns

// knip.ts
const config: KnipConfig = {
  // Ignore entire directories
  ignore: ['legacy/**', 'vendor/**'],

  // Ignore specific dependencies
  ignoreDependencies: [
    '@types/*',
    'some-peer-dependency',
  ],

  // Ignore specific exports
  ignoreExportsUsedInFile: {
    interface: true, // Ignore interfaces used only in same file
    type: true, // Ignore types used only in same file
  },

  // Ignore workspace packages
  ignoreWorkspaces: ['packages/deprecated/**'],
};

Inline Comments

// Ignore unused export
// @knip-ignore-export
export const unusedFunction = () => {};

// Ignore unused dependency in package.json
{
  "dependencies": {
    "some-package": "1.0.0" // @knip-ignore-dependency
  }
}

Whitelist Pattern

// knip.ts - Whitelist specific exports
const config: KnipConfig = {
  entry: ['src/index.ts'],
  project: ['src/**/*.ts'],

  // Only these exports are allowed to be unused (public API)
  exports: {
    include: ['src/index.ts'],
  },
};

CI/CD Integration

GitHub Actions

name: Knip
on:
  push:
    branches: [main]
  pull_request:

jobs:
  knip:
    name: Check for unused code
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 'lts/*'

      - name: Install dependencies
        run: npm ci

      - name: Run Knip
        run: npx knip --production

      - name: Run Knip (strict)
        run: npx knip --max-issues 0

GitLab CI

knip:
  image: node:lts
  stage: test
  script:
    - npm ci
    - npx knip --production
  only:
    - merge_requests
    - main

Pre-commit Hook

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: knip
        name: Knip
        entry: npx knip
        language: system
        pass_filenames: false

Common Patterns

Check Only Unused Dependencies

# Fastest check - only dependencies
npx knip --dependencies

# Exit with error if any unused dependencies
npx knip --dependencies --max-issues 0

Use in CI to enforce strict dependency hygiene.

Check Only Exports (Library Development)

# Check for unused exports
npx knip --exports

# Allow exports used in same file
npx knip --exports --exclude-exports-used-in-file

Use for libraries to ensure clean public API.

Production vs Development Dependencies

# Check production code only
npx knip --production

# Check everything (including dev dependencies)
npx knip

Monorepo Workflows

// knip.ts
const config: KnipConfig = {
  workspaces: {
    '.': {
      entry: ['scripts/**/*.ts'],
      ignoreDependencies: ['@org/internal-package'],
    },
    'packages/web': {
      entry: ['src/index.ts', 'src/App.tsx'],
      ignoreDependencies: ['react', 'react-dom'], // Provided by parent
    },
    'packages/api': {
      entry: ['src/server.ts'],
    },
  },
};
# Check all workspaces
npx knip

# Check specific workspace
npx knip --workspace packages/web

Interpreting Results

Example Output

✓ No unused files
✓ No unused dependencies
✗ 2 unused exports

src/utils.ts:
  - calculateTax (line 42)
  - formatDate (line 58)

src/types.ts:
  - UserRole (line 12)

Issue Types

Type Description Action
Unused file File not imported anywhere Delete or add to entry points
Unused dependency Package in package.json not used Remove from dependencies
Unused export Exported but never imported Remove export or make private
Unused type Type/interface exported but unused Remove or make internal
Unused enum member Enum member never referenced Remove member
Duplicate export Same export from multiple files Consolidate exports

Troubleshooting

False Positives (Exports Used via Side Effects)

// knip.ts
const config: KnipConfig = {
  // Ignore exports that are used via side effects
  ignoreExportsUsedInFile: true,

  // Or add to entry points
  entry: ['src/index.ts', 'src/side-effect-file.ts'],
};

Knip Not Finding Entry Points

# Debug configuration
npx knip --debug

# Manually specify entry points
npx knip --entry src/index.ts --entry src/cli.ts

Performance Issues

# Exclude node_modules explicitly (usually automatic)
npx knip --exclude '**/node_modules/**'

# Use .gitignore patterns
npx knip --include-libs false

# Increase memory limit
NODE_OPTIONS=--max-old-space-size=4096 npx knip

Plugin Not Detected

// knip.ts - Force enable plugin
const config: KnipConfig = {
  vite: {
    entry: ['vite.config.ts'],
    config: ['vite.config.ts'],
  },
};

Unused Dependencies in Scripts

// package.json - Knip detects binaries in scripts
{
  "scripts": {
    "lint": "eslint .", // Detects eslint dependency
    "test": "vitest" // Detects vitest dependency
  }
}

If not detected:

// knip.ts
const config: KnipConfig = {
  ignoreDependencies: ['eslint', 'vitest'],
};

Advanced Usage

Custom Reporters

# JSON output (for CI)
npx knip --reporter json > knip-report.json

# Compact output
npx knip --reporter compact

# Custom format (coming soon)
npx knip --reporter custom

Incremental Checks (Changed Files Only)

# Check only changed files (requires git)
npx knip --changed

# Since specific commit
npx knip --changed --base main

Type Checking Integration

// knip.ts
const config: KnipConfig = {
  // Include type-only imports as used
  includeTypeImports: true,

  // Check for unused TypeScript types
  types: true,
};

Best Practices

Start with Dependencies Only

# Easiest wins first
npx knip --dependencies

# Then move to exports
npx knip --exports

# Finally check files
npx knip --files

Gradual Adoption

// knip.ts - Start strict, then relax
const config: KnipConfig = {
  // Start with critical paths only
  entry: ['src/index.ts'],
  project: ['src/core/**/*.ts'],

  // Expand coverage over time
  // entry: ['src/**/*.ts'],
  // project: ['src/**/*.ts'],
};

CI Strategy

# Check dependencies in CI (fast, high value)
- name: Check unused dependencies
  run: npx knip --dependencies --max-issues 0

# Check exports in PR (prevents API bloat)
- name: Check unused exports
  run: npx knip --exports
  if: github.event_name == 'pull_request'

Maintenance Schedule

  • Weekly: Run full Knip scan, clean up issues
  • PR Review: Check for new unused exports
  • Pre-release: Full scan with --production
  • Refactors: Run Knip before and after

References