# Knip

> Run Knip to find unused files, exports and types, with per-framework and per-test-runner plugins. TRIGGER WHEN: cleaning up TypeScript/JavaScript codebases, optimizing bundle size, or enforcing strict dependency hygiene in CI. DO NOT TRIGGER WHEN: the target is a Python codebase (use python-dead-code).

- Skill: `acaprino/knip` (Agent Skill)
- Install (CLI): `npx skillmds@latest add acaprino/knip`
- Raw SKILL.md: https://api.skillmd.com/api/skills/acaprino/knip/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: acaprino (https://skillmd.com/u/acaprino)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/acaprino/knip

---


# 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`.

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

# Verify installation
npx knip --version
```

## Basic Usage

```bash
# 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)

```json
{
  "$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)

```typescript
// 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

```typescript
// 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

```typescript
// 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

```typescript
// 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

```typescript
// 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

```typescript
// 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

```yaml
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

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

### Pre-commit Hook

```yaml
# .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

```bash
# 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)

```bash
# 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

```bash
# Check production code only
npx knip --production

# Check everything (including dev dependencies)
npx knip
```

### Monorepo Workflows

```typescript
// 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'],
    },
  },
};
```

```bash
# 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)

```typescript
// 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

```bash
# Debug configuration
npx knip --debug

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

### Performance Issues

```bash
# 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

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

### Unused Dependencies in Scripts

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

If not detected:
```typescript
// knip.ts
const config: KnipConfig = {
  ignoreDependencies: ['eslint', 'vitest'],
};
```

## Advanced Usage

### Custom Reporters

```bash
# 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)

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

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

### Type Checking Integration

```typescript
// 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

```bash
# Easiest wins first
npx knip --dependencies

# Then move to exports
npx knip --exports

# Finally check files
npx knip --files
```

### Gradual Adoption

```typescript
// 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

```yaml
# 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

- Official docs: https://knip.dev
- Configuration: https://knip.dev/reference/configuration
- Plugins: https://knip.dev/reference/plugins
- CLI reference: https://knip.dev/reference/cli
- FAQ: https://knip.dev/reference/faq

