0
# Plugin System
1
2
Extensive plugin architecture supporting 129+ tools and frameworks with automatic detection and configuration. Plugins extend Knip's analysis capabilities to understand project-specific patterns and configurations.
3
4
## Capabilities
5
6
### Plugin Interface
7
8
Core plugin interface for extending Knip functionality.
9
10
```typescript { .api }
11
/**
12
* Plugin interface for extending Knip analysis
13
*/
14
interface Plugin {
15
/** Display name for the plugin */
16
title: string;
17
/** CLI argument configuration */
18
args?: Args;
19
/** Path to package.json or function to check manifest */
20
packageJsonPath?: string | ((manifest: PackageJson) => unknown);
21
/** Dependencies/files that enable this plugin */
22
enablers?: IgnorePatterns | string;
23
/** Custom plugin enablement logic */
24
isEnabled?: IsPluginEnabled;
25
/** Only run in root workspace */
26
isRootOnly?: boolean;
27
/** Configuration file patterns */
28
config?: string[];
29
/** Entry file patterns */
30
entry?: string[];
31
/** Production-specific file patterns */
32
production?: string[];
33
/** Project file patterns */
34
project?: string[];
35
/** Plugin setup function */
36
setup?: PluginSetup;
37
/** Plugin teardown function */
38
teardown?: PluginTeardown;
39
/** Function to determine if config should be loaded */
40
isLoadConfig?: IsLoadConfig;
41
/** Function to resolve configuration files */
42
resolveConfig?: ResolveConfig;
43
/** Function to resolve additional inputs */
44
resolve?: Resolve;
45
/** Function to resolve inputs from AST */
46
resolveFromAST?: ResolveFromAST;
47
}
48
49
type IsPluginEnabled = (options: IsPluginEnabledOptions) => boolean | Promise<boolean>;
50
51
interface IsPluginEnabledOptions {
52
cwd: string;
53
manifest: PackageJson;
54
dependencies: Set<string>;
55
config: WorkspaceConfiguration;
56
}
57
58
type PluginSetup = (options: PluginOptions) => Promise<void> | void;
59
type PluginTeardown = (options: PluginOptions) => Promise<void> | void;
60
type IsLoadConfig = (options: PluginOptions, dependencies: Set<string>) => boolean;
61
type ResolveConfig<T = any> = (config: T, options: PluginOptions) => Promise<Input[]> | Input[];
62
type Resolve = (options: PluginOptions) => Promise<Input[]> | Input[];
63
```
64
65
**Usage Examples:**
66
67
### Creating Custom Plugins
68
69
```typescript
70
import type { Plugin } from "knip";
71
72
const myCustomPlugin: Plugin = {
73
title: "My Custom Tool",
74
enablers: ["my-custom-tool"],
75
config: ["my-tool.config.{js,json}"],
76
entry: ["src/my-tool-entries/**/*.js"],
77
resolve: async (options) => {
78
// Custom logic to find additional entry points
79
return [
80
{ filePath: "src/generated.js" },
81
{ filePath: "scripts/build.js" }
82
];
83
}
84
};
85
```
86
87
### Available Plugins
88
89
Knip includes 129+ built-in plugins for popular tools and frameworks.
90
91
```typescript { .api }
92
/** Map of all available plugins */
93
const plugins: Record<PluginName, Plugin>;
94
95
/** Union type of all plugin names */
96
type PluginName =
97
| 'angular' | 'astro' | 'ava' | 'babel' | 'biome' | 'bun' | 'c8'
98
| 'capacitor' | 'changelogen' | 'changesets' | 'commitizen' | 'commitlint'
99
| 'convex' | 'create-typescript-app' | 'cspell' | 'cucumber' | 'cypress'
100
| 'dependency-cruiser' | 'docusaurus' | 'drizzle' | 'eleventy' | 'eslint'
101
| 'expo' | 'gatsby' | 'github-actions' | 'glob' | 'graphql-codegen'
102
| 'husky' | 'jest' | 'knip' | 'lefthook' | 'lint-staged' | 'markdownlint'
103
| 'mocha' | 'msw' | 'next' | 'node-test-runner' | 'nodemon' | 'npm-package-json-lint'
104
| 'nuxt' | 'nx' | 'oclif' | 'playwright' | 'postcss' | 'prettier'
105
| 'react' | 'release-it' | 'remix' | 'rollup' | 'rush' | 'semantic-release'
106
| 'storybook' | 'tailwind' | 'tsup' | 'typescript' | 'unbuild' | 'vite'
107
| 'vitest' | 'vue' | 'webpack' | 'wireit' | 'xo' | 'yarn'
108
// ... and 80+ more
109
;
110
```
111
112
**Popular Plugins:**
113
114
### Framework Plugins
115
116
```typescript
117
// Next.js plugin
118
const nextPlugin: Plugin = {
119
title: "Next.js",
120
enablers: ["next"],
121
config: ["next.config.{js,mjs,ts}"],
122
entry: ["pages/**/*.{js,jsx,ts,tsx}", "app/**/*.{js,jsx,ts,tsx}"]
123
};
124
125
// React plugin
126
const reactPlugin: Plugin = {
127
title: "React",
128
enablers: ["react", "react-dom"],
129
entry: ["src/**/*.{jsx,tsx}"]
130
};
131
132
// Vue plugin
133
const vuePlugin: Plugin = {
134
title: "Vue",
135
enablers: ["vue"],
136
entry: ["src/**/*.vue"]
137
};
138
```
139
140
### Testing Framework Plugins
141
142
```typescript
143
// Jest plugin
144
const jestPlugin: Plugin = {
145
title: "Jest",
146
enablers: ["jest"],
147
config: ["jest.config.{js,ts,mjs,cjs,json}"],
148
entry: ["**/*.{test,spec}.{js,ts,tsx,jsx}"]
149
};
150
151
// Cypress plugin
152
const cypressPlugin: Plugin = {
153
title: "Cypress",
154
enablers: ["cypress"],
155
config: ["cypress.config.{js,ts}"],
156
entry: ["cypress/**/*.{js,ts}"]
157
};
158
159
// Playwright plugin
160
const playwrightPlugin: Plugin = {
161
title: "Playwright",
162
enablers: ["@playwright/test", "playwright"],
163
config: ["playwright.config.{js,ts}"],
164
entry: ["**/*.{test,spec}.{js,ts}"]
165
};
166
```
167
168
### Build Tool Plugins
169
170
```typescript
171
// Webpack plugin
172
const webpackPlugin: Plugin = {
173
title: "Webpack",
174
enablers: ["webpack"],
175
config: ["webpack.config.{js,ts}"],
176
entry: ["webpack.config.{js,ts}"]
177
};
178
179
// Vite plugin
180
const vitePlugin: Plugin = {
181
title: "Vite",
182
enablers: ["vite"],
183
config: ["vite.config.{js,ts,mjs}"],
184
entry: ["vite.config.{js,ts,mjs}"]
185
};
186
187
// Rollup plugin
188
const rollupPlugin: Plugin = {
189
title: "Rollup",
190
enablers: ["rollup"],
191
config: ["rollup.config.{js,ts,mjs}"],
192
entry: ["rollup.config.{js,ts,mjs}"]
193
};
194
```
195
196
### Plugin Options
197
198
Configuration options passed to plugin functions.
199
200
```typescript { .api }
201
interface PluginOptions {
202
/** Root working directory */
203
rootCwd: string;
204
/** Current working directory */
205
cwd: string;
206
/** Set of npm script names */
207
manifestScriptNames: Set<string>;
208
/** Package.json manifest */
209
manifest: PackageJson;
210
/** Plugin configuration */
211
config: EnsuredPluginConfiguration;
212
/** Configuration file directory */
213
configFileDir: string;
214
/** Configuration file name */
215
configFileName: string;
216
/** Configuration file path */
217
configFilePath: string;
218
/** Production mode flag */
219
isProduction: boolean;
220
/** List of enabled plugins */
221
enabledPlugins: string[];
222
/** Function to get inputs from npm scripts */
223
getInputsFromScripts: GetInputsFromScriptsPartial;
224
}
225
226
interface EnsuredPluginConfiguration {
227
/** Configuration file patterns */
228
config: string[] | null;
229
/** Entry file patterns */
230
entry: string[] | null;
231
/** Project file patterns */
232
project: string[] | null;
233
}
234
235
type GetInputsFromScriptsPartial = (
236
npmScripts: string | string[] | Set<string>,
237
options?: Partial<GetInputsFromScriptsOptions>
238
) => Input[];
239
```
240
241
### Plugin Resolution
242
243
Functions for resolving plugin inputs and configurations.
244
245
```typescript { .api }
246
/**
247
* Input representing a file or dependency
248
*/
249
interface Input {
250
/** File path */
251
filePath: string;
252
/** Optional specifier for the input */
253
specifier?: string;
254
}
255
256
/**
257
* Resolve configuration function type
258
*/
259
type ResolveConfig<T = any> = (
260
config: T,
261
options: PluginOptions
262
) => Promise<Input[]> | Input[];
263
264
/**
265
* Resolve function type for finding additional inputs
266
*/
267
type Resolve = (
268
options: PluginOptions
269
) => Promise<Input[]> | Input[];
270
271
/**
272
* Resolve from AST function type
273
*/
274
type ResolveFromAST = (
275
sourceFile: ts.SourceFile,
276
options: PluginOptions & {
277
getSourceFile: GetSourceFile;
278
getReferencedInternalFilePath: GetReferencedInternalFilePath;
279
}
280
) => Input[];
281
282
type GetSourceFile = (filePath: string) => ts.SourceFile | undefined;
283
type GetReferencedInternalFilePath = (input: Input) => string | undefined;
284
```
285
286
**Plugin Resolution Examples:**
287
288
```typescript
289
// Example plugin with custom resolution
290
const examplePlugin: Plugin = {
291
title: "Example Plugin",
292
enablers: ["example-tool"],
293
294
resolve: async (options) => {
295
// Find additional entry points from package.json scripts
296
const inputs = options.getInputsFromScripts(
297
options.manifest.scripts?.build || [],
298
{ containingFilePath: options.configFilePath }
299
);
300
301
return inputs;
302
},
303
304
resolveConfig: async (config, options) => {
305
// Parse configuration file to find referenced files
306
return config.files?.map((file: string) => ({
307
filePath: path.resolve(options.configFileDir, file)
308
})) || [];
309
},
310
311
resolveFromAST: (sourceFile, options) => {
312
// Analyze TypeScript AST to find dynamic imports
313
const inputs: Input[] = [];
314
315
// Custom AST traversal logic here
316
// to find require() calls, dynamic imports, etc.
317
318
return inputs;
319
}
320
};
321
```
322
323
### Plugin Configuration
324
325
Plugins can be configured globally or per workspace.
326
327
```typescript { .api }
328
type PluginConfiguration = boolean | EnsuredPluginConfiguration;
329
330
type PluginsConfiguration = Record<PluginName, PluginConfiguration>;
331
332
interface WorkspaceConfiguration {
333
/** Plugin configurations for this workspace */
334
[pluginName: string]: PluginConfiguration | any;
335
}
336
```
337
338
**Configuration Examples:**
339
340
```json
341
{
342
"jest": true,
343
"eslint": {
344
"config": ["eslint.config.js"],
345
"entry": ["src/**/*.test.js"]
346
},
347
"webpack": false,
348
"workspaces": {
349
"frontend": {
350
"react": true,
351
"jest": {
352
"config": ["jest.config.frontend.js"]
353
}
354
}
355
}
356
}
357
```