Knip finds unused files, dependencies, exports, and types in JavaScript/TypeScript projects. Plugin system for frameworks (React, Next.js, Vite), test runners (Vitest, Jest), and build tools. Use when cleaning up codebases, optimizing bundle size, or enforcing strict dependency hygiene in CI.
/plugin marketplace add laurigates/claude-plugins/plugin install typescript-plugin@lgates-claude-pluginsThis skill is limited to using the following tools:
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.
What is Knip?
Key Capabilities
# Project-local (recommended)
bun add --dev knip
# Global installation
bun add --global knip
# Verify installation
bunx knip --version
# Run Knip (scans entire project)
bunx knip
# Show only unused dependencies
bunx knip --dependencies
# Show only unused exports
bunx knip --exports
# Show only unused files
bunx knip --files
# Production mode (only check production dependencies)
bunx knip --production
# Exclude specific issue types
bunx knip --exclude-exports-used-in-file
# Output JSON (for CI)
bunx knip --reporter json
# Debug mode (show configuration)
bunx knip --debug
Knip automatically detects:
main, exports, bin)No configuration needed for standard projects.
{
"$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
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;
// 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;
Knip automatically detects and configures plugins for popular tools:
| 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/ |
| 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 |
| 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 |
// 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',
],
},
};
// 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/**'],
};
// Ignore unused export
// @knip-ignore-export
export const unusedFunction = () => {};
// Ignore unused dependency in package.json
{
"dependencies": {
"some-package": "1.0.0" // @knip-ignore-dependency
}
}
// 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'],
},
};
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: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Run Knip
run: bunx knip --production
- name: Run Knip (strict)
run: bunx knip --max-issues 0
knip:
image: oven/bun:latest
stage: test
script:
- bun install --frozen-lockfile
- bunx knip --production
only:
- merge_requests
- main
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: knip
name: Knip
entry: bunx knip
language: system
pass_filenames: false
# Fastest check - only dependencies
bunx knip --dependencies
# Exit with error if any unused dependencies
bunx knip --dependencies --max-issues 0
Use in CI to enforce strict dependency hygiene.
# Check for unused exports
bunx knip --exports
# Allow exports used in same file
bunx knip --exports --exclude-exports-used-in-file
Use for libraries to ensure clean public API.
# Check production code only
bunx knip --production
# Check everything (including dev dependencies)
bunx knip
// 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
bunx knip
# Check specific workspace
bunx knip --workspace packages/web
✓ No unused files
✓ No unused dependencies
✗ 2 unused exports
src/utils.ts:
- calculateTax (line 42)
- formatDate (line 58)
src/types.ts:
- UserRole (line 12)
| 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 |
// 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'],
};
# Debug configuration
bunx knip --debug
# Manually specify entry points
bunx knip --entry src/index.ts --entry src/cli.ts
# Exclude node_modules explicitly (usually automatic)
bunx knip --exclude '**/node_modules/**'
# Use .gitignore patterns
bunx knip --include-libs false
# Increase memory limit
NODE_OPTIONS=--max-old-space-size=4096 bunx knip
// knip.ts - Force enable plugin
const config: KnipConfig = {
vite: {
entry: ['vite.config.ts'],
config: ['vite.config.ts'],
},
};
// 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'],
};
# JSON output (for CI)
bunx knip --reporter json > knip-report.json
# Compact output
bunx knip --reporter compact
# Custom format (coming soon)
bunx knip --reporter custom
# Check only changed files (requires git)
bunx knip --changed
# Since specific commit
bunx knip --changed --base main
// knip.ts
const config: KnipConfig = {
// Include type-only imports as used
includeTypeImports: true,
// Check for unused TypeScript types
types: true,
};
# Easiest wins first
bunx knip --dependencies
# Then move to exports
bunx knip --exports
# Finally check files
bunx knip --files
// 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'],
};
# Check dependencies in CI (fast, high value)
- name: Check unused dependencies
run: bunx knip --dependencies --max-issues 0
# Check exports in PR (prevents API bloat)
- name: Check unused exports
run: bunx knip --exports
if: github.event_name == 'pull_request'
--productionThis skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.