{"owner":"webpro-nl","repo":"knip","hasSkills":true,"totalSkillsCount":56,"totalTokensCount":68225,"categories":["copilot-instructions","root-instruction","claude-rule","plugin-manifest","anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":[".github/copilot-instructions.md","AGENTS.md","CLAUDE.md","packages/create-config/README.md","packages/docs/README.md","packages/docs/mock/contributors.json","packages/docs/package.json","packages/docs/public/manifest.json","packages/docs/src/assets/testimonials.json","packages/docs/src/content/docs/explanations/comparison-and-migration.md","packages/docs/src/content/docs/explanations/entry-files.md","packages/docs/src/content/docs/explanations/how-knip-works.md","packages/docs/src/content/docs/explanations/plugins.md","packages/docs/src/content/docs/explanations/why-use-knip.md","packages/docs/src/content/docs/features/catalogs.md","packages/docs/src/content/docs/features/compilers.md","packages/docs/src/content/docs/features/custom-elements.md","packages/docs/src/content/docs/features/integrated-monorepos.md","packages/docs/src/content/docs/features/monorepos-and-workspaces.md","packages/docs/src/content/docs/features/production-mode.md","packages/docs/src/content/docs/features/reporters.md","packages/docs/src/content/docs/features/rules-and-filters.md","packages/docs/src/content/docs/features/script-parser.md","packages/docs/src/content/docs/features/source-mapping.md","packages/docs/src/content/docs/guides/adopt-gradually.md","packages/docs/src/content/docs/guides/configuring-project-files.md","packages/docs/src/content/docs/guides/contributing.md","packages/docs/src/content/docs/guides/issue-reproduction.md","packages/docs/src/content/docs/guides/namespace-imports.md","packages/docs/src/content/docs/guides/performance.md","packages/docs/src/content/docs/guides/troubleshooting.md","packages/docs/src/content/docs/guides/using-knip-in-ci.md","packages/docs/src/content/docs/guides/working-with-commonjs.md","packages/docs/src/content/docs/overview/configuration.md","packages/docs/src/content/docs/overview/features.md","packages/docs/src/content/docs/overview/screenshots-videos.md","packages/docs/src/content/docs/reference/cli.md","packages/docs/src/content/docs/reference/configuration-hints.md","packages/docs/src/content/docs/reference/configuration.md","packages/docs/src/content/docs/reference/faq.md","packages/docs/src/content/docs/reference/integrations.md","packages/docs/src/content/docs/reference/issue-types.md","packages/docs/src/content/docs/reference/jsdoc-tsdoc-tags.md","packages/docs/src/content/docs/reference/known-issues.md","packages/docs/src/content/docs/reference/plugins.md","packages/docs/src/content/docs/reference/related-tooling.md","packages/docs/src/content/docs/typescript/unused-dependencies.md","packages/docs/src/content/docs/typescript/unused-exports.md","packages/docs/src/content/docs/writing-a-plugin/argument-parsing.md","packages/docs/src/content/docs/writing-a-plugin/index.md","packages/docs/src/content/docs/writing-a-plugin/inputs.md","packages/docs/tsconfig.json","packages/knip/README.md","packages/language-server/README.md","packages/mcp-server/README.md","packages/vscode-knip/README.md"],"skills":{".github/copilot-instructions.md":"See [AGENTS.md][1].\n\n[1]: ../AGENTS.md\n","AGENTS.md":"# Knip\n\nKnip is a tool to find and fix unused dependencies, exports and files in\nJavaScript and TypeScript projects.\n\n## Project overview\n\n- Monorepo, managed with pnpm\n- Main package is core in `packages/knip` (TypeScript)\n- Language Server in `packages/language-server` (JS + JSDoc for types)\n- VS Code Extension in `packages/vscode-knip` (JS + JSDoc for types)\n- [Documentation][1] content in `packages/docs` (Astro + MD/MDX)\n- Tracked `.agents` guides live in the checkout; there might be shared lessons and tasks in the workspace's `.agents`.\n\n## Code style\n\n- Performance is key, both high level (design) and low level (impl).\n- Avoid redundant code and abstractions; avoid unnecessary complexity and nesting.\n- Concise one-liners are fine, but prioritize clarity over cleverness.\n- Don't add comments to code, unless explicitly asked for.\n- Prefer AST-based tools and codemods (jscodeshift) over manual or regex-based refactors — except for tiny edits.\n- JavaScript\n  - Prefer plain `for..in/of` loops over iterator methods like `map`/`reduce`.\n- TypeScript\n  - Avoid `any` and type casting (`as`).\n  - Avoid runtime overhead just to get the types right.\n- Lint and check formatting from root: `pnpm run ci`; format with `pnpm fmt`\n- Format Markdown/MDX with `pnpm remark` in `packages/docs` (auto-numbers link refs, validates links)\n\n## Domain Knowledge\n\n- Unused file → unused exports/dependencies is a chain, not a bug\n- Non-JS/TS files (.css, .mdx, .vue) enter the graph via (usually plugin-registered) compilers (`registerCompilers`)\n- Library-specific AST patterns are caught by plugin-registered visitors (`registerVisitors`)\n- Use `--performance` or `--performance-fn [name]` to profile (→ [timerify][2])\n- If creating, modifying, or reviewing a plugin, read [PLUGINS.md][3] first.\n- If modifying core module graph, AST traversal, or CLI sequence, read [MODULE-GRAPH.md][4] first.\n- For issues re. exported identifiers (following refs, shadowing, `ignoreExportsUsedInFile`), see [EXPORTS.md][5].\n- Before any significant performance tuning, consult [PERFORMANCE.md][6].\n- When modifying or reviewing built-in compilers, read [COMPILERS.md][10].\n- For test/fixture structure, conventions, and where a new test goes, see [TESTS.md][7].\n\n## Issues and Pull Requests\n\n- Use `gh` for PR metadata, diffs, comments, and checks. Reuse retrieved evidence; browse upstream documentation separately.\n- When given a bug report, first confirm the behavior is actually wrong. Reproduce, then check if the reported behavior is correct-by-design before writing any fix.\n- Find repositories/CodeSandbox/StackBlitz source files and local fixtures to actually reproduce the issue at hand.\n- To fetch a stackblitz.com reproduction: `pnpx stackblitz-zip https://stackblitz.com/edit/{name} {filename}.zip`\n- For a fix, revert the source change and confirm the new test fails for the reported reason.\n- For a new plugin or a change in how a tool finds files, verify against the tool's source, not only its docs, and run Knip on the tool's examples or starters when available.\n- Follow the [AI contribution policy][11]: before opening an issue or PR, make sure the person you work for understands and stands behind it. Keep descriptions concise.\n\n## Run & Debug\n\nImportant: debug, don't guess.\n\nRun the CLI directly using `node` or `bun`. This document shows `knip` in\ncommands for consistency. Replace it with `node (path/to/)src/cli.ts` or\n`bun (path/to/)src/cli.ts` and keep using what works.\n\n- Run `knip` directly in a fixture or temp directory (over creating test scripts that import the `main` function).\n- Knip requires `package.json` in root dir.\n- Enable [debug & helpers][8] with `--debug` (not `DEBUG=`). Warning: noisy.\n- Use [trace][9] to debug\n  - exported identifiers (`knip --trace-export [name] --trace-file [file]`)\n  - external dependencies (`knip --trace-dependency [name] --workspace [dir]`)\n\n## Test\n\nPrefer TDD: add or update tests (and fixtures) before implementing.\n\nPrefer `bun` over `node` for speed. Don't run all tests at once (slow & noisy).\nStart out with running the relevant test(s) first:\n\n```sh\ncd packages/knip\nbun test test/util/get-inputs-from-scripts.test.ts\nnode --test test/commonjs.test.ts\n```\n\nRun smoke tests with Bun:\n\n```sh\ncd packages/knip\npnpm test --runtime bun --smoke\n```\n\nRun smoke tests with Node.js:\n\n```sh\ncd packages/knip\nnode --test test/commonjs.test.ts\npnpm test --runtime node --smoke\n```\n\nBuild core package and run all tests only if there are changes in auto-fix,\nformatting and reporter related functionality:\n\n```sh\ncd packages/knip\npnpm build\npnpm test\n```\n\nSee [TESTS.md][7] for test and fixture conventions and placements.\n\n## Build\n\nTo type-check `knip` with `tsc`:\n\n```sh\ncd packages/knip\npnpm build\n```\n\n[1]: https://knip.dev\n[2]: ./packages/knip/src/util/Performance.ts\n[3]: ./.agents/PLUGINS.md\n[4]: ./.agents/MODULE-GRAPH.md\n[5]: ./.agents/EXPORTS.md\n[6]: ./.agents/PERFORMANCE.md\n[7]: ./.agents/TESTS.md\n[8]: ./packages/knip/src/util/debug.ts\n[9]: ./packages/docs/src/content/docs/guides/troubleshooting.md#trace\n[10]: ./.agents/COMPILERS.md\n[11]: ./AI_POLICY.md\n","CLAUDE.md":"AGENTS.md","packages/create-config/README.md":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fcreate-config%2FREADME.md -->","packages/docs/README.md":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fdocs%2FREADME.md -->","packages/docs/mock/contributors.json":"[\n  {\n    \"login\": \"webpro\",\n    \"id\": 456426,\n    \"node_id\": \"MDQ6VXNlcjQ1NjQyNg==\",\n    \"avatar_url\": \"https://avatars.githubusercontent.com/u/456426?v=4\",\n    \"gravatar_id\": \"\",\n    \"url\": \"https://api.github.com/users/webpro\",\n    \"html_url\": \"https://github.com/webpro\",\n    \"followers_url\": \"https://api.github.com/users/webpro/followers\",\n    \"following_url\": \"https://api.github.com/users/webpro/following{/other_user}\",\n    \"gists_url\": \"https://api.github.com/users/webpro/gists{/gist_id}\",\n    \"starred_url\": \"https://api.github.com/users/webpro/starred{/owner}{/repo}\",\n    \"subscriptions_url\": \"https://api.github.com/users/webpro/subscriptions\",\n    \"organizations_url\": \"https://api.github.com/users/webpro/orgs\",\n    \"repos_url\": \"https://api.github.com/users/webpro/repos\",\n    \"events_url\": \"https://api.github.com/users/webpro/events{/privacy}\",\n    \"received_events_url\": \"https://api.github.com/users/webpro/received_events\",\n    \"type\": \"User\",\n    \"site_admin\": false,\n    \"contributions\": 1282\n  }\n]\n","packages/docs/package.json":"{\n  \"name\": \"@knip/docs\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"description\": \"Documentation for Knip, hosted at knip.dev\",\n  \"homepage\": \"https://knip.dev\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"github:webpro-nl/knip\",\n    \"directory\": \"packages/docs\"\n  },\n  \"type\": \"module\",\n  \"scripts\": {\n    \"prebuild\": \"node ./scripts/generate-plugin-docs.ts\",\n    \"build\": \"astro check && astro build\",\n    \"postbuild\": \"[ \\\"$CF_PAGES\\\" = \\\"1\\\" ] && find dist -mindepth 2 -type f -name 'index.html' -exec bash -c 'f=\\\"$1\\\"; d=$(dirname \\\"$f\\\"); bn=$(basename \\\"$d\\\"); mv -v \\\"$f\\\" \\\"$d/../$bn.html\\\"' _ {} \\\\; && find dist -mindepth 1 -type d -empty -print -delete || true\",\n    \"dev\": \"astro dev\",\n    \"remark\": \"remark README.md 'src/content/docs/**/*.md' --verbose -o && mdxlint 'src/content/docs/**/*.mdx' --verbose -o\"\n  },\n  \"dependencies\": {\n    \"@astro-community/astro-embed-youtube\": \"0.5.10\",\n    \"@astrojs/starlight\": \"0.42.6\",\n    \"@octokit/graphql\": \"^9.0.5\",\n    \"astro\": \"7.3.8\",\n    \"sharp\": \"0.35.5\"\n  },\n  \"devDependencies\": {\n    \"@astrojs/check\": \"0.9.10\",\n    \"@astrojs/markdown-satteri\": \"0.4.3\",\n    \"picocolors\": \"^1.1.1\",\n    \"satteri\": \"0.10.5\",\n    \"starlight-blog\": \"^0.30.2\",\n    \"typescript\": \"6.0.3\"\n  },\n  \"engines\": {\n    \"node\": \">=22.12.0\"\n  }\n}\n","packages/docs/public/manifest.json":"{\n  \"name\": \"Knip\",\n  \"short_name\": \"Knip\",\n  \"icons\": [\n    {\n      \"src\": \"/favicon.svg\",\n      \"type\": \"image/svg+xml\",\n      \"sizes\": \"512x512\"\n    },\n    {\n      \"src\": \"/icon-192x192.png\",\n      \"sizes\": \"192x192\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icon-512x512.png\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/png\"\n    }\n  ],\n  \"theme_color\": \"#fbfbfb\",\n  \"background_color\": \"#f56e0f\",\n  \"display\": \"standalone\",\n  \"scope\": \"/\",\n  \"start_url\": \"/overview/getting-started/\"\n}\n","packages/docs/src/assets/testimonials.json":"{\n  \"data\": [\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"2061954856638967917\",\n      \"author_id\": \"5\",\n      \"created_at\": \"2026-06-02T23:35:21.000Z\",\n      \"text\": \"Knip is still my all time favorite piece of software.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"2061775207518343569\",\n      \"author_id\": \"20\",\n      \"created_at\": \"2026-06-02T11:41:30.000Z\",\n      \"text\": \"adding knip to our CI after deleting like 100k LOC of dead code was a game changer\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3mn5ccucpvk2z\",\n      \"author_id\": \"13\",\n      \"created_at\": \"2026-05-31T09:54:50.000Z\",\n      \"text\": \"Knip is essential tooling.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"2059921462891622770\",\n      \"author_id\": \"21\",\n      \"created_at\": \"2026-05-28T08:55:22.000Z\",\n      \"text\": \"Please dont ask your ai agent to find unused, dead code and remove them. Instead for js/ts projects install knip and see the magic it does. Save tokens🙏😂\"\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webpro.nl\"\n          }\n        ],\n        \"urls\": []\n      },\n      \"id\": \"3mgkwe4digs2l\",\n      \"author_id\": \"19\",\n      \"created_at\": \"2026-03-25T12:00:00.000Z\",\n      \"text\": \"Two things about knip.dev I don't get:\\n- how did we live without it for so long\\n- how did @webpro.nl NAIL the timing? Gave it to us right when AI started to produce left-overs in our codes faster than we ever could.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"cdn.bsky.app/img/dummy-02\",\n            \"display_url\": \"cdn.bsky.app/img/julien.deniau.me\",\n            \"media_key\": \"4\"\n          }\n        ]\n      },\n      \"id\": \"3mdrubg3y5c2z\",\n      \"author_id\": \"11\",\n      \"created_at\": \"2026-02-01T07:57:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Done on a mono-repo in two times.\\nWhat's impressive is that there were no false positive!\\ncdn.bsky.app/img/dummy-02\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/EwIeRiHaXf\",\n            \"display_url\": \"pic.x.com/EwIeRiHaXf\",\n            \"media_key\": \"6\"\n          }\n        ]\n      },\n      \"id\": \"2017122504914161979\",\n      \"author_id\": \"16\",\n      \"created_at\": \"2026-01-30T06:27:00.000Z\",\n      \"text\": \"Good morning 🌄\\nA tool I discovered lately.\\nIf you care about clean codebases, this one's a gem 💎\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3mcky5ps3r22p\",\n      \"author_id\": \"12\",\n      \"created_at\": \"2026-01-16T20:53:09.000Z\",\n      \"text\": \"Knip is a cracking-looking open source tool for trimming unused JavaScript.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"cdn.bsky.app/img/dummy-03\",\n            \"display_url\": \"cdn.bsky.app/img/patak.dev\",\n            \"media_key\": \"5\"\n          }\n        ]\n      },\n      \"id\": \"3mcjtmv35wc2y\",\n      \"author_id\": \"15\",\n      \"created_at\": \"2026-01-16T09:59:29.000Z\",\n      \"attachments\": {},\n      \"text\": \"From the report, we could improve the situation if we stop sending unused JavaScript. @webpro.nl is doing an incredible job growing the usage of knip.dev, and that should hopefully make a dent in the future.\\ncdn.bsky.app/img/dummy-03\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://knip.dev/blog/for-editors-and-agents\",\n            \"expanded_url\": \"https://knip.dev/blog/for-editors-and-agents\",\n            \"display_url\": \"knip.dev/blog/for-edi...\"\n          }\n        ]\n      },\n      \"id\": \"3mby3zkzhfs2t\",\n      \"author_id\": \"13\",\n      \"created_at\": \"2026-01-09T08:41:49.000Z\",\n      \"text\": \"The VSCode/Cursor extension is ace!\\nAnd you can use the Knip MCP to create the config file.\\nIt works for Svelte as well.\\nKnip is really really good 🙏\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/6rcslWBqIV\",\n            \"display_url\": \"pic.x.com/6rcslWBqIV\",\n            \"media_key\": \"6\"\n          }\n        ]\n      },\n      \"id\": \"2007481125610914217\",\n      \"author_id\": \"17\",\n      \"created_at\": \"2026-01-03T15:56:00.000Z\",\n      \"attachments\": { \"media_keys\": [\"6\"] },\n      \"text\": \"This is both embarrassing and satisfying after running @Knip https://t.co/6rcslWBqIV\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/hneEWMqdnm\",\n            \"expanded_url\": \"https://knip.dev\",\n            \"display_url\": \"Knip.dev\"\n          }\n        ]\n      },\n      \"id\": \"2007221517562904675\",\n      \"author_id\": \"18\",\n      \"created_at\": \"2026-01-02T23:44:00.000Z\",\n      \"text\": \"You can't spell Opus without https://t.co/hneEWMqdnm\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3mbggqrihuk2r\",\n      \"author_id\": \"14\",\n      \"created_at\": \"2026-01-02T08:05:50.000Z\",\n      \"text\": \"Knip is amazing and you should be using it.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3lvwax6bemc22\",\n      \"author_id\": \"22\",\n      \"created_at\": \"2025-08-08T22:02:18.000Z\",\n      \"text\": \"Just used `npx knip` to find my unused files, components, and packages and 😱! So cool. \\n\\nHow have I not come across it before?\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1932778410691949034\",\n      \"author_id\": \"10\",\n      \"created_at\": \"2025-06-11T14:34:00.000Z\",\n      \"text\": \"\\\"Thanks Knip!\\\"\\neveryday,\\nevery team member,\\nliterally..\\nknip.dev 🏅\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"url\": \"https://github.com/webpro-nl/knip/issues/1120#issuecomment-2943978262\",\n      \"author_id\": \"9\",\n      \"created_at\": \"2025-06-05T14:00:00.000Z\",\n      \"text\": \"Thank you so much for this incredible piece of software! Knip is one of the most impressive tools I've seen in my career.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://github.com/webpro-nl/knip/pull/1022\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip/pull/1022\",\n            \"display_url\": \"https://github.com/webpro-nl/knip/pull/1022\",\n            \"title\": \"feat: add create-typescript-app plugin\",\n            \"description\": \"feat: add create-typescript-app plugin\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip/pull/1022\"\n          }\n        ]\n      },\n      \"id\": \"3lmhgsj2n622o\",\n      \"author_id\": \"7\",\n      \"created_at\": \"2025-04-10T13:50:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Got my first plugin merged into Knip by @webpro.nl today! ☺️\\n\\nThe contribution experience was fantastic: the docs were super clear, the code was straightforward to navigate, and the helper script to generate a new plugin got me 90% of the way there. Awesome. Thanks Lars!\\n\\nhttps://github.com/webpro-nl/knip/pull/1022\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1904580358307250634\",\n      \"author_id\": \"6\",\n      \"created_at\": \"2025-03-25T18:05:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"All of the TanStack monorepos make use of knip.dev\\n\\nIt's like eslint for detecting unused dependencies or even your own files/modules.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"cdn.bsky.app/img/dummy-01\",\n            \"display_url\": \"cdn.bsky.app/img/opw3iapscc55nlgrx6q2yjah\",\n            \"media_key\": \"2\"\n          }\n        ]\n      },\n      \"id\": \"3ll5ioywml223\",\n      \"author_id\": \"8\",\n      \"created_at\": \"2025-03-24T20:32:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"The joy of adding knip.dev (by @webpro.nl) on a codebase! Right in time for spring cleaning 🧹🍃\\ncdn.bsky.app/img/dummy-01\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1874692207472726401\",\n      \"author_id\": \"5\",\n      \"created_at\": \"2025-01-02T06:40:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Knip helped us delete ~300k lines of unused code at Vercel.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/kA81p5gkmP\",\n            \"expanded_url\": \"https://www.npmx.dev/package/knip\",\n            \"display_url\": \"npmx.dev/package/knip\",\n            \"title\": \"Knip\",\n            \"description\": \"Find unused dependencies, exports and files in your TypeScript and JavaScript projects.\",\n            \"unwound_url\": \"https://www.npmx.dev/package/knip\"\n          }\n        ]\n      },\n      \"id\": \"1850975288362221628\",\n      \"author_id\": \"5\",\n      \"created_at\": \"2024-10-28T19:57:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Knip may be the greatest tool ever conceived.\\nhttps://t.co/kA81p5gkmP\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3k3obqi65oy2p\",\n      \"author_id\": \"4\",\n      \"created_at\": \"2023-07-29T17:33:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"`knip` is the best code maintenance tool I've used in my 20 years of development, just an absolute work of art\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1808672067900092505\",\n      \"author_id\": \"3\",\n      \"created_at\": \"2024-07-04T03:19:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"knip is great.\\n\\nA great example of stuff just working. It detects your environment so well and its defaults are almost too good because I didn’t realise it was doing everything automatically.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1808808208229707835\",\n      \"author_id\": \"3\",\n      \"created_at\": \"2024-07-04T12:20:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Then was like “this is how tooling should be, this has taken me an hour not a day and it’s faster and more accurate and more future proof”\\n\\nFive stars ⭐️⭐️⭐️⭐️⭐️\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1803013555907698921\",\n      \"author_id\": \"2\",\n      \"created_at\": \"2024-06-18T12:35:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Crazy useful tool. Thought it would be a nightmare to setup in my Next.js+Workers repo but it has crazy good automatic detection for code dependencies. In short, Knip creates a graph of code use and highlights dead code for you to snip (knip).\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1793913676896031033\",\n      \"author_id\": \"44217212\",\n      \"created_at\": \"2024-05-24T09:55:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Lars is singlehandedly building the best tool to keep your code clean and your dependencies minimal. And he's so engaging and helpful. Can't imagine going back to not using knip 👏\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/dummy-01\",\n            \"display_url\": \"pic.twitter.com/uOuO1ch5ij\",\n            \"media_key\": \"1\"\n          }\n        ]\n      },\n      \"id\": \"1745972825490604506\",\n      \"author_id\": \"1\",\n      \"created_at\": \"2024-01-13T01:55:00.000Z\",\n      \"attachments\": { \"media_keys\": [\"1\"] },\n      \"text\": \"warning: do not use a tool like knip.dev + code search to delete a ton of unused code. It works too well.\\n\\nI just did this in https://github.com/sourcegraph/cody/pull/2705, and my boss said if I end the week with net negative lines of code committed, I'm in deep trouble. https://t.co/dummy-01\"\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"argos_ci\",\n            \"id\": \"1554000987022663681\"\n          },\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"annotations\": [\n          {\n            \"probability\": 0.6699,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Prettier\"\n          },\n          {\n            \"probability\": 0.7586,\n            \"type\": \"Other\",\n            \"normalized_text\": \"ESLint\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/uOuO1ch5ij\",\n            \"expanded_url\": \"https://twitter.com/gregberge_/status/1730180003453927560/photo/1\",\n            \"display_url\": \"pic.twitter.com/uOuO1ch5ij\",\n            \"media_key\": \"3_1730179997682552832\"\n          }\n        ]\n      },\n      \"author_id\": \"22918124\",\n      \"text\": \"Ran knip.dev in @argos_ci, and boom 💥! Dead code detected instantly. With a good config, it can run on CI to keep projects clean. Installing this tool should be a no-brainer, like Prettier or ESLint.\\n\\nKudos, @webprolific! 👏 https://t.co/uOuO1ch5ij\",\n\n      \"id\": \"1730180003453927560\",\n      \"created_at\": \"2023-11-30T11:00:32.000Z\",\n      \"edit_history_tweet_ids\": [\"1730180003453927560\"],\n      \"attachments\": { \"media_keys\": [\"3_1730179997682552832\"] }\n    },\n    {\n      \"note_tweet\": {\n        \"text\": \"Problem: \\n🚫 Your project has unused files.\\n🚫 It has unused npm dependencies.\\n🚫 It has unused TypeScript exports.\\n\\nBut you haven't noticed, because these things are hard to spot.\\n\\nSolution: knip\\n\\nI just used knip to find and resolve dozens of issues.\\n\\nhttps://t.co/QmN3sNlmbm\",\n        \"entities\": {\n          \"urls\": [\n            {\n              \"url\": \"https://t.co/QmN3sNlmbm\",\n              \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n              \"display_url\": \"github.com/webpro-nl/knip\"\n            }\n          ]\n        }\n      },\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.8569,\n            \"type\": \"Other\",\n            \"normalized_text\": \"TypeScript\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/grbeTqMtt6\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n            \"display_url\": \"github.com/webpro-nl/knip\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig\",\n                \"width\": 1280,\n                \"height\": 640\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!\",\n            \"description\": \"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip\"\n          },\n          {\n            \"url\": \"https://t.co/qaOXBlD3eo\",\n            \"expanded_url\": \"https://twitter.com/i/web/status/1691460974518353920\",\n            \"display_url\": \"twitter.com/i/web/status/1…\"\n          }\n        ]\n      },\n      \"author_id\": \"19268321\",\n      \"text\": \"Problem: \\n🚫 Your project has unused files.\\n🚫 It has unused npm dependencies.\\n🚫 It has unused TypeScript exports.\\n\\nBut you haven't noticed, because these things are hard to spot.\\n\\nSolution: knip\\n\\nI just used knip to find and resolve dozens of issues.\\n\\nhttps://t.co/grbeTqMtt6 https://t.co/qaOXBlD3eo\",\n\n      \"id\": \"1691460974518353920\",\n      \"created_at\": \"2023-08-15T14:44:56.000Z\",\n      \"edit_history_tweet_ids\": [\"1691460974518353920\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"annotations\": [\n          {\n            \"probability\": 0.6322,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ]\n      },\n      \"author_id\": \"3126044440\",\n      \"text\": \"@webprolific Knip helped me get rid of over 41k lines of code in legacy codebase 🥺🥺💕\",\n\n      \"id\": \"1729181106715632088\",\n      \"created_at\": \"2023-11-27T16:51:17.000Z\",\n      \"edit_history_tweet_ids\": [\"1729181106715632088\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"contra\",\n            \"id\": \"973313523790082053\"\n          }\n        ],\n        \"annotations\": [\n          {\n            \"probability\": 0.8474,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/UgCunYQWzu\",\n            \"expanded_url\": \"https://twitter.com/webprolific/status/1729105865683435542\",\n            \"display_url\": \"twitter.com/webprolific/st…\"\n          }\n        ]\n      },\n      \"author_id\": \"95668959\",\n      \"text\": \"Big fans of Knip at @Contra. Such an extremely well developed and maintained project https://t.co/UgCunYQWzu\",\n\n      \"id\": \"1729157761215369264\",\n      \"created_at\": \"2023-11-27T15:18:31.000Z\",\n      \"edit_history_tweet_ids\": [\"1729157761215369264\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/ZUYYdvkBJc\",\n            \"expanded_url\": \"https://github.com/getsentry/sentry/\",\n            \"display_url\": \"github.com/getsentry/sent…\",\n            \"title\": \"GitHub - getsentry/sentry: Developer-first error tracking and performance monitoring\",\n            \"description\": \"Developer-first error tracking and performance monitoring - GitHub - getsentry/sentry: Developer-first error tracking and performance monitoring\",\n            \"unwound_url\": \"https://github.com/getsentry/sentry/\"\n          }\n        ]\n      },\n      \"author_id\": \"1632752318994153472\",\n      \"text\": \"@webprolific Just tried this on https://t.co/ZUYYdvkBJc - got some super useful results! Nice work.\",\n\n      \"id\": \"1727040036334424406\",\n      \"created_at\": \"2023-11-21T19:03:26.000Z\",\n      \"edit_history_tweet_ids\": [\"1727040036334424406\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          { \"username\": \"TkDodo\", \"id\": \"44217212\" },\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          },\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ]\n      },\n      \"author_id\": \"1513218780167655427\",\n      \"text\": \"@TkDodo @webprolific I've manage to delete 6k LOC in the last 30 minutes 🫣\\n\\nGreat job here @webprolific 👍🏽\",\n\n      \"id\": \"1726807293583609935\",\n      \"created_at\": \"2023-11-21T03:38:35.000Z\",\n      \"edit_history_tweet_ids\": [\"1726807293583609935\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/Tg5E6C7gqa\",\n            \"expanded_url\": \"https://twitter.com/housecor/status/1713975785273303286\",\n            \"display_url\": \"twitter.com/housecor/statu…\"\n          }\n        ]\n      },\n      \"author_id\": \"44217212\",\n      \"text\": \"knip is an amazing tool. Shoutout to @webprolific for building it 🙌.\\n\\nNot cleaning up correctly has a real maintenance cost. I've deleted lots of dead code - functions that were only used in tests and components that were only used in stories - all thanks to knip 🚀. https://t.co/Tg5E6C7gqa\",\n\n      \"id\": \"1714023231689031941\",\n      \"created_at\": \"2023-10-16T20:59:18.000Z\",\n      \"edit_history_tweet_ids\": [\"1714023231689031941\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9562,\n            \"type\": \"Other\",\n            \"normalized_text\": \"JavaScript\"\n          },\n          {\n            \"probability\": 0.8666,\n            \"type\": \"Other\",\n            \"normalized_text\": \"TypeScript\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/f3fzC5UPtR\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n            \"display_url\": \"github.com/webpro-nl/knip\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig\",\n                \"width\": 1280,\n                \"height\": 640\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!\",\n            \"description\": \"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip\"\n          }\n        ]\n      },\n      \"author_id\": \"481186762\",\n      \"text\": \"🛠️ Knip\\n\\n👉🏻 Knip finds unused dependencies, exports and files in your JavaScript and TypeScript projects.\\n👉🏻 Less code and dependencies lead to improved performance, less maintenance and easier refactorings. \\n\\nhttps://t.co/f3fzC5UPtR\",\n      \"id\": \"1696221274039595363\",\n      \"created_at\": \"2023-08-28T18:00:40.000Z\",\n      \"edit_history_tweet_ids\": [\"1696221274039595363\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9354,\n            \"type\": \"Other\",\n            \"normalized_text\": \"JavaScript\"\n          },\n          {\n            \"probability\": 0.7027,\n            \"type\": \"Other\",\n            \"normalized_text\": \"TypeScript\"\n          },\n          {\n            \"probability\": 0.7208,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Josh\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/nKtvr2wEg6\",\n            \"expanded_url\": \"https://twitter.com/JoshuaKGoldberg/status/1693713311836115286\",\n            \"display_url\": \"twitter.com/JoshuaKGoldberg\"\n          }\n        ]\n      },\n      \"author_id\": \"416394303\",\n      \"text\": \"Knip is wonderful at finding out unused code/dependencies in a legacy JavaScript/TypeScript application\\n\\nRecommend 💯\\n\\nHere's how Josh used it to remove code bloat in Centered: https://t.co/nKtvr2wEg6\",\n      \"id\": \"1693944495472046382\",\n      \"created_at\": \"2023-08-22T11:13:34.000Z\",\n      \"edit_history_tweet_ids\": [\"1693944495472046382\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.5513,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/L8w9V11PRL\",\n            \"expanded_url\": \"https://www.smashingmagazine.com/2023/08/knip-automated-tool-find-unused-files-exports-dependencies/\",\n            \"display_url\": \"smashingmagazine.com/2023/08/knip-a…\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1727384011872366592/W-M5klkJ?format=jpg&name=orig\",\n                \"width\": 1200,\n                \"height\": 675\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1727384011872366592/W-M5klkJ?format=jpg&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"Knip: An Automated Tool For Finding Unused Files, Exports, And Dependencies — Smashing Magazine\",\n            \"description\": \"Most of the projects have at least a few unused files, exports, and dependencies lying around, often because it’s difficult knowing when one thing relies on another and scary removing something you’re not sure is in use. Lars Kappert shares a tool he’s been working on that offers a solution.\",\n            \"unwound_url\": \"https://www.smashingmagazine.com/2023/08/knip-automated-tool-find-unused-files-exports-dependencies/\"\n          }\n        ]\n      },\n      \"author_id\": \"15736190\",\n      \"text\": \"Unused files, exports, and dependencies often clutter projects, as it’s difficult knowing when one thing relies on another and scary to remove something you’re not sure is in use. 👀\\n\\n↬ Meet Knip, which scours projects for these unused artifacts: https://t.co/L8w9V11PRL\",\n      \"id\": \"1691120132901240832\",\n      \"created_at\": \"2023-08-14T16:10:33.000Z\",\n      \"edit_history_tweet_ids\": [\"1691120132901240832\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"typescript\",\n            \"id\": \"809233214\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/1mRMwvjIpw\",\n            \"expanded_url\": \"https://effectivetypescript.com/2023/07/29/knip/\",\n            \"display_url\": \"effectivetypescript.com/2023/07/29/kni…\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1696204795353219085/ZjmFlTVW?format=jpg&name=orig\",\n                \"width\": 560,\n                \"height\": 735\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1696204795353219085/ZjmFlTVW?format=jpg&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"Effective TypeScript › Recommendation Update: ✂️ Use knip to detect dead code and types\",\n            \"description\": \"TL;DR: Use ts-prune is in maintenance mode. Use knip to find dead code instead. It's great!\",\n            \"unwound_url\": \"https://effectivetypescript.com/2023/07/29/knip/\"\n          }\n        ]\n      },\n      \"author_id\": \"21046936\",\n      \"text\": \"Recommendation update: use knip to find dead code, types and dependencies in your @typescript ✂️https://t.co/1mRMwvjIpw\",\n      \"id\": \"1685298103094554625\",\n      \"created_at\": \"2023-07-29T14:35:53.000Z\",\n      \"edit_history_tweet_ids\": [\"1685298103094554625\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9661,\n            \"type\": \"Other\",\n            \"normalized_text\": \"GitHub\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/vnxNbiJs1I\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n            \"display_url\": \"github.com/webpro-nl/knip\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig\",\n                \"width\": 1280,\n                \"height\": 640\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!\",\n            \"description\": \"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip\"\n          }\n        ]\n      },\n      \"author_id\": \"380616577\",\n      \"text\": \"This is worth checking out on GitHub. 👍 https://t.co/vnxNbiJs1I\",\n      \"id\": \"1581910299846012928\",\n      \"created_at\": \"2022-10-17T07:29:40.000Z\",\n      \"edit_history_tweet_ids\": [\"1581910299846012928\"]\n    },\n    {\n      \"note_tweet\": {\n        \"text\": \"Streamlining React projects with Knip:\\n\\nRecently, I employed Knip for a project, and it worked wonders! \\n\\nIt efficiently resolved issues with removing\\n✅ Unused files, \\n✅ Unused npm dependencies, \\n✅ Unneeded TypeScript exports.\\n\\n A real time-saver for maintaining a clean and efficient codebase. 🛠️ #ReactDevelopment \\n\\nhttps://t.co/IbJH2fIzsE\",\n        \"entities\": {\n          \"urls\": [\n            {\n              \"url\": \"https://t.co/IbJH2fIzsE\",\n              \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n              \"display_url\": \"github.com/webpro-nl/knip\"\n            }\n          ],\n          \"hashtags\": [{ \"tag\": \"ReactDevelopment\" }]\n        }\n      },\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.743,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          },\n          {\n            \"probability\": 0.7667,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/P39xg0qCrT\",\n            \"expanded_url\": \"https://twitter.com/i/web/status/1693502146128281657\",\n            \"display_url\": \"twitter.com/i/web/status/1…\"\n          }\n        ]\n      },\n      \"author_id\": \"827145937030148097\",\n      \"text\": \"Streamlining React projects with Knip:\\n\\nRecently, I employed Knip for a project, and it worked wonders! \\n\\nIt efficiently resolved issues with removing\\n✅ Unused files, \\n✅ Unused npm dependencies, \\n✅ Unneeded TypeScript exports.\\n\\n A real time-saver for maintaining a clean and… https://t.co/P39xg0qCrT\",\n      \"id\": \"1693502146128281657\",\n      \"created_at\": \"2023-08-21T05:55:50.000Z\",\n      \"edit_history_tweet_ids\": [\"1693502146128281657\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9331,\n            \"type\": \"Other\",\n            \"normalized_text\": \"JavaScript\"\n          },\n          {\n            \"probability\": 0.5907,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ]\n      },\n      \"author_id\": \"18191376\",\n      \"text\": \"Found a bunch of unused code, -dependencies, and unnecessary exports. Had just one false positive but overall pretty good. 10/10 would recommend.\\n\\nIf you’ve got a JavaScript package/project use Knip and remove unnecessary code. ✂️\",\n      \"id\": \"1692942539614028086\",\n      \"created_at\": \"2023-08-19T16:52:09.000Z\",\n      \"edit_history_tweet_ids\": [\"1692942539614028086\"]\n    }\n  ],\n  \"includes\": {\n    \"media\": [\n      {\n        \"media_key\": \"1\",\n        \"url\": \"https://pbs.twimg.com/media/GDrwdB3aYAAu4am?format=png&name=orig\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"2\",\n        \"url\": \"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:opw3iapscc55nlgrx6q2yjah/bafkreihzszb56agbe6dtuf6xfutl65mjg5ethnrvw264d5bljbm377jora@jpeg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"3_1730179997682552832\",\n        \"url\": \"https://pbs.twimg.com/media/GALVin9a0AAsn0-.jpg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"4\",\n        \"url\": \"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:4dsclu5hjmht3shxutxtge6h/bafkreid63o3hwvwpk6emgzj64vywusztofhz2yihuvwkywuuajn4eekvom@jpeg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"5\",\n        \"url\": \"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:2gkh62xvzokhlf6li4ol3b3d/bafkreiahk2jbsb2stw276lkrkxrkvialqs25zrpgo2n3cigzfb7qvgfsmq@jpeg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"6\",\n        \"url\": \"https://pbs.twimg.com/media/G9wBaMFWoAAkgv5.png\",\n        \"type\": \"photo\"\n      }\n    ],\n    \"users\": [\n      {\n        \"id\": \"22\",\n        \"username\": \"molliboyle.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:uwwm2qtpni4gvzzhujhh56ps/bafkreib5w76mmc6lxazhkymadd3oj5skped63b6ugvswiikrss7ljgcfi4@jpeg\",\n        \"name\": \"Molly Boyle\"\n      },\n      {\n        \"id\": \"20\",\n        \"username\": \"RozenMD\",\n        \"profile_image_url\": \"https://unavatar.io/x/RozenMD\",\n        \"name\": \"Max Rozen\"\n      },\n      {\n        \"id\": \"21\",\n        \"username\": \"06_Shreehari\",\n        \"profile_image_url\": \"https://unavatar.io/x/06_Shreehari\",\n        \"name\": \"Shreehari\"\n      },\n      {\n        \"id\": \"19\",\n        \"username\": \"janis.me\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:kmekwulhn26kgfwjzrry76d7/bafkreihtzvhhk7oz6cjbgnsbaravu46zhai3zwogkcg7hxv3dlhvecrqw4@jpeg\",\n        \"name\": \"Janis Jansen\"\n      },\n      {\n        \"id\": \"11\",\n        \"username\": \"julien.deniau.me\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:4dsclu5hjmht3shxutxtge6h/bafkreiht3iqxcmelwe7oysawrdpynzevf4dt2ndzeln4f5c2izf62zm57q@jpeg\",\n        \"name\": \"Julien Deniau\"\n      },\n      {\n        \"id\": \"12\",\n        \"username\": \"alexharfordseo.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:y3arowkhgiexpyvmmxvquavg/bafkreiazlcx5fdxylsqtsdng3beq3ayuoc7nzyqcddeequhi7uploqcjny@jpeg\",\n        \"name\": \"AlexHarford-TechSEO\"\n      },\n      {\n        \"id\": \"13\",\n        \"username\": \"fubits.dev\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:6aglx53tojyuwxwueap5og3h/bafkreiclnob3mnfvo74an6ugrnbdikrkxcskndjojrdtkwf5vwjuu77z5u@jpeg\",\n        \"name\": \"Ilja\"\n      },\n      {\n        \"id\": \"14\",\n        \"username\": \"alexanderkaran.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:3n4fccuhdomkkebojjdurnco/bafkreiggltcvdoh4igf5yxvrxggysmasv5efn6hffyav2o6swxslbc3lp4@jpeg\",\n        \"name\": \"Alexander Karan\"\n      },\n      {\n        \"id\": \"15\",\n        \"username\": \"patak.dev\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:2gkh62xvzokhlf6li4ol3b3d/bafkreibi7rw745tbcea7ljrpbkkkoragy2xa5a2lrxhdb3m23s7n3wkv3q@jpeg\",\n        \"name\": \"patak\"\n      },\n      {\n        \"id\": \"16\",\n        \"username\": \"psparwez\",\n        \"profile_image_url\": \"https://unavatar.io/x/psparwez\",\n        \"name\": \"PS\"\n      },\n      {\n        \"id\": \"17\",\n        \"username\": \"k_shehadeh\",\n        \"profile_image_url\": \"https://unavatar.io/x/k_shehadeh\",\n        \"name\": \"Karim Shehadeh\"\n      },\n      {\n        \"id\": \"18\",\n        \"username\": \"cramforce\",\n        \"profile_image_url\": \"https://unavatar.io/x/cramforce\",\n        \"name\": \"Malte Ubl\"\n      },\n      {\n        \"id\": \"1\",\n        \"username\": \"sqs\",\n        \"profile_image_url\": \"https://unavatar.io/x/sqs\",\n        \"name\": \"Quinn Slack\"\n      },\n      {\n        \"id\": \"2\",\n        \"username\": \"jokull\",\n        \"profile_image_url\": \"https://unavatar.io/x/jokull\",\n        \"name\": \"Jökull Solberg\"\n      },\n      {\n        \"id\": \"3\",\n        \"username\": \"Hicksyfern\",\n        \"profile_image_url\": \"https://unavatar.io/x/Hicksyfern\",\n        \"name\": \"Tom Hicks\"\n      },\n      {\n        \"id\": \"4\",\n        \"username\": \"daviduzumeri.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:6ykajndqngy2kxozo37mpsgc/bafkreif2xu6bini3tpv2hfauw53ng43zbefgqol36yt4baehcbdfxahihu@jpeg\",\n        \"name\": \"Old Man Uzi\"\n      },\n      {\n        \"id\": \"5\",\n        \"username\": \"gary__tyr\",\n        \"profile_image_url\": \"https://unavatar.io/x/gary__tyr\",\n        \"name\": \"Gary Tyr\"\n      },\n      {\n        \"id\": \"6\",\n        \"username\": \"KevinVanCott\",\n        \"profile_image_url\": \"https://unavatar.io/x/KevinVanCott\",\n        \"name\": \"Kevin Thomas Van Cott\"\n      },\n      {\n        \"id\": \"7\",\n        \"username\": \"joshuakgoldberg.com\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:hwtki3j7oghodc7h6gqnrtro/bafkreicvkrpjmc7yoviwf5vhkecgcgyn23x24ix4aqdwiikcl226c64k2q@jpeg\",\n        \"name\": \"Josh Goldberg 💖\"\n      },\n      {\n        \"id\": \"8\",\n        \"username\": \"beaussan.io\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:opw3iapscc55nlgrx6q2yjah/bafkreiaj72657msogojjdk4wr76fe3umimydon3pzzrquuj7opcftntrqa@jpeg\",\n        \"name\": \"Nicolas Beaussart\"\n      },\n      {\n        \"id\": \"9\",\n        \"username\": \"MidnightDesign\",\n        \"name\": \"Rudolph Gottesheim\",\n        \"profile_image_url\": \"https://avatars.githubusercontent.com/u/743172?v=4\"\n      },\n      {\n        \"id\": \"10\",\n        \"username\": \"stephaneledorze\",\n        \"name\": \"stephane le dorze\",\n        \"profile_image_url\": \"https://unavatar.io/x/stephaneledorze\"\n      },\n      {\n        \"id\": \"22918124\",\n        \"username\": \"gregberge_\",\n        \"profile_image_url\": \"https://unavatar.io/x/gregberge_\",\n        \"name\": \"Greg Bergé\"\n      },\n      {\n        \"id\": \"19268321\",\n        \"username\": \"housecor\",\n        \"profile_image_url\": \"https://unavatar.io/x/housecor\",\n        \"name\": \"Cory House\"\n      },\n      {\n        \"id\": \"3126044440\",\n        \"username\": \"pkgacek\",\n        \"profile_image_url\": \"https://unavatar.io/x/pkgacek\",\n        \"name\": \"Piotr Gacek 🐟\"\n      },\n      {\n        \"id\": \"95668959\",\n        \"username\": \"kuizinas\",\n        \"profile_image_url\": \"https://unavatar.io/x/kuizinas\",\n        \"name\": \"Gajus\"\n      },\n      {\n        \"id\": \"1632752318994153472\",\n        \"username\": \"imabhiprasad\",\n        \"profile_image_url\": \"https://unavatar.io/x/imabhiprasad\",\n        \"name\": \"Abhijeet Prasad\"\n      },\n      {\n        \"id\": \"1513218780167655427\",\n        \"username\": \"fernandoeeu_dev\",\n        \"profile_image_url\": \"https://unavatar.io/x/fernandoeeu_dev\",\n        \"name\": \"Fernando\"\n      },\n      {\n        \"id\": \"44217212\",\n        \"username\": \"TkDodo\",\n        \"profile_image_url\": \"https://unavatar.io/x/TkDodo\",\n        \"name\": \"Dominik 🔮\"\n      },\n      {\n        \"id\": \"481186762\",\n        \"username\": \"Mokkapps\",\n        \"profile_image_url\": \"https://unavatar.io/x/Mokkapps\",\n        \"name\": \"Michael Hoffmann\"\n      },\n      {\n        \"id\": \"416394303\",\n        \"username\": \"nicoespeon\",\n        \"profile_image_url\": \"https://unavatar.io/x/nicoespeon\",\n        \"name\": \"Nicolas Carlo\"\n      },\n      {\n        \"id\": \"15736190\",\n        \"username\": \"smashingmag\",\n        \"profile_image_url\": \"https://unavatar.io/x/smashingmag\",\n        \"name\": \"Smashing Magazine 🇺🇦 🏳️‍🌈\"\n      },\n      {\n        \"id\": \"21046936\",\n        \"username\": \"danvdk\",\n        \"profile_image_url\": \"https://unavatar.io/x/danvdk\",\n        \"name\": \"Dan Vanderkam\"\n      },\n      {\n        \"id\": \"380616577\",\n        \"username\": \"stefanjudis\",\n        \"profile_image_url\": \"https://unavatar.io/x/stefanjudis\",\n        \"name\": \"Stefan Judis\"\n      },\n      {\n        \"id\": \"827145937030148097\",\n        \"username\": \"BKailaash\",\n        \"profile_image_url\": \"https://unavatar.io/x/BKailaash\",\n        \"name\": \"Kailaash\"\n      },\n      {\n        \"id\": \"18191376\",\n        \"username\": \"waldekm\",\n        \"profile_image_url\": \"https://unavatar.io/x/waldekm\",\n        \"name\": \"Waldek Mastykarz\"\n      }\n    ]\n  }\n}\n","packages/docs/src/content/docs/explanations/comparison-and-migration.md":"---\ntitle: Comparison & Migration\ndescription: How Knip compares to depcheck, unimported, ts-prune, ts-unused-exports and tsr, and how to migrate from them.\n---\n\nFirst of all, Knip owes a lot to the projects on this page and they've all been\ninspirational in their own way. For best results, Knip has [a vision embracing\ncomprehensiveness][1] which is larger in scope than any of the alternatives. So\nif any of those tools has the right scope for your requirements, then by all\nmeans, use what suits you best. Note that most projects are no longer\nmaintained.\n\nAll tools have in common that they have less features and don't support the\nconcept of [monorepos/workspaces][2]. Feel free to send in projects that Knip\ndoes not handle better, Knip loves to be challenged!\n\n## Migration\n\nA migration consists of deleting the dependency and its configuration file and\n[getting started with Knip][3]. You should end up with less configuration.\n\n## Comparison\n\n### depcheck\n\n> [Depcheck][4] is a tool for analyzing the dependencies in a project to see:\n> how each dependency is used, which dependencies are useless, and which\n> dependencies are missing from package.json.\n\nThe project has plugins (specials), yet not as many as Knip has and they're not\nas advanced. It also supports compilers (parsers) for non-standard files.\n\nThe following commands are similar:\n\n```sh\ndepcheck\nknip --dependencies\n```\n\n**Project status**: The project is archived and recommends Knip.\n\n### unimported\n\n> Find and fix dangling files and unused dependencies in your JavaScript\n> projects.\n\n[unimported][5] is fast and works well. It works in what Knip calls \"production\nmode\" exclusively. If you're fine with a little bit of configuration and don't\nwant or need to deal with non-production items (such as `devDependencies` and\ntest files), then this might work well for you.\n\nThe following commands are similar:\n\n```sh\nunimported\nknip --production --dependencies --files\n```\n\n**Project status**: The project is archived and recommends Knip.\n\n### ts-prune\n\n> Find unused exports in a typescript project. 🛀\n\n[ts-prune][6] aims to find potentially unused exports in your TypeScript project\nwith zero configuration.\n\nThe following commands are similar:\n\n```sh\nts-prune\nknip --include exports,types,nsExports,nsTypes\n```\n\nUse `knip --exports` to also include enum and namespace members.\n\n**Project status**: The project is archived and recommends Knip.\n\n### ts-unused-exports\n\n> [ts-unused-exports][7] finds unused exported symbols in your Typescript\n> project\n\nThe following commands are similar:\n\n```sh\nts-unused-exports\nknip --include exports,types,nsExports,nsTypes\n```\n\nUse `knip --exports` to also include enum and namespace members.\n\n### tsr\n\n> Remove unused code from your TypeScript Project\n\n[tsr][8] (previously `ts-remove-unused`) removes unused exports, and works based\non a single `tsconfig.json` file (`includes` and `excludes`) and requires no\nconfiguration. It removes the `export` keyword or the whole export declaration.\n\n**Project status**: The project is archived and recommends Knip.\n\n## Related projects\n\nAdditional alternative and related projects include:\n\n- [deadfile][9]\n- [DepClean][10]\n- [dependency-check][11]\n- [find-unused-exports][12]\n- [next-unused][13]\n- [npm-check][14]\n- [renoma][15]\n\nIn general, the [e18e.dev][16] website and in particular the [Cleanup][17]\nsection is a great resource when dealing with technical debt.\n\n[1]: ./why-use-knip.md#comprehensive\n[2]: ../features/monorepos-and-workspaces.md\n[3]: ../overview/getting-started.mdx\n[4]: https://github.com/depcheck/depcheck\n[5]: https://github.com/smeijer/unimported\n[6]: https://github.com/nadeesha/ts-prune\n[7]: https://github.com/pzavolinsky/ts-unused-exports\n[8]: https://github.com/line/tsr\n[9]: https://github.com/M-Izadmehr/deadfile\n[10]: https://github.com/mysteryven/depclean\n[11]: https://github.com/dependency-check-team/dependency-check\n[12]: https://github.com/jaydenseric/find-unused-exports\n[13]: https://github.com/pacocoursey/next-unused\n[14]: https://github.com/dylang/npm-check\n[15]: https://github.com/bluwy/renoma\n[16]: https://e18e.dev\n[17]: https://e18e.dev/guide/cleanup.html\n","packages/docs/src/content/docs/explanations/entry-files.md":"---\ntitle: Entry Files\ndescription: What entry files are and how Knip and its plugins find them automatically from defaults, `package.json`, plugins and dynamic imports.\n---\n\nEntry files are the starting point for Knip to determine what files are used in\nthe codebase. More entry files lead to increased coverage of the codebase. This\nalso leads to more dependencies to be discovered. This page explains how Knip\nand its plugins try to find entry files so you don't need to configure them\nyourself.\n\n## Default entry file patterns\n\nFor brevity, the [default configuration][1] on the previous page mentions only\n`index.js` and `index.ts`, but the default set of file names and extensions is\nactually a bit larger:\n\n- `index`, `main` and `cli`\n- `js`, `mjs`, `cjs`, `jsx`, `ts`, `mts`, `cts` and `tsx`\n\nThis means files like `main.cjs` and `src/cli.ts` are automatically added as\nentry files. Here's the default configuration in full:\n\n```json\n{\n  \"entry\": [\n    \"{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\",\n    \"src/{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\"\n  ],\n  \"project\": [\"**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}!\"]\n}\n```\n\nNext to the default locations, Knip looks for `entry` files in other places. In\na monorepo, this is done for each workspace separately.\n\nThe values you set override the default values, they are not merged.\n\n## Plugins\n\nPlugins often add entry files. For instance, the Remix, Storybook and Vitest\nplugins add additional entry files. See [the next page about plugins][2] for\nmore details about this.\n\n## Scripts in package.json\n\nThe `package.json` is scanned for entry files. The `main`, `bin`, and `exports`\nfields may contain entry files. The `scripts` are also parsed to find entry\nfiles and dependencies. See [Script Parser][3] for more details.\n\n## Ignored files\n\nKnip respects `.gitignore` files. By default, ignored files are not added as\nentry files. This behavior can be disabled by using the [`--no-gitignore`][4]\nflag on the CLI.\n\n## Configuring project files\n\nSee [configuring project files][5] for guidance on tuning `entry` and `project`\nand when to use `ignore`.\n\n## Where Knip looks for entry files\n\nPutting it together, Knip discovers entry files from:\n\n- Default locations such as `index.js` and `src/index.ts`\n- The `main`, `bin` and `exports` fields in `package.json`\n- Entry and config files added by enabled plugins (the config files are entry\n  files too)\n- Dynamic imports: `require()` and `import()`\n- `require.resolve()` and `import.meta.resolve()`\n- `new URL('./file.js', import.meta.url)`\n- `new Worker(…)` and `child_process` `fork`/`spawn`/`execFile` when the target\n  is `path.join(__dirname, …)`\n- `module.register('./loader.js')` loader registration\n- Scripts the [script parser][3] extracts: `package.json` scripts, CI workflow\n  `run` commands, and source-code calls (tagged `$` templates,\n  `node:child_process`, `execa`, `nano-spawn`)\n\nEntry files are added to the module graph, and module resolution may pull in\nfurther entry files recursively until none remain.\n\n[1]: ../overview/configuration.md#defaults\n[2]: ./plugins.md\n[3]: ../features/script-parser.md\n[4]: ../reference/cli.md#--no-gitignore\n[5]: ../guides/configuring-project-files.md\n","packages/docs/src/content/docs/explanations/how-knip-works.md":"---\ntitle: How Knip works\ndescription: The mental model behind Knip. How entry files, the module graph and reachability decide what counts as unused, and why surprising results trace back to them.\n---\n\nKnip finds and removes unused code and dependencies. It starts at your entry\nfiles, follows every import to the files they reach, and builds a graph of\neverything connected. Anything left out is reported as unused: a file no entry\nreaches, an export no file imports, a dependency no file uses.\n\nThis page explains how Knip produces its results.\n\n## Build and analyze\n\nKnip runs in two phases.\n\nThe build phase starts from the entry files. Knip reads a file, parses it,\ncollects its imports and exports, resolves each import to another file, and\nrepeats for every newly reached file. The result is a graph of the project:\nevery reachable file, what it imports, and what imports it.\n\nResolution is broad by design. Knip follows custom path aliases and extensions,\nreads references out of config files and [shell scripts][1], and \"[compiles][2]\"\nnon-standard files like `.vue` and `.svelte` so their imports are in the graph\ntoo.\n\nThe analysis phase queries that graph. It never re-parses anything. It walks the\nedges already recorded:\n\n- a **file** is unused when no entry reaches it\n- an **export** is unused when no other file imports it\n- a **dependency** is unused when no file imports it (and _unlisted_ when a file\n  imports it but `package.json` doesn't list it)\n\nAnalysis happens by quering the graph. Your results are only as accurate as the\ngraph is complete. And the graph depends on your entry files.\n\n## Entry files decide what Knip can see\n\nThe graph contains only what's reachable from an entry file. Miss one entry, and\neverything reachable _only_ from it looks unused.\n\nIdeally you don't need to list entries by hand. Knip starts from sensible\n[defaults][3] like `src/index.ts`, and [plugins][4] automatically add the entry\npoints specific to your frameworks and libraries. The Vitest plugin adds your\ntest files, the Astro plugin adds your pages, and so on. This is why plugins are\nimportant: each one tells Knip about a whole class of files it might otherwise\nnever reach.\n\n## Findings come in chains\n\nUnused results cascade. They don't appear in isolation. Say a tool generates an\nentry file Knip doesn't know about:\n\n- that file looks unused, because nothing reaches it\n- every file it imports looks unused too, because nothing else reaches them\n- every export in those files looks unused\n- every dependency only those files used looks unused\n\nOne unreached entry can turn into dozens of findings. The chain also runs in\nreverse: add the entry, and the whole cascade collapses at once.\n\nSo read the output from the root down: **unused files first, then exports, then\ndependencies.** A single unused file usually explains a long list of results\nbelow it. Fix causes at the root and the rest disappears.\n\nSome chains only show up one run at a time. An export counts as used when\nanother file imports it, even if the importing code is unused. Remove that code,\nand the next run may report the export. Unused exports that import each other\nacross files are never reported.\n\n## A surprising result might be a gap, not a bug\n\nWhen Knip flags something you're sure is used, it's based on the graph: it\ncouldn't reach that code from an entry. The cause is usually one of:\n\n- a missing entry for a tool or convention Knip doesn't know yet\n- a dynamic import Knip can't follow statically, or a path it can't resolve\n- a transitive dependency of a package that resolves only because something else\n  installs it\n\nIn each case the fix is to teach Knip: add the entry, configure the plugin, list\nthe dependency. Don't hide the result. [Configuring project files][5] and\n[resolving reported issues][6] cover how, issue type by issue type.\n\n[1]: ../features/script-parser.md\n[2]: ../features/compilers.md\n[3]: ./entry-files.md\n[4]: ./plugins.md\n[5]: ../guides/configuring-project-files.md\n[6]: ../guides/handling-issues.mdx\n","packages/docs/src/content/docs/explanations/plugins.md":"---\ntitle: Plugins\ndescription: How Knip plugins work and the difference between `config` files (parsed for dependencies) and `entry` files (added to the module graph).\n---\n\nThis page describes why Knip uses plugins and the difference between `config`\nand `entry` files.\n\nKnip has an extensive and growing [list of built-in plugins][1]. Feel free to\n[write a plugin][2] so others can benefit too!\n\n## What does a plugin do?\n\nPlugins are enabled if the related package is listed in the list of dependencies\nin `package.json`. For instance, if `astro` is listed in `dependencies` or\n`devDependencies`, then the Astro plugin is enabled. And this means that this\nplugin will:\n\n- Handle [configuration files][3] like `astro.config.mjs`\n- Add [entry files][4] such as `src/pages/**/*.astro`\n- Define [command-line arguments][5]\n\n## Configuration files\n\nKnip uses [entry files][6] as starting points to scan your source code and\nresolve other internal files and external dependencies. The module graph can be\nstatically resolved through the `require` and `import` statements in those\nsource files. However, configuration files reference external dependencies in\nvarious ways. Knip uses a plugin for each tool to parse configuration files and\nfind those dependencies.\n\n### Example: ESLint\n\nIn the first example we look at [the ESLint plugin][7]. The default `config`\nfile patterns include `.eslintrc.json`. Here's a minimal example:\n\n```json title=\".eslintrc.json\"\n{\n  \"extends\": [\"airbnb\", \"prettier\"],\n  \"plugins\": [\"@typescript-eslint\"]\n}\n```\n\nConfiguration files like this don't `import` or `require` anything, but they do\nrequire the referenced dependencies to be installed.\n\nIn this case, the plugin will return three dependencies:\n\n- `eslint-config-airbnb`\n- `eslint-config-prettier`\n- `@typescript-eslint/eslint-plugin`\n\nKnip will then look for missing dependencies in `package.json` and report those\nas unlisted. And vice versa, if there are any ESLint plugins listed in\n`package.json`, but unused, those will be reported as well.\n\n### Example: Vitest\n\nThe second example uses [the Vitest plugin][8]. Here's a minimal example of a\nVitest configuration file:\n\n```ts title=\"vitest.config.ts\"\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    coverage: {\n      provider: 'istanbul',\n    },\n    environment: 'happy-dom',\n  },\n});\n```\n\nThe Vitest plugin reads this configuration and returns two dependencies:\n\n- `@vitest/coverage-istanbul`\n- `vitest-environment-happy-dom`\n\nKnip will look for missing and unused dependencies in `package.json` and report\naccordingly.\n\nSome tools allow configuration to be stored in `package.json`, that's why some\nplugins contain `package.json` in the list of `config` files.\n\n:::tip[Summary]\n\nPlugins load configuration files to find referenced dependencies, and determine\nunused and unlisted dependencies.\n\n:::\n\n## Entry files\n\nMany plugins have default `entry` files configured. When the plugin is enabled,\nKnip will add entry files as configured by the plugin to resolve used files and\ndependencies.\n\nFor example, if `next` is listed as a dependency in `package.json`, the Next.js\nplugin will automatically add multiple patterns as entry files, such as\n`pages/**/*.{js,jsx,ts,tsx}`. If `vitest` is listed, the Vitest plugin adds\n`**/*.{test,test-d,spec,spec-d}.ts` as entry file patterns. Most plugins have\nentry files configured, so you don't have to.\n\nIt's mostly plugins for meta frameworks and test runners that have `entry` files\nconfigured.\n\n:::tip[Plugins result in less configuration]\n\nPlugins use entry file patterns as defined in your configuration file of these\ntools. So you don't need to repeat this in your Knip configuration.\n\n:::\n\nFor example, let's say your Playwright configuration contains the following:\n\n```ts title=\"playwright.config.ts\"\nimport type { PlaywrightTestConfig } from '@playwright/test';\n\nconst config: PlaywrightTestConfig = {\n  testDir: 'integration',\n  testMatch: ['**/*-test.ts'],\n};\n\nexport default config;\n```\n\nThe Playwright plugin will read this configuration file and return those entry\npatterns (`integration/**/*-test.ts`). Knip will then not use the default entry\npatterns.\n\nYou can still override this behavior in your Knip configuration:\n\n```json title=\"knip.json\"\n{\n  \"playwright\": {\n    \"entry\": \"src/**/*.integration.ts\"\n  }\n}\n```\n\nThis should not be necessary though. Please consider opening a pull request or a\nbug report if any plugin is not behaving as expected.\n\n:::tip[Summary]\n\nPlugins try hard to automatically add the correct entry files.\n\n:::\n\n## Entry files from config files\n\nEntry files are part of plugin configuration (as described in the previous\nsection). Yet plugins can also return additional entry files after parsing\nconfiguration files. Below are some examples of configuration files parsed by\nplugins to return additional entry files. The goal of these examples is to give\nyou an idea about the various ways Knip and its plugins try to find entry files\nso you don't need to configure them yourself.\n\n### Angular\n\nThe Angular plugin parses the Angular configuration file. Here's a fragment:\n\n```json title=\"angular.json\"\n{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"projects\": {\n    \"knip-angular-example\": {\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit/build-angular:browser\",\n          \"options\": {\n            \"outputPath\": \"dist/knip-angular-example\",\n            \"main\": \"src/main.ts\",\n            \"tsConfig\": \"tsconfig.app.json\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nThis will result in `src/main.ts` being added as an entry file (and\n`@angular-devkit/build-angular` as a referenced dependency).\n\nAdditionally, the Angular plugin returns `tsconfig.app.json` as a configuration\nfile for the TypeScript plugin.\n\n### GitHub Actions\n\nThis plugin parses workflow YAML files. This fragment contains three `run`\nscripts:\n\n```yml title=\".github/workflows/deploy.yml\"\njobs:\n  integration:\n    runs-on: ubuntu-latest\n    steps:\n      - run: npm install\n      - run: node scripts/build.js\n      - run: node --loader tsx scripts/deploy.ts\n      - run: playwright test -c playwright.web.config.ts\n        working-directory: e2e\n```\n\nFrom these scripts, the `scripts/build.js` and `scripts/deploy.ts` files will be\nadded as entry files by the GitHub Actions plugin.\n\nAdditionally, the file `e2e/playwright.web.config.ts` is detected and will be\nhanded over as a Playwright configuration file.\n\nRead more about this in [command-line arguments][5].\n\n### webpack\n\nLet's take a look at this example webpack configuration file:\n\n```js title=\"webpack.config.js\"\nmodule.exports = env => {\n  return {\n    entry: {\n      main: './src/app.ts',\n      vendor: './src/vendor.ts',\n    },\n    module: {\n      rules: [\n        {\n          test: /\\.(woff|ttf|ico|woff2|jpg|jpeg|png|webp)$/i,\n          use: 'base64-inline-loader',\n        },\n      ],\n    },\n  };\n};\n```\n\nThe webpack plugin will parse this and add `./src/app.ts` and `./src/vendor.ts`\nas entry files. It will also add `base64-inline-loader` as a referenced\ndependency.\n\n:::tip[Summary]\n\nIn your config files, plugins can find additional entry files and also other\nconfig files recursively.\n\n:::\n\n## Bringing it all together\n\nSometimes a configuration file is a JavaScript or TypeScript file that imports\ndependencies, but also contains configuration that needs to be parsed by a\nplugin to find additional dependencies.\n\nLet's take a look at this example Vite configuration file:\n\n```ts title=\"vite.config.ts\"\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig(async ({ mode, command }) => {\n  return {\n    plugins: [react()],\n    test: {\n      setupFiles: ['./setup-tests.ts'],\n      environment: 'happy-dom',\n      coverage: {\n        provider: 'c8',\n      },\n    },\n  };\n});\n```\n\nThis file imports `vite` and `@vitejs/plugin-react` directly, but also\nindirectly references the `happy-dom` and `@vitest/coverage-c8` packages.\n\nThe Vite plugin of Knip will **dynamically** load this configuration file and\nparse the exported configuration. But it's not aware of the `vite` and\n`@vitejs/plugin-react` imports. This is why such `config` files are also\nautomatically added as `entry` files for Knip to **statically** resolve the\n`import` and `require` statements.\n\nAdditionally, `./setup-tests.ts` will be added as an `entry` file.\n\n:::note\n\nWhen plugins dynamically load configuration files, conditional dependencies may\nnot be detected if the condition evaluates differently during analysis. See\n[conditional or dynamic dependencies][9] for details and workarounds.\n\n:::\n\n## Command-Line Arguments\n\nPlugins may define the arguments where Knip should look for entry files,\nconfiguration files and dependencies. We've already seen some examples above:\n\n```sh\nnode --loader tsx scripts/deploy.ts\nplaywright test -c playwright.web.config.ts\n```\n\nPlease see [script parser][10] for more details.\n\n## Config File Location\n\nIf configuration files aren't in their default location and they are not\nreferenced through some script like `vite -c ./dir/vite.config.ts`, then make\nsure to tell Knip about it. Two examples:\n\n```json title=\"knip.jsonc\"\n{\n  \"playwright\": { \"config\": [\"e2e/playwright.config.ts\"] },\n  \"vite\": \"packages/*/vite.config.ts\" // shorthand without `config` and array notation\n}\n```\n\nThis is common in projects where a directory like `packages/lib` is not an\nactual workspace with a `package.json` file. Also see [integrated monorepos][11]\nfor similar cases.\n\n## Summary\n\n:::tip[Summary]\n\nPlugins are configured with two distinct types of files:\n\n- `config` files are dynamically loaded and parsed by the plugin\n- `entry` files are added to the module graph\n- Both can recursively lead to additional entry files, config files and\n  dependencies\n\n:::\n\n[1]: ../reference/plugins.md\n[2]: ../writing-a-plugin/index.md\n[3]: #configuration-files\n[4]: #entry-files\n[5]: #command-line-arguments\n[6]: ./entry-files.md\n[7]: ../reference/plugins/eslint.md\n[8]: ../reference/plugins/vitest.md\n[9]: ../guides/handling-issues.mdx#conditional-or-dynamic-dependencies\n[10]: ../features/script-parser.md\n[11]: ../features/integrated-monorepos.md\n","packages/docs/src/content/docs/explanations/why-use-knip.md":"---\ntitle: Why use Knip?\ndescription: Why remove unused files, exports and dependencies, and how Knip finds them comprehensively across greenfield and legacy (mono)repos.\n---\n\nThe value of removing clutter is clear, but finding it manually is tedious. Meet\nKnip: comprehensive and accurate results at any scale.\n\n:::tip[TL;DR]\n\nUnused files, exports and dependencies pile up as projects grow. Removing them\nimproves maintenance, performance, security and onboarding, and prevents\nregressions in CI. Knip automates finding (and fixing) all three,\ncomprehensively and at any scale.\n\n:::\n\n## Less is more\n\nThere are plenty of reasons to delete unused files, dependencies and \"dead\ncode\":\n\n- Easier maintenance: things are easier to manage when there's less of it.\n- Improved performance: startup time, build time and/or bundle size can be\n  negatively impacted when unused code, files and/or dependencies are included.\n  Relying on tree-shaking when bundling code helps, but it's not a silver\n  bullet.\n- Increased security: less code and dependencies means less room for weak spots.\n- Easier onboarding: there should be no doubts about whether files, dependencies\n  and exports are actually in use or not. Especially for people new to the\n  project and/or taking over responsibilities this is harder to grasp.\n- Prevent regressions: tools like TypeScript, ESLint and Prettier do all sorts\n  of checks and linting to report violations and prevent regressions. Knip does\n  the same for dependencies, exports and files that are obsolete.\n- Keeping dead code around has a negative value on readability, as it can be\n  misleading and distracting. Even if it serves no purpose it will need to be\n  maintained (source: [Safe dead code removal → YAGNI][1]).\n- Also see [Why are unused dependencies a problem?][2] and [Why are unused\n  exports a problem?][3].\n\n## Automation\n\nCode and dependency management is usually not the most exciting task for most of\nus. Knip's mission is to automate finding clutter. This is such a tedious job if\nyou were to do it manually, and where would you even start? Knip applies many\ntechniques and heuristics to report what you need and save a lot of time.\n\n:::tip\n\nKnip not only finds clutter, it can also [remove clutter][4]!\n\nUse Knip next to a linter like ESLint or Biome: after removing unused variables\ninside files, Knip might find even more unused code. Rinse and repeat!\n\n:::\n\n## Comprehensive\n\nYou can use alternative tools that do the same. However, the advantage of a\nstrategy that addresses all of dependencies, exports and files is in their\nsynergy:\n\n- Utilizing plugins to find their dependencies includes the capacity to find\n  additional entry and configuration files. This results in more resolved and\n  used files. Better coverage gives better insights into unused files and\n  exports.\n- Analyzing more files reveals more unused exports and dependency usage,\n  refining the list of both unused and unlisted dependencies.\n- This approach is amplified in a [monorepo setting][5]. In fact, files and\n  internal dependencies can recursively reference each other (across\n  workspaces).\n\nKnip reaches this coverage through [fine-grained entry points][6], [custom\nmodule resolution][7], [configuration-file parsers][8], an [advanced\nshell-script parser][9], and [built-in and custom compilers][10], then [fixes\nmost of it automatically][4].\n\n## Greenfield or Legacy\n\nInstalling Knip in greenfield projects ensures the project stays neat and tidy\nfrom the start. Add it to your CI workflow and prevent any regressions from\nentering the codebase.\n\n:::tip\n\nUse Knip in a CI environment to prevent future regressions.\n\n:::\n\nIn large and/or legacy projects, Knip may report false positives and require\nsome configuration. It aims to be a great assistant when cleaning up parts of\nthe project or doing large refactors. Even a list of results with a few false\npositives is many times better and faster than if you were to do it manually.\n\n## Unobtrusive\n\nKnip does not introduce new syntax for you to learn. This may sound obvious, but\nconsider comments like the following:\n\n```js\n// eslint-disable-next-line\n// prettier-ignore\n// @ts-expect-error\n```\n\nKnip doesn't have similar comments like `// knip-ignore` so you can get rid of\nfalse positives for a variety of reasons:\n\n1. A false positive may be a bug in Knip, and should be reported, not dismissed.\n2. Instead of proprietary comments, use [standardized annotations][11] that also\n   serve as documentation.\n3. In the event you want to remove Knip, just uninstall `knip` without having to\n   remove useless comments scattered throughout the codebase.\n\nTip: use `@lintignore` in JSDoc comments, so other linters can use the same.\n\n[1]: https://jfmengels.net/safe-dead-code-removal/#yagni-you-arent-gonna-need-it\n[2]: ../typescript/unused-dependencies.md#why-are-unused-dependencies-a-problem\n[3]: ../typescript/unused-exports.md#why-are-unused-exports-a-problem\n[4]: ../features/auto-fix.mdx\n[5]: ../features/monorepos-and-workspaces.md\n[6]: ./entry-files.md\n[7]: ../reference/faq.md#why-doesnt-knip-use-an-existing-module-resolver\n[8]: ./plugins.md#configuration-files\n[9]: ../features/script-parser.md\n[10]: ../features/compilers.md\n[11]: ../reference/jsdoc-tsdoc-tags.md\n","packages/docs/src/content/docs/features/catalogs.md":"---\ntitle: Catalogs\ndescription: How Knip finds unused pnpm, Yarn and Bun catalog entries referenced through the `catalog:` protocol, and removes them with auto-fix.\n---\n\nCatalogs let you define dependency version ranges once and reference them across\nworkspaces in a monorepo. Knip reports catalog entries that are defined but no\nlonger referenced, and references to entries that do not exist. It can remove\nunused entries with [auto-fix][1].\n\n## Supported catalogs\n\nKnip reads catalogs from the first applicable location:\n\n- `pnpm-workspace.yaml` — the `catalog` (default) and `catalogs` (named) keys\n- `.yarnrc.yml` — the `catalog` and `catalogs` keys\n- `package.json` — the `catalog` and `catalogs` keys\n- `package.json#workspaces` — the `catalog` and `catalogs` keys (Bun)\n\n## Unused catalog entries\n\nA catalog entry is reported as unused when no workspace references it through\nthe `catalog:` protocol in its `package.json`:\n\n```json title=\"packages/app/package.json\"\n{\n  \"dependencies\": {\n    \"react\": \"catalog:\",\n    \"zod\": \"catalog:validation\"\n  }\n}\n```\n\n`catalog:` references the `default` catalog, while `catalog:validation`\nreferences the named `validation` catalog. References are resolved from\n`dependencies`, `devDependencies`, `peerDependencies`, `optionalDependencies`,\n`resolutions`, `pnpm-workspace.yaml#overrides`, and `pnpm.overrides` in the root\n`package.json` (pnpm 10 and older).\n\nEntries defined in a catalog but not referenced anywhere are reported as [unused\ncatalog entries][2].\n\n## Unresolved catalog references\n\nA `catalog:` reference is reported when the selected catalog does not define\nthat package. These issues point to the consuming `package.json` or\n`pnpm-workspace.yaml`, where package managers would otherwise fail to resolve\nthe version.\n\n## Filter and fix\n\nThe `catalog` and `catalogReferences` issue types are included by the\n[`--dependencies`][3] shortcut. Focus on them (or exclude them) like any other\nissue type:\n\n```sh\nknip --include catalog,catalogReferences\nknip --exclude catalog,catalogReferences\n```\n\n[Auto-fix][1] removes unused catalog entries from the catalog file:\n\n```sh\nknip --fix --fix-type catalog\n```\n\n[1]: ./auto-fix.mdx#catalog-entries\n[2]: ../reference/issue-types.md\n[3]: ./rules-and-filters.md#shorthands\n","packages/docs/src/content/docs/features/compilers.md":"---\ntitle: Compilers\ndescription: Built-in and custom compilers let Knip analyze non-standard files like `.astro`, `.mdx`, `.svelte` and `.vue` for imports and exports.\n---\n\nProjects may have source files that are not JavaScript or TypeScript, and thus\nrequire compilation (or transpilation, or pre-processing, you name it). Files\nlike `.mdx`, `.astro`, `.vue` and `.svelte` may also import other source files\nand external dependencies. So ideally, these files are included when linting the\nproject. That's why Knip supports compilers.\n\n## Built-in compilers\n\nKnip has built-in \"compilers\" for the following file extensions:\n\n- `.astro`\n- `.css` (only enabled by `tailwindcss`)\n- `.mdx`\n- `.prisma`\n- `.sass` + `.scss`\n- `.less`\n- `.styl` + `.stylus`\n- `.svelte`\n- `.tsrx`\n- `.vue`\n\nKnip does not include real compilers for those files, but regular expressions to\ncollect `import` statements. This is fast, requires no dependencies, and enough\nfor Knip to build the module graph. The tradeoff is that unused exports inside\nthese files go unreported.\n\nReal compilers recover those exports, but bring their own challenges. The Svelte\ncompiler, for instance, keeps `exports` intact even when they represent\ncomponent properties, so Knip reports them as unused. When you need that\nfidelity, override any built-in with the framework's own compiler (see the\n[Svelte][1] and [Vue][2] examples below). For example, to report unused exports\nin [`.tsrx`][3] files.\n\nCompilers are enabled only when a related dependency is found. The `.tsrx`\ncompiler when a `@tsrx/*` package is installed, for example. If that detection\ndoesn't work for your project, set `true` to enable any compiler manually:\n\n```ts title=\"knip.ts\"\nexport default {\n  compilers: {\n    mdx: true,\n  },\n};\n```\n\n## Compiled files and `project` patterns\n\nThe default `project` patterns include compiler extensions automatically. When\nyou override `project`, list them explicitly:\n\n```ts title=\"knip.ts\"\nexport default {\n  project: ['src/**/*.{ts,tsx,css}'],\n};\n```\n\nFiles outside `project` are not analyzed, so their imports don't count. A\nnarrowed pattern like `['src/**/*.{ts,tsx}']` silently drops everything a\nstylesheet imports, which is a common source of false positives: `@import\n'tailwindcss'` in an excluded `.css` file gets `tailwindcss` reported as an\nunused dependency. Knip reports a configuration hint when a compiled extension\nis excluded this way.\n\n## Custom compilers\n\nBuilt-in compilers can be overridden, and additional compilers can be added.\nSince compilers are functions, the Knip configuration file must be a dynamic\n`.js` or `.ts` file.\n\n### Interface\n\nThe compiler function interface is straightforward. Text in, text out:\n\n```ts\n(source: string, filename: string) => string | PromiseLike<string>;\n```\n\nReturn a string or a Promise-like value that resolves to a string. Knip compiles\nfiles on demand and awaits asynchronous results; the `async` keyword is\noptional.\n\n### Examples\n\n- [CSS][4]\n- [MDX][5]\n- [Svelte][1]\n- [Vue][2]\n\n#### CSS\n\nHere's an example, minimal compiler for CSS files:\n\n```ts title=\"knip.ts\"\nexport default {\n  compilers: {\n    css: (text: string) => [...text.matchAll(/(?<=@)import[^;]+/g)].join('\\n'),\n  },\n};\n```\n\nYou may wonder why the CSS compiler is not included by default. It's currently\nnot clear if it should be included. And if so, what would be the best way to\ndetermine it should be enabled, and what syntax(es) it should support. Note that\nTailwind CSS, SASS/SCSS, Less and Stylus compilers are included.\n\n#### MDX\n\nAnother example, in case the built-in MDX compiler is not enough:\n\n```ts\nimport { compile } from '@mdx-js/mdx';\n\nexport default {\n  compilers: {\n    mdx: async text => (await compile(text)).toString(),\n  },\n};\n```\n\n#### Svelte\n\nIn a Svelte project, the compiler is automatically enabled. Override and use\nSvelte's compiler for better results if the built-in \"compiler\" is not enough:\n\n```ts\nimport type { KnipConfig } from 'knip';\nimport { compile } from 'svelte/compiler';\n\nexport default {\n  compilers: {\n    svelte: (source: string) => compile(source, {}).js.code,\n  },\n} satisfies KnipConfig;\n```\n\n#### Vue\n\nIn a Vue project, the compiler is automatically enabled. Override and use Vue's\nparser for better results if the built-in \"compiler\" is not enough:\n\n```ts\nimport type { KnipConfig } from 'knip';\nimport {\n  parse,\n  type SFCScriptBlock,\n  type SFCStyleBlock,\n} from 'vue/compiler-sfc';\n\nfunction getScriptBlockContent(block: SFCScriptBlock | null): string[] {\n  if (!block) return [];\n  if (block.src) return [`import '${block.src}'`];\n  return [block.content];\n}\n\nfunction getStyleBlockContent(block: SFCStyleBlock | null): string[] {\n  if (!block) return [];\n  if (block.src) return [`@import '${block.src}';`];\n  return [block.content];\n}\n\nfunction getStyleImports(content: string): string {\n  return [...content.matchAll(/(?<=@)import[^;]+/g)].join('\\n');\n}\n\nconst config = {\n  compilers: {\n    vue: (text: string, filename: string) => {\n      const { descriptor } = parse(text, { filename, sourceMap: false });\n      return [\n        ...getScriptBlockContent(descriptor.script),\n        ...getScriptBlockContent(descriptor.scriptSetup),\n        ...descriptor.styles.flatMap(getStyleBlockContent).map(getStyleImports),\n      ].join('\\n');\n    },\n  },\n} satisfies KnipConfig;\n\nexport default config;\n```\n\n## Tracking non-source files\n\nTo track any file extension that's not meant to compile to JavaScript, register\na no-op compiler:\n\n```ts title=\"knip.ts\"\nexport default {\n  compilers: { template: () => '' },\n};\n```\n\n[1]: #svelte\n[2]: #vue\n[3]: https://tsrx.dev\n[4]: #css\n[5]: #mdx\n","packages/docs/src/content/docs/features/custom-elements.md":"---\ntitle: Custom Elements\ndescription: How Knip credits custom element classes registered via `customElements.define()` or Lit, FAST, Stencil and Catalyst decorators.\n---\n\nCustom elements are registered under a tag name. When such a class isn't\nreferenced elsewhere, Knip would report the export as unused. Instead, Knip\nrecognizes the registration and considers the class used.\n\nNative registration needs no configuration. Framework registrations are credited\nthrough their plugin, which is enabled when the framework is a dependency.\n\n## Native registration\n\nThe web standard `customElements.define()` credits the registered class:\n\n```ts\nexport class MyCard extends HTMLElement {}\n\ncustomElements.define('my-card', MyCard);\n```\n\nThe registry can be the global `customElements` — directly, through a `window`,\n`globalThis` or `self` prefix, or a local alias — a `CustomElementRegistry`\ninstance, or a shadow root's scoped registry:\n\n```ts\nconst registry = new CustomElementRegistry();\nregistry.define('my-card', MyCard);\n```\n\nA class can also register itself from a `static` block using `this`:\n\n```ts\nexport class MyCard extends HTMLElement {\n  static {\n    customElements.define('my-card', this);\n  }\n}\n```\n\n## Framework registration\n\n| Framework     | Plugin        | Registration                    | Imported from                                            |\n| ------------- | ------------- | ------------------------------- | -------------------------------------------------------- |\n| [Lit][1]      | [lit][2]      | `@customElement('tag')`         | `lit/decorators`, `lit-element`, `@lit/reactive-element` |\n| [FAST][3]     | [fast][4]     | `@customElement` or `.define()` | `@microsoft/fast-element`                                |\n| [Stencil][5]  | [stencil][6]  | `@Component({ tag })`           | `@stencil/core`                                          |\n| [Catalyst][7] | [catalyst][8] | `@controller`                   | `@github/catalyst`                                       |\n\nThe decorator counts only when imported from the framework. A locally defined or\ndifferently-imported decorator is ignored.\n\n### Lit\n\nA `@customElement('tag')` decorator credits the class when the matching plugin\nis enabled:\n\n```ts\nimport { LitElement } from 'lit';\nimport { customElement } from 'lit/decorators.js';\n\n@customElement('my-card')\nexport class MyCard extends LitElement {}\n```\n\n### FAST\n\n[FAST][3] also registers elements through a static `define()` or `defineAsync()`\nmethod. A class extending `FASTElement`, directly or through a mixin, is\ncredited when registered this way:\n\n```ts\nimport { FASTElement } from '@microsoft/fast-element';\n\nexport class MyCard extends FASTElement {}\n\nMyCard.define('my-card');\n```\n\n### Stencil\n\nA `@Component` decorator credits the class:\n\n```ts\nimport { Component } from '@stencil/core';\n\n@Component({ tag: 'my-card' })\nexport class MyCard {}\n```\n\n### Catalyst\n\nThe bare `@controller` decorator registers the element under a tag derived from\nthe class name:\n\n```ts\nimport { controller } from '@github/catalyst';\n\n@controller\nexport class MyCardElement extends HTMLElement {}\n```\n\n[1]: https://lit.dev\n[2]: ../reference/plugins/lit.md\n[3]: https://fast.design\n[4]: ../reference/plugins/fast.md\n[5]: https://stenciljs.com\n[6]: ../reference/plugins/stencil.md\n[7]: https://catalyst.rocks\n[8]: ../reference/plugins/catalyst.md\n","packages/docs/src/content/docs/features/integrated-monorepos.md":"---\ntitle: Integrated Monorepos\ndescription: Configure Knip for repositories with a single `package.json` and many projects, like the Nx integrated monorepo style.\n---\n\nSome repositories have a single `package.json`, but consist of multiple projects\nwith configuration files across the repository. A good example is the [Nx\nintegrated monorepo style][1].\n\n:::tip\n\nAn integrated monorepo is a single workspace.\n\n:::\n\n## Entry Files\n\nThe default entrypoints files might not be enough. Here's an idea that might fit\nthis type of monorepo:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"{apps,libs}/**/src/index.{ts,tsx}\"],\n  \"project\": [\"{apps,libs}/**/src/**/*.{ts,tsx}\"]\n}\n```\n\n## Plugins\n\nLet's assume some of these projects are applications (\"apps\") which have their\nown ESLint configuration files and Cypress configuration and test files. This\nmay result in those files getting reported as unused, and consequently also the\ndependencies they import and refer to.\n\nIn that case, we could configure the ESLint and Cypress plugins like this:\n\n```json title=\"knip.json\"\n{\n  \"eslint\": {\n    \"config\": [\"{apps,libs}/**/.eslintrc.json\"]\n  },\n  \"cypress\": {\n    \"entry\": [\"apps/**/cypress.config.ts\", \"apps/**/cypress/e2e/*.spec.ts\"]\n  }\n}\n```\n\nAdapt the file patterns to your project, and the relevant `config` and `entry`\nfiles and dependencies should no longer be reported as unused.\n\n## Internal Workspace Dependencies\n\nA note about repositories with multiple `package.json` files and **internal**\nworkspace packages: it is recommended to list all dependencies in each consuming\n`package.json`, allowing Knip to do fine-grained reporting of both unused and\nunlisted dependencies.\n\nAn alternative is to `ignoreDependencies: [\"@internal/*\"]`.\n\n[1]: https://nx.dev/getting-started/tutorials/integrated-repo-tutorial\n","packages/docs/src/content/docs/features/monorepos-and-workspaces.md":"---\ntitle: Monorepos & Workspaces\ndescription: How Knip discovers and configures workspaces in package-based monorepos, with per-workspace options and the `--workspace` filter.\n---\n\nWorkspaces are handled out-of-the-box by Knip.\n\nWorkspaces are sometimes also referred to as package-based monorepos, or as\npackages in a monorepo. Knip uses the term workspace exclusively to indicate a\ndirectory that has a `package.json`.\n\n## Configuration\n\nHere's example configuration with custom `entry` and `project` patterns:\n\n```json title=\"knip.json\"\n{\n  \"workspaces\": {\n    \".\": {\n      \"entry\": \"scripts/*.js\",\n      \"project\": \"scripts/**/*.js\"\n    },\n    \"packages/*\": {\n      \"entry\": \"{index,cli}.ts\",\n      \"project\": \"**/*.ts\"\n    },\n    \"packages/cli\": {\n      \"entry\": \"bin/cli.js\"\n    }\n  }\n}\n```\n\n:::tip\n\nRun Knip without any configuration to see if and where custom `entry` and/or\n`project` files are necessary per workspace.\n\n:::\n\nEach workspace has the same [default configuration][1].\n\nThe root workspace is named `\".\"` under `workspaces` (like in the example\nabove).\n\n:::caution\n\nIn a project with workspaces, the `entry` and `project` options at the root\nlevel are ignored. Use the workspace named `\".\"` for those (like in the example\nabove).\n\n:::\n\n## Workspaces\n\nKnip reads workspaces from four possible locations:\n\n1. The `workspaces` array in `package.json` (npm, Bun, Yarn, Lerna)\n2. The `packages` array in `pnpm-workspace.yaml` (pnpm)\n3. The `workspaces.packages` array in `package.json` (legacy)\n4. The `workspaces` object in Knip configuration\n\nThe `workspaces` in Knip configuration (4) not already defined in the root\n`package.json` or `pnpm-workspace.yaml` (1, 2, 3) are added to the analysis.\n\n:::caution\n\nA workspace must have a `package.json` file.\n\n:::\n\nFor projects with only a root `package.json`, please see [integrated\nmonorepos][2].\n\n## Additional workspaces\n\nIf a workspace is not configured as such in `package.json#workspaces` (or\n`pnpm-workspace.yaml`) it can be added to the Knip configuration manually. Add\ntheir path to the `workspaces` configuration object the same way as\n`\"packages/cli\": {}` in the example above.\n\n## Source mapping\n\nSee [Source Mapping][3].\n\n## Additional options\n\nThe following options are available inside workspace configurations:\n\n- [ignore][4]\n- [ignoreBinaries][5]\n- [ignoreDependencies][6]\n- [ignoreIssues][7]\n- [ignoreMembers][8]\n- [ignoreUnresolved][9]\n- [includeEntryExports][10]\n\n[Plugins][11] can be configured separately per workspace.\n\nUse `--debug` for verbose output and see the workspaces Knip includes, their\nconfigurations, enabled plugins, glob options and resolved files.\n\n## Filter workspaces\n\nUse the `--workspace` (or `-W`) argument to select one or more workspaces:\n\n```sh\nknip --workspace packages/my-lib\n```\n\nThe filter supports multiple formats:\n\n```sh\nknip --workspace @myorg/my-lib     # Package name\nknip --workspace '@myorg/*'        # Package name glob\nknip --workspace packages/my-lib   # Directory path\nknip --workspace './apps/*'        # Directory glob\n```\n\nCombine selectors to include or exclude workspaces:\n\n```sh\nknip --workspace @myorg/* --workspace '!@myorg/legacy'\nknip --workspace './apps/*' --workspace '@shared/utils'\n```\n\nThis will include the target workspace(s), but also ancestor, dependency and\ndependent workspaces. For three reasons:\n\n- Ancestor workspaces may list dependencies in `package.json` the linted\n  workspace uses.\n- Dependency workspaces may provide configuration and source information used by\n  the linted workspace.\n- Dependent workspaces may reference exports from the linted workspace.\n\nTo lint the workspace in isolation, there are two options:\n\n- Combine the `workspace` argument with [strict production mode][12].\n- Run Knip from inside the workspace directory.\n\n[1]: ../overview/configuration.md#defaults\n[2]: ./integrated-monorepos.md\n[3]: ./source-mapping.md\n[4]: ../reference/configuration.md#ignore\n[5]: ../reference/configuration.md#ignorebinaries\n[6]: ../reference/configuration.md#ignoredependencies\n[7]: ../reference/configuration.md#ignoreissues\n[8]: ../reference/configuration.md#ignoremembers\n[9]: ../reference/configuration.md#ignoreunresolved\n[10]: ../reference/configuration.md#includeentryexports\n[11]: ../reference/configuration.md#plugins\n[12]: ./production-mode.md#strict-mode\n","packages/docs/src/content/docs/features/production-mode.md":"---\ntitle: Production Mode\ndescription: Use `--production` and `--strict` with `!` entry patterns to lint only shipped code, ignoring tests, stories and config files.\n---\n\nThe default mode for Knip is comprehensive and targets all project code,\nincluding configuration files, test files, Storybook stories, and so on. Test\nfiles usually import production files. This prevents production files or their\nexports from being reported as unused, while sometimes both of them can be\ndeleted. Knip features a \"production mode\" to focus only on the code that you\nship.\n\n## Configuration\n\nTo tell Knip what is production code, add an exclamation mark behind each\n`pattern!` that represents production code:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts!\", \"build/script.js\"],\n  \"project\": [\"src/**/*.ts!\", \"build/*.js\"]\n}\n```\n\nDepending on file structure and enabled plugins, you might not need to modify\nyour configuration at all.\n\nRun Knip with the `--production` flag:\n\n```sh\nknip --production\n```\n\nHere's what's included in production mode:\n\n- Only `entry` and `project` patterns suffixed with `!`\n- Only production `entry` file patterns exported by plugins (such as Next.js and\n  Remix)\n- Only the `start` script (of `package.json#scripts`)\n- Ignore exports with the [`@internal` tag][1]\n\n:::note\n\nThe production run does not replace the default run. Depending on your needs you\ncan run either of them or both separately. Usually both modes can share the same\nconfiguration.\n\n:::\n\nTo see the difference between default and production mode in great detail, use\nthe `--debug` flag and inspect what entry and project files are used, and the\nplugins that are enabled. For instance, in production mode this shows that files\nsuch as tests and Storybook files (stories) are excluded from the analysis.\n\nIn case files like mocks and test helpers are reported as unused files, use\nnegated patterns to exclude those files in production mode:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts!\"],\n  \"project\": [\"src/**/*.ts!\", \"!src/test-helpers/**!\"]\n}\n```\n\nAlso see [configuring project files][2] to align `entry` and `project` with\nproduction mode.\n\n## Strict Mode\n\nIn production mode, only `dependencies` (not `devDependencies`) are considered\nwhen finding unused or unlisted dependencies.\n\nAdditionally, the `--strict` flag can be added to:\n\n- Verify isolation: workspaces should use strictly their own `dependencies`\n- Include required `peerDependencies` when finding unused or unlisted\n  dependencies\n- [Distinguish development-only type imports from types exposed to package\n  consumers][3]\n\n```sh\nknip --production --strict\n```\n\nUsing `--strict` implies `--production`, so the latter can be omitted.\n\n## Types\n\nAdd `--exclude types` if you don't want to include types in the report:\n\n```sh\nknip --production --exclude types\n```\n\n[1]: ../reference/jsdoc-tsdoc-tags.md#internal\n[2]: ../guides/configuring-project-files.md\n[3]: ../guides/handling-issues.mdx#production-types\n","packages/docs/src/content/docs/features/reporters.md":"---\ntitle: Reporters & Preprocessors\ndescription: Knip's built-in reporters (including the shape of `knip --reporter json` for scripts, CI and coding agents), plus custom reporters and preprocessors.\n---\n\n## Built-in Reporters\n\nKnip provides the following built-in reporters:\n\n- [`codeclimate`][1]\n- [`codeowners`][2]\n- `compact`\n- [`cycles`][3]\n- [`disclosure`][4]\n- [`github-actions`][5]\n- [`json`][6]\n- [`markdown`][7]\n- [`sarif`][8]\n- `symbols` (default)\n\nExample usage:\n\n```sh\nknip --reporter compact\n```\n\n### CodeClimate\n\nThe built-in `codeclimate` reporter generates output in the Code Climate Report\nJSON format. Example usage:\n\n```text\n$ knip --reporter codeclimate\n\n[\n  {\n    \"type\": \"issue\",\n    \"check_name\": \"Unused exports\",\n    \"description\": \"isUnused\",\n    \"categories\": [\"Bug Risk\"],\n    \"location\": {\n      \"path\": \"path/to/file.ts\",\n      \"positions\": {\n        \"begin\": {\n          \"line\": 6,\n          \"column\": 1\n        }\n      }\n    },\n    \"severity\": \"major\",\n    \"fingerprint\": \"e9789995c1fe9f7d75eed6a0c0f89e84\"\n  }\n]\n```\n\n### CODEOWNERS\n\nWhen a `.github/CODEOWNERS` file exists, each entry gains an `owners` array.\nPoint the reporter at a different path through [`--reporter-options`][9]:\n\n```sh\nknip --reporter json --reporter-options '{\"codeowners\":\"docs/CODEOWNERS\"}'\n```\n\n### Cycles\n\nA verbose, multi-line tree view of [circular dependencies][10]. Each file path\nis suffixed with the location of the import that continues the cycle. Each edge\nshows the import kind and specifier, descends one file per level, and closes\n(`↩`) back to the file it started from.\n\nUse `--cycles` to report only circular dependencies and `--reporter cycles` to\ndisplay them as a tree:\n\n```text\n$ knip --cycles --reporter cycles\n\nCircular dependencies (1)\n\nsrc/i18n/index.ts:1:28\n└── import ./middleware → src/i18n/middleware.ts:3:15\n    └── re-export ../core/i18n/handler → src/core/i18n/handler.ts:5:10\n        └── import ../../i18n → src/i18n/index.ts:1:28 ↩\n```\n\nKnip reports representative cycle paths found while walking the module graph.\nThis is not an exhaustive list of every possible simple cycle in a cyclic\nsubgraph, because that can produce a noisy and very large report. If the same\nfile participates in multiple distinct reported paths, each path is shown\nseparately.\n\nUse [`cycles.allow`][11] to accept known cycle paths.\n\nDynamic imports are ignored by default because they are commonly used to avoid\nsynchronous circular loads. Set [`cycles.dynamicImports`][11] to include them.\nRepeated starting imports are grouped under one heading.\n\nFor one line per cycle path, use `knip --cycles` with the default reporter. To\nreport unused code as well, [combine the issue-type shorthands][12].\n\nCycles are warnings by default. Set `\"rules\": { \"cycles\": \"error\" }` to make\nreported cycles cause a non-zero exit code.\n\n### Disclosure\n\nThis reporter is useful for sharing large reports. Groups of issues are rendered\nin a closed state initially. The reporter renders this:\n\n````text\n$ knip --reporter disclosure\n\n<details>\n<summary>Unused files (2)</summary>\n\n```\nunused.ts\ndangling.js\n```\n\n</details>\n\n<details>\n<summary>Unused dependencies (2)</summary>\n\n```\nmy-package     package.json:17:5\nunused-dep     package.json:20:5\n```\n\n</details>\n````\n\nThe above can be copy-pasted where HTML and Markdown is supported, such as a\nGitHub issue or pull request, and renders like so:\n\n<details>\n  <summary>Unused files (2)</summary>\n\n```\nunused.ts\ndangling.js\n```\n\n</details>\n\n<details>\n  <summary>Unused dependencies (2)</summary>\n\n```\nmy-package     package.json:17:5\nunused-dep     package.json:20:5\n```\n\n</details>\n\n### GitHub Actions\n\nUse the GitHub Actions reporter in a workflow for annotations in pull requests.\nExample usage:\n\n```sh\nknip --reporter github-actions\n```\n\nChanged files in pull requests will now contain inline annotations for lint\nfindings.\n\n### JSON\n\nThe `json` reporter prints machine-readable results for scripts, CI, and tools\n(including coding agents) to consume:\n\n```sh\nknip --reporter json\n```\n\nOutput is one line of JSON. Formatted here for readability:\n\n```json\n{\n  \"issues\": [\n    {\n      \"file\": \"src/legacy.ts\",\n      \"files\": [{ \"name\": \"src/legacy.ts\" }]\n    },\n    {\n      \"file\": \"src/math.ts\",\n      \"exports\": [{ \"name\": \"factorial\", \"line\": 12, \"col\": 14, \"pos\": 256 }],\n      \"types\": [{ \"name\": \"Radians\", \"line\": 20, \"col\": 13, \"pos\": 410 }]\n    },\n    {\n      \"file\": \"package.json\",\n      \"dependencies\": [{ \"name\": \"lodash\" }],\n      \"unlisted\": [{ \"name\": \"rimraf\" }]\n    }\n  ]\n}\n```\n\nThe top level is an object with a single `issues` array. Each element groups\nevery issue found in one file:\n\n| Field        | Type         | Notes                                               |\n| :----------- | :----------- | :-------------------------------------------------- |\n| `file`       | `string`     | Path relative to the working directory              |\n| `owners`     | `{ name }[]` | Code owners, only when a `CODEOWNERS` file is found |\n| _issue type_ | array        | One key per enabled issue type (see below)          |\n\nEach entry carries a key for **every enabled [issue type][10]**, so the keys are\nthe same across entries. An array is empty when that file has no issues of that\ntype. Drop a type's key by disabling it with [filters or rules][12].\n\nIssue-type items are objects with position info:\n\n| Field       | Type      | Notes                                          |\n| :---------- | :-------- | :--------------------------------------------- |\n| `name`      | `string`  | The unused symbol, dependency, file, or import |\n| `namespace` | `string?` | Set for namespace members                      |\n| `line`      | `number?` | 1-based line                                   |\n| `col`       | `number?` | 1-based column                                 |\n| `pos`       | `number?` | Character offset                               |\n\nSee [Issue types][10] for the full set of issue-type keys.\n\nFor a typed object instead of JSON to parse, write a [custom reporter][13].\nCoding agents can also call Knip through the [MCP server][14], which returns\nstructured results and configuration hints directly.\n\n### SARIF\n\nThe `sarif` reporter emits [SARIF 2.1.0][15] for code-scanning integrations:\n\n```sh\nknip --reporter sarif > knip.sarif\n```\n\nFor example, upload the report to GitHub Code Scanning after installing project\ndependencies:\n\n```yaml\npermissions:\n  contents: read\n  security-events: write\n\nsteps:\n  - uses: actions/checkout@v4\n  - run: pnpm exec knip --reporter sarif > knip.sarif\n  - if: always()\n    uses: github/codeql-action/upload-sarif@v4\n    with:\n      sarif_file: knip.sarif\n```\n\nThe upload step runs even when Knip finds issues and exits non-zero. GitHub Code\nScanning availability for private repositories depends on the repository's\nGitHub Code Security plan.\n\n### Markdown\n\nThe built-in `markdown` reporter output is meant to be saved to a Markdown file.\nThis allows following the changes in issues over time. It reports issues in\nMarkdown tables separated by issue types as headings, for example:\n\n```md\n# Knip report\n\n## Unused files (1)\n\n- src/unused.ts\n\n## Unlisted dependencies (2)\n\n| Name            | Location          | Severity |\n| :-------------- | :---------------- | :------- |\n| unresolved      | src/index.ts:8:23 | error    |\n| @org/unresolved | src/index.ts:9:23 | error    |\n\n## Unresolved imports (1)\n\n| Name         | Location           | Severity |\n| :----------- | :----------------- | :------- |\n| ./unresolved | src/index.ts:10:12 | error    |\n```\n\n## Custom Reporters\n\nWhen the provided built-in reporters are not sufficient, a custom local reporter\ncan be implemented or an external reporter can be used. Multiple reporters can\nbe used at once by repeating the `--reporter` argument.\n\nThe results are passed to the function from its default export and can be used\nto write issues to `stdout`, a JSON or CSV file, or sent to a service. It\nsupports a local JavaScript or TypeScript file or an external dependency.\n\n### Local\n\nThe default export of the reporter should be a function with this interface:\n\n```ts\ntype Reporter = (options: ReporterOptions) => void;\n\ntype ReporterOptions = {\n  report: Report;\n  issues: Issues;\n  counters: Counters;\n  configurationHints: ConfigurationHints;\n  isDisableConfigHints: boolean;\n  isTreatConfigHintsAsErrors: boolean;\n  cwd: string;\n  isProduction: boolean;\n  isShowProgress: boolean;\n  options: string;\n};\n```\n\nThe data can then be used to write issues to `stdout`, a JSON or CSV file, or\nsent to a service.\n\nHere's a most minimal reporter example:\n\n```ts title=\"./my-reporter.ts\"\nimport type { Reporter } from 'knip';\n\nconst reporter: Reporter = function (options) {\n  console.log(options.issues);\n  console.log(options.counters);\n};\n\nexport default reporter;\n```\n\nExample usage:\n\n```sh\nknip --reporter ./my-reporter.ts\n```\n\n### External\n\nPass `--reporter [pkg-name]` to use an external reporter. The default exported\nfunction of the `main` script (default: `index.js`) will be invoked with the\n`ReporterOptions`, just like a local reporter.\n\n## Preprocessors\n\nA preprocessor is a function that runs after the analysis is finished. It\nreceives the results from the analysis and should return data in the same\nshape/structure (unless you pass it to only your own reporter).\n\nThe data goes through the preprocessors before the final data is passed to the\nreporters. There are no built-in preprocessors. Just like reporters, use e.g.\n`--preprocessor ./my-preprocessor` from the command line (can be repeated).\n\nThe default export of the preprocessor should be a function with this interface:\n\n```ts\ntype Preprocessor = (options: ReporterOptions) => ReporterOptions;\n```\n\nLike reporters, you can use local JavaScript or TypeScript files and external\nnpm packages as preprocessors.\n\nExample preprocessor:\n\n```ts title=\"./preprocess.ts\"\nimport type { Preprocessor } from 'knip';\n\nconst preprocess: Preprocessor = function (options) {\n  // modify options.issues and options.counters\n  return options;\n};\n\nexport default preprocess;\n```\n\nExample usage:\n\n```sh\nknip --preprocessor ./preprocess.ts\n```\n\nPreprocessors can also be configured in the Knip configuration file:\n\n```json title=\"knip.json\"\n{\n  \"preprocessor\": \"./preprocess.ts\"\n}\n```\n\n[1]: #codeclimate\n[2]: #codeowners\n[3]: #cycles\n[4]: #disclosure\n[5]: #github-actions\n[6]: #json\n[7]: #markdown\n[8]: #sarif\n[9]: ../reference/cli.md#--reporter-options-json\n[10]: ../reference/issue-types.md\n[11]: ../reference/configuration.md#cycles\n[12]: ./rules-and-filters.md\n[13]: #custom-reporters\n[14]: ../reference/integrations.md\n[15]: https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html\n","packages/docs/src/content/docs/features/rules-and-filters.md":"---\ntitle: Rules & Filters\ndescription: Customize Knip's output with `--include`/`--exclude` filters, shorthand flags and `rules` to set issue types to error, warn or off.\n---\n\nUse rules or filters to customize Knip's output. This has various use cases, a\nfew examples:\n\n- Temporarily focus on a specific issue type.\n- You don't want to see unused `type`, `interface` and `enum` exports reported.\n- Specific issue types should be printed, but not counted against the total\n  error count.\n\nIf you're looking to handle one-off exceptions, also see [JSDoc tags][1].\n\n## Filters\n\nYou can `--include` or `--exclude` any of the reported issue types to slice &\ndice the report to your needs. Alternatively, they can be added to the\nconfiguration (e.g. `\"exclude\": [\"dependencies\"]`).\n\nUse `--include` to report only specific issue types. The following example\ncommands do the same:\n\n```sh\nknip --include files --include dependencies\nknip --include files,dependencies\n```\n\nOr the other way around, use `--exclude` to ignore the types you're not\ninterested in:\n\n```sh\nknip --include files --exclude enumMembers,duplicates\n```\n\nThe `nsExports` and `nsTypes` types are [off by default][2]. Including only\nthose _adds_ them to the default report, rather than narrowing it to just those.\n\n`cycles` is also off by default. `--include cycles` (or `\"include\": [\"cycles\"]`\nin configuration) reports only circular dependencies. Use it with the [cycles\nreporter][3] for a detailed tree view.\n\nAlso see the [list of issue types][4].\n\n### Shorthands\n\nKnip has shortcuts to report only specific issue types.\n\n1. The `--dependencies` flag includes:\n   - `dependencies` (and `devDependencies` + `optionalPeerDependencies`)\n   - `unlisted`\n   - `binaries`\n   - `unresolved`\n   - `catalog`\n   - `catalogReferences`\n\n2. The `--exports` flag includes:\n   - `exports`\n   - `types`\n   - `enumMembers`\n   - `namespaceMembers`\n   - `duplicates`\n\n3. The `--files` flag is a shortcut to report only unused files.\n\n4. The `--cycles` flag is a shortcut to report only circular dependencies.\n\nCombine shorthands to report the default issue types plus circular dependencies:\n\n```sh\nknip --dependencies --exports --files --cycles\n```\n\n## Rules\n\nUse `rules` in the configuration to customize the issue types that count towards\nthe total error count, or to exclude them altogether.\n\n| Value     | Default | Printed | Counted | Description                       |\n| :-------- | :-----: | :-----: | :-----: | :-------------------------------- |\n| `\"error\"` |   ✓ ¹   |    ✓    |    ✓    | Similar to the `--include` filter |\n| `\"warn\"`  |    -    |    ✓    |    -    | Printed in faded/gray color       |\n| `\"off\"`   |    -    |    -    |    -    | Similar to the `--exclude` filter |\n\nExample:\n\n```json title=\"knip.json\"\n{\n  \"rules\": {\n    \"files\": \"warn\",\n    \"duplicates\": \"off\"\n  }\n}\n```\n\nNotes:\n\n- ¹ Exception: the `cycles` issue type is a warning by default.\n- If the `dependencies` issue type is included, the `devDependencies` and\n  `optionalPeerDependencies` types can still be set to `\"warn\"` separately.\n- The rules are modeled after the ESLint `rules` configuration, and could be\n  extended in the future.\n\nAlso see the [issue types overview][4].\n\n## Rules or filters?\n\nFilters are meant to be used as command-line flags, rules allow for more\nfine-grained configuration.\n\n- Rules are more fine-grained since they also have \"warn\".\n- Rules could be extended in the future.\n- Filters can be set in configuration and from CLI (rules only in\n  configuration).\n- Filters have shorthands (rules don't have this).\n\n[1]: ../reference/jsdoc-tsdoc-tags.md\n[2]: ../guides/namespace-imports.md\n[3]: ./reporters.md#cycles\n[4]: ../reference/issue-types.md\n","packages/docs/src/content/docs/features/script-parser.md":"---\ntitle: Script Parser\ndescription: How Knip statically parses shell scripts and CLI arguments in `package.json`, plugins and source code to find entry files and dependencies.\n---\n\nKnip parses shell commands and scripts to find additional dependencies, entry\nfiles and configuration files in various places:\n\n- In [`package.json`][1]\n- In [CLI arguments][2]\n- In [scripts][3]\n- In [source code][4]\n\nShell scripts are parsed and statically analyzed, but they're not executed.\n\n## package.json\n\nThe `main`, `bin`, `exports` and `scripts` fields may contain entry files. Let's\ntake a look at this example:\n\n```json title=\"package.json\"\n{\n  \"name\": \"my-package\",\n  \"main\": \"index.js\",\n  \"exports\": {\n    \"./lib\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./dist/index.cjs\"\n    }\n  },\n  \"bin\": {\n    \"program\": \"bin/cli.js\"\n  },\n  \"scripts\": {\n    \"build\": \"rollup src/entry.ts\",\n    \"start\": \"node --loader tsx server.ts\"\n  }\n}\n```\n\nFrom this example, Knip automatically adds the following files as entry files:\n\n- `index.js`\n- `./dist/index.mjs`\n- `./dist/index.cjs`\n- `bin/cli.js`\n- `src/entry.ts`\n- `server.ts`\n\n### Excluded files\n\nKnip would not add the `exports` if the `dist` folder is matching a pattern in a\nrelevant `.gitignore` file or `ignore` option.\n\nKnip does not add scripts without a standard extension. For instance, the\n`bin/tool` file might be a valid executable for Node.js, but wouldn't be added\nor parsed by Knip.\n\n### CLI Arguments\n\nWhen parsing the `scripts` of `package.json` and other files, Knip detects\nvarious types of inputs. Some examples:\n\n- The first positional argument is usually an entry file\n- Configuration files are often in the `-c` or `--config` argument\n- The `--require`, `--loader` or `--import` arguments are often dependencies\n\n```json\n{\n  \"name\": \"my-lib\",\n  \"scripts\": {\n    \"start\": \"node --import tsx/esm run.ts\",\n    \"bundle\": \"tsup -c tsup.lib.config.ts\",\n    \"type-check\": \"tsc -p tsconfig.app.json\"\n  }\n}\n```\n\nThe `\"start\"` script will have `tsx` marked as a referenced dependency, and adds\n`run.ts` as an entry file.\n\nAdditionally, the following files are detected as configuration files:\n\n- `tsup.lib.config.ts` - to be handled by the tsup plugin\n- `tsconfig.app.json` - to be handled by the TypeScript plugin\n\nSuch executables and their arguments are all defined in plugins separately for\nfine-grained results.\n\n## Scripts\n\nPlugins may also use the script parser to extract entry files and dependencies\nfrom commands. A few examples:\n\n- GitHub Actions: workflow files may contain `run` commands (e.g.\n  `.github/workflows/ci.yml`)\n- Husky & Lefthook: Git hooks such as `.git/hooks/pre-push` contain scripts;\n  also `lefthook.yml` has `run` commands\n- Lint Staged: configuration values are all commands\n- Nx: task executors and `nx:run-commands` executors in `project.json` contains\n  scripts\n- Release It: `hooks` contain commands\n\nPlugins can also return configuration files. Some examples:\n\n- The Angular plugin detects `options.tsConfig` as a TypeScript config file\n- The GitHub Actions plugin parses `run` commands which may contain\n  configuration file paths\n\n## Source Code\n\nWhen Knip is walking the abstract syntax trees (ASTs) of JavaScript and\nTypeScript source code files, it looks for imports and exports. But there's a\nfew more (rather obscure) things that Knip detects in the process. Below are\nexamples of additional scripts Knip parses to find entry files and dependencies.\n\n### bun\n\nIf the `bun` dependency is imported in source code, Knip considers the contents\nof `$` template tags to be scripts:\n\n```ts\nimport { $ } from 'bun';\nawait $`bun boxen I ❤ unicorns`;\nawait $`boxen I ❤ unicorns`;\n```\n\nParsing the script results in the `boxen` binary (the `boxen-cli` dependency) as\nreferenced (twice).\n\n### execa\n\nIf the `execa` dependency is imported in source code, Knip considers the\ncontents of `$` template tags to be scripts:\n\n```ts\nawait $({ stdio: 'inherit' })`c8 node hydrate.js`;\n```\n\nParsing the script results in `hydrate.js` added as an entry file and the `c8`\nbinary/dependency as referenced. The `execa()`, `execaSync()`, `execaCommand()`\nand `execaCommandSync()` call forms are parsed the same way.\n\n### zx\n\nIf the `zx` dependency is imported in source code, Knip considers the contents\nof `$` template tags to be scripts:\n\n```ts\nawait $`node scripts/parse.js`;\n```\n\nThis will add `scripts/parse.js` as an entry file.\n\n### child\\_process\n\nIf `node:child_process` is imported in source code, Knip parses the command in\n`exec`/`execSync` calls and the executable (with its arguments) in\n`spawn`/`spawnSync`/`execFile`/`execFileSync` calls:\n\n```ts\nimport { execSync, execFile } from 'node:child_process';\nexecSync('eslint --cache');\nexecFile('boxen', ['I ❤ unicorns']);\n```\n\nThis marks the `eslint` and `boxen` binaries as referenced. An inline\n`path.join(__dirname, …)` argument to `spawn`, `execFile` or `fork` is added as\nan entry file instead.\n\n### nano-spawn\n\nIf `nano-spawn` is imported in source code, Knip parses the executable and its\narguments:\n\n```ts\nimport spawn from 'nano-spawn';\nawait spawn('gsutil', ['cp', './file.txt', 'gs://bucket/']);\n```\n\nThis marks the `gsutil` binary as referenced.\n\n[1]: #packagejson\n[2]: #cli-arguments\n[3]: #scripts\n[4]: #source-code\n","packages/docs/src/content/docs/features/source-mapping.md":"---\ntitle: Source Mapping\ndescription: How Knip maps build artifacts in `dist`/`outDir` back to their original source files using `tsconfig.json` to avoid false positives.\n---\n\nKnip is mostly interested in source code. Analyzing build artifacts hurts\nperformance and often leads to false positives, as they potentially contain\nbundled code and unresolvable imports.\n\nThat's why Knip tries to map such build artifacts back to their original source\nfiles and analyze those instead. This is done based on `tsconfig.json` settings.\n\n## Example 1: package.json\n\nLet's look at an example case with `package.json` and `tsconfig.json` files, and\nsee how \"dist\" files are mapped to \"src\" files.\n\n```jsonc title=\"package.json\"\n{\n  \"name\": \"my-workspace\",\n  \"main\": \"index.js\",\n  \"exports\": {\n    \".\": \"./src/entry.js\",\n    \"./feat\": \"./lib/feat.js\",\n    \"./public\": \"./dist/app.js\",\n    \"./public/*\": \"./dist/*.js\",\n    \"./public/*.js\": \"./dist/*.js\",\n    \"./dist/internal/*\": null,\n  },\n}\n```\n\nWith this TypeScript configuration:\n\n```json title=\"tsconfig.json\"\n{\n  \"compilerOptions\": {\n    \"baseUrl\": \"src\",\n    \"outDir\": \"dist\"\n  }\n}\n```\n\n- `./src/entry.js` is not in an `outDir` folder, so it's added as an entry file\n- `./lib/feat.js` is not in an `outDir` folder, so it's added as an entry file\n- `./dist/app.js` is in a `dist` folder and mapped to `./src/app.{js,ts}` (¹)\n- `./dist/*.js` is in a `dist` folder and mapped to `./src/**/*.{js,ts}` (¹)\n- `./dist/internal/*` is translated to `./dist/internal/**` and files in this\n  directory and deeper are ignored when globbing entry files\n\n(¹) full extensions list is actually: `js`, `mjs`, `cjs`, `jsx`, `ts`, `tsx`,\n`mts`, `cts`\n\nIn `--debug` mode, look for \"Source mapping\" to see this in action.\n\n:::tip\n\nUsing `./dist/*.js` means that all files matching `./src/**/*.{js,ts}` are added\nas entry files. By default, unused exports of entry files are not reported. Use\n[includeEntryExports][1] to include them.\n\n:::\n\n## Example 2: monorepo\n\nLet's say we have this module in a monorepo that imports `helper` from another\nworkspace in the same monorepo:\n\n```ts title=\"index.js\"\nimport { helper } from '@org/shared';\n```\n\nThe target workspace `@org/shared` has this `package.json`:\n\n```json title=\"package.json\"\n{\n  \"name\": \"@org/shared\",\n  \"main\": \"dist/index.js\"\n}\n```\n\nThe module resolver will resolve `@org/shared` to `dist/index.js`. That file is\nusually compiled and git-ignored, while Knip wants the source file instead.\n\n:::tip\n\nYou may need to compile build artifacts to `outDir` first before Knip can\nsuccessfully apply source mapping for internal references in a monorepo.\n\n:::\n\nIf the target workspace has a `tsconfig.json` file with an `outDir` option, Knip\nwill try to map the \"dist\" file to the \"src\" file. Then if `src/index.ts`\nexists, Knip will use that file instead of `dist/index.js`.\n\nCurrently this only works based on `tsconfig.json`, in the future more source\nmappings may be added.\n\n## Example 3: source conditions\n\nSource-first monorepos may expose source files directly through a custom\ncondition in `package.json#exports` or `#imports` maps:\n\n```json title=\"package.json\"\n{\n  \"name\": \"@org/shared\",\n  \"exports\": {\n    \".\": {\n      \"@org/source\": \"./src/index.ts\",\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    }\n  }\n}\n```\n\nWhen module resolution fails because the targets aren't built, Knip falls back\nto the first conditional target of the workspace package that exists on disk,\nregardless of the condition's name. No build step or configuration required.\n\n[1]: ../reference/configuration.md#includeentryexports\n","packages/docs/src/content/docs/guides/adopt-gradually.md":"---\ntitle: Adopt Knip gradually\ndescription: Roll Knip out on a large or legacy codebase without trying to reach zero on day one. Baseline, focus one issue type at a time, then ratchet with rules.\n---\n\nOn a large or legacy codebase the first run can report a lot. Reaching zero in\none sitting is then the wrong goal. Get a trustworthy signal first, then ratchet\nthe codebase toward clean and keep it there.\n\n## Actionable baseline\n\nMost of the noise on a first run comes from gaps in what Knip can reach: a\ndependency that Knip does not have a plugin for yet, an entry point it can't\nresolve, a phantom dependency. Fix the gaps before you delete anything:\n\n- Address [configuration hints][1].\n- Tune [entry and project files][2] so Knip analyzes the right set of files.\n- Tune configuration for your tools' [plugins][3].\n\nRead the output from the top. One unused file hides its exports and\ndependencies, so files come first.\n\nOnce the report reflects real findings instead of gaps, you have an actionable\nbaseline.\n\n## Focus one issue type at a time\n\nDon't fix everything at once. Narrow the report with [filters][4]:\n\n```sh\nknip --files        # unused files only (the major cascade!)\nknip --dependencies # then dependencies\nknip --exports      # then exports and types\n```\n\nClear one type, commit, move to the next.\n\n## Stage by rules\n\n[Rules][5] set a severity per issue type. Start by setting all types to\n`\"warn\"`, and then the types you've cleaned to `\"error\"`. Warnings are printed\nin gray, and they don't fail the run. Example:\n\n```json title=\"knip.json\"\n{\n  \"rules\": {\n    \"files\": \"error\",\n    \"dependencies\": \"error\",\n    \"exports\": \"warn\",\n    \"duplicates\": \"off\"\n  }\n}\n```\n\nAs each `\"warn\"` type reaches zero, set it to `\"error\"`. Keep iterating and\nprune the codebase to perfection.\n\n## Gate CI without blocking the team\n\nAdd Knip to [CI][6] as soon as you have a baseline, so new clutter is caught in\nreview. A few ways to stage it:\n\n- Mark cleaned types `\"error\"` and the rest `\"warn\"`, so CI fails only on the\n  types you've finished.\n- Workspace by workspace: in a [monorepo][7], scope passes with `--workspace`\n  (accepts multiple workspaces and glob patterns).\n- Production first: [`--production`][8] limits analysis to shipped code, so you\n  can clean what matters most and defer tests and tooling.\n- Set a budget, so CI fails only when the count exceeds the number (e.g. `knip\n--max-issues 50`). This blocks regressions while you burn down the rest.\n- Run report-only with [`--no-exit-code`][9] while you're still triaging.\n\n## Suppress only what's justified\n\nWhen something is genuinely fine as-is, prefer a specific, documented signal\nover a blanket `ignore`, for example:\n\n- tag an export with e.g. [`@lintignore` or `@internal`][10]\n- use [`ignoreExportsUsedInFile`][11] for internal-only exports\n- list known exceptions in [`ignoreDependencies`][12]\n\n[Resolving reported issues][13] covers the right tool for each case.\n\n[1]: ../reference/configuration-hints.md\n[2]: ./configuring-project-files.md\n[3]: ../explanations/plugins.md\n[4]: ../features/rules-and-filters.md#filters\n[5]: ../features/rules-and-filters.md#rules\n[6]: ./using-knip-in-ci.md\n[7]: ../features/monorepos-and-workspaces.md\n[8]: ../features/production-mode.md\n[9]: ../reference/cli.md#--no-exit-code\n[10]: ../reference/jsdoc-tsdoc-tags.md\n[11]: ../reference/configuration.md#ignoreexportsusedinfile\n[12]: ../reference/configuration.md#ignoredependencies\n[13]: ./handling-issues.mdx\n","packages/docs/src/content/docs/guides/configuring-project-files.md":"---\ntitle: Configuring Project Files\ndescription: How to set Knip's `entry` and `project` file patterns, use negations and production mode, and when to reach for `ignore`.\n---\n\nThe `entry` and `project` file patterns are the first and most important\noptions. Getting those right is essential to help you delete more code and make\nKnip faster:\n\n- Start with defaults. Only add targeted `entry` overrides when needed.\n- Use `project` patterns (with negations) to define the scope for Knip.\n- Use production mode to exclude tests and other non-production files.\n- Use `ignore` only to suppress issues in specific files; it does not exclude\n  files from analysis.\n\nLet's dive in and expand on all of these.\n\n## Entry files\n\nAvoid adding too many files as `entry` files:\n\n1. Knip does not report [unused exports][1] in entry files by default.\n2. Proper `entry` and `project` patterns allow Knip to find unused files and\n   exports.\n\n## Unused files\n\nFiles are reported as unused if they are in the set of `project` files, but are\nnot resolved from the `entry` files:\n\n```\nunused files = project files - (entry files + resolved files)\n```\n\nSee [entry files][2] to see where Knip looks for entry files. Fine-tune `entry`\nand adjust `project` to fit your codebase.\n\n:::tip\n\nUse negated `project` patterns to precisely include/exclude files for unused\nfiles detection.\n\nUse `ignore*` to suppress specific issues in matching files; it does not exclude\nfiles from analysis.\n\n:::\n\n## Negated patterns\n\nWhen there are too many files in the analysis, start here.\n\nFor instance, routes are entry files except those prefixed with an underscore:\n\n```json\n{\n  \"entry\": [\"src/routes/*.ts\", \"!src/routes/_*.ts\"]\n}\n```\n\nSome files are not part of your source and are reported as unused (false\npositives)? Use negated `project` patterns:\n\n```json\n{\n  \"entry\": [\"src/index.ts\"],\n  \"project\": [\"src/**/*.ts\", \"!src/exclude/**\"]\n}\n```\n\n❌   Don't use `ignore` for generated artifacts:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts\", \"scripts/*.ts\"],\n  \"ignore\": [\"build/**\", \"dist/**\", \"src/generated.ts\"]\n}\n```\n\n✅   Do define your project boundaries:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts\", \"scripts/*.ts\"],\n  \"project\": [\"src/**\", \"scripts/**\"],\n  \"ignore\": [\"src/generated.ts\"]\n}\n```\n\nWhy this is better:\n\n- `project` defines what belongs to the codebase, so build outputs are excluded\n  from analysis and unused file detection\n- `ignore` is for the few files that should be analyzed but contain exceptions\n- Improves performance by analyzing fewer files\n\n## Ignore issues in specific files\n\nUse `ignore` when a specific analyzed file is not handled properly by Knip or\nintentionally contains unused exports (e.g. generated files exporting\n\"everything\"):\n\n```json\n{\n  \"entry\": [\"src/index.ts\"],\n  \"project\": [\"src/**/*.ts\"],\n  \"ignore\": [\"src/generated.ts\"]\n}\n```\n\nAlso see [ignoreExportsUsedInFile][3] for a more targeted approach.\n\n## Production Mode\n\nDefault mode includes tests and other non-production files in the analysis. To\nfocus on production code, use [production mode][4].\n\nDon't try to exclude tests via `ignore` or negated `project` patterns. That's\ninefficient and ineffective due to entries added by plugins. Use production mode\ninstead.\n\n❌   Don't do this:\n\n```json\n{\n  \"ignore\": [\"**/*.test.js\"]\n}\n```\n\nWhy not: `ignore` hides issues from the report; it does not exclude files from\nanalysis.\n\n❌   Also don't do this:\n\n```json\n{\n  \"entry\": [\"index.ts\", \"!**/*.test.js\"]\n}\n```\n\nWhy not: plugins add test files as `entry` files; you can't and shouldn't\noverride that globally.\n\n❌   Or this:\n\n```json\n{\n  \"project\": [\"**/*.ts\", \"!**/*.spec.ts\"]\n}\n```\n\nWhy not: `project` is for unused file detection; negating test files is\nineffective because they are `entry` files.\n\n✅   Do this instead:\n\n```shell\nknip --production\n```\n\nTo fine-tune the resulting production file set, for instance to exclude test\nhelper files that still show as unused, use the exclamation mark suffix on\nproduction patterns:\n\n```json\n{\n  \"entry\": [\"src/index.ts!\"],\n  \"project\": [\"src/**/*.ts!\", \"!src/test-helpers/**!\"]\n}\n```\n\nRemember to keep adding the exclamation mark `suffix!` for production file\npatterns.\n\n:::tip\n\nUse the exclamation mark (`!`) on both ends (`!`) to exclude files in production\nmode.\n\n:::\n\n## Defaults & Plugins\n\nTo reiterate, the default `entry` and `project` files for each workspace:\n\n```json\n{\n  \"entry\": [\n    \"{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\",\n    \"src/{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\"\n  ],\n  \"project\": [\"**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}!\"]\n}\n```\n\nNext to this, there are other places where [Knip looks for entry files][2].\n\nAdditionally, [plugins have plenty of entry files configured][5] that are\nautomatically added as well.\n\n[1]: ../typescript/unused-exports.md\n[2]: ../explanations/entry-files.md\n[3]: ../reference/configuration.md#ignoreexportsusedinfile\n[4]: ../features/production-mode.md\n[5]: ../explanations/plugins.md#entry-files\n","packages/docs/src/content/docs/guides/contributing.md":"---\ntitle: Contributing to Knip\ndescription: Ways to contribute to Knip, including filing reproductions, opening pull requests, and writing a plugin.\n---\n\nHere are some ways to contribute to Knip:\n\n- Spread the word!\n- [Star the project][1]\n- [File an issue with a reproduction][2]\n- [Pull requests are welcome][3]\n\n[Writing a plugin][4] is a great and fun way to get started.\n\nThe [CONTRIBUTING.md][3] and [DEVELOPMENT.md][5] guides should get you up and\nrunning quickly.\n\nThe main goal of Knip is to keep projects clean & tidy. Everything that\ncontributes to that goal is welcome!\n\n[1]: https://github.com/webpro-nl/knip\n[2]: ./issue-reproduction.md\n[3]: https://github.com/webpro-nl/knip/blob/main/.github/CONTRIBUTING.md\n[4]: ../writing-a-plugin/index.md\n[5]: https://github.com/webpro-nl/knip/blob/main/.github/DEVELOPMENT.md\n","packages/docs/src/content/docs/guides/issue-reproduction.md":"---\ntitle: Issue Reproduction\ndescription: How to create a minimal reproduction for a Knip bug or false positive using CodeSandbox, StackBlitz, a repo, or a test fixture.\n---\n\nIf you encounter an issue or false positives when using Knip, you can [open an\nissue on GitHub][1]. This will help you in your project, and will also improve\nKnip for everyone else!\n\nThink of Knip as a kitchen sink, it handles a large amount of projects and\nconfigurations, and your project is different from all others. Many factors may\ninfluence the issue at hand, such as:\n\n- Code syntax, import and export structure in source files\n- Dependencies, scripts and entry files in `package.json`\n- TypeScript configuration in `tsconfig.json`\n- Enabled plugins and related configuration files\n- Dependent or depending workspaces in a monorepo\n- Knip configuration in `knip.json`\n\n## Keep it minimal\n\nCreate the minimum of source code and configuration with a few files to\nreproduce and demonstrate the issue. Having this as a basis has many benefits:\n\n- Minimize barriers and unrelated contextual overhead\n- Optimize shared understanding of the situation\n- Serves as a \"contract\" to fix the actual issue\n- Files serve as a fixture to the project\n\nProviding this with an issue description will help us help you and improve the\nchances the issue can be looked into efficiently and in a timely manner.\n\nUseful **complements** to a minimal reproduction might include:\n\n- Screenshots, videos, code snippets or log output\n- Links to an existing project repository\n- Applications scaffolded by tools like Angular or Svelte CLI\n\n## Before opening an issue\n\nBefore opening an issue, please make sure you:\n\n- are using the latest version\n- have read the relevant documentation\n- have searched [existing issues][1]\n- have checked the list of [known issues][2]\n\nPlease file only a single issue at a time, so each of them can be labeled and\ntracked separately.\n\nThere is no need to open an issue if you're going to submit a pull request to\nclose it right away anyway. In that case it's preferred to keep things central\nin either an issue or pull request.\n\n## Templates\n\nA convenient way to create a minimal reproduction is by starting with one of\nthese templates in CodeSandbox or StackBlitz:\n\n| Template |                  |                 |\n| :------- | ---------------- | --------------- |\n| Basic    | [CodeSandbox][3] | [StackBlitz][4] |\n| Monorepo | [CodeSandbox][5] | [StackBlitz][6] |\n\nShoutout to [CodeSandbox][7] and [StackBlitz][8] for generously providing these\nfree dev containers!\n\n## Alternatives\n\nOther solutions to share a minimal and reproducible case may work well too,\nincluding:\n\n- A public repository on e.g. GitHub or GitLab.\n- A pull request with a new [test][9] and/or [fixture folder][10].\n\nThe goal is to have an easy and common understanding and reproduction. If you're\nunable to create a reproduction using one of the methods described then please\nclearly explain this in the issue or [contact me][11].\n\n## Pull Request\n\nThe optimal way is to add fixtures and failing tests to the Knip repository, and\nopen a pull request to discuss the issue! Also see [instructions for\ndevelopment][12].\n\n[1]: https://github.com/webpro-nl/knip/issues?q=is%3Aissue\n[2]: https://knip.dev/reference/known-issues\n[3]: https://codesandbox.io/p/devbox/github/webpro-nl/knip/main/templates/issue-reproduction/basic\n[4]: https://stackblitz.com/github/webpro-nl/knip/tree/main/templates/issue-reproduction/basic\n[5]: https://codesandbox.io/p/devbox/github/webpro-nl/knip/main/templates/issue-reproduction/monorepo\n[6]: https://stackblitz.com/github/webpro-nl/knip/tree/main/templates/issue-reproduction/monorepo\n[7]: https://codesandbox.io\n[8]: https://stackblitz.com\n[9]: https://github.com/webpro-nl/knip/blob/main/.github/DEVELOPMENT.md#tests\n[10]: https://github.com/webpro-nl/knip/tree/main/packages/knip/fixtures\n[11]: https://github.com/webpro\n[12]: https://github.com/webpro-nl/knip/blob/main/.github/DEVELOPMENT.md\n","packages/docs/src/content/docs/guides/namespace-imports.md":"---\ntitle: Namespace Imports\ndescription: How Knip handles exports used through `import * as NS` namespace imports, its usage heuristic, and the `nsExports` and `nsTypes` issue types.\n---\n\nThe intention of exports used through namespace imports may not always be clear\nto Knip. Here's a guide to better understand how Knip handles such exports.\n\n## Example\n\nWe start off by having two exports:\n\n```ts title=\"my-namespace.js\"\nexport const version = 'v5';\nexport const getRocket = () => '🚀';\n```\n\nThe next snippet shows how to import all the exports above on a namespace. All\nexports of the `my-namespace.js` module will be members on the `NS` object:\n\n```ts title=\"my-module.ts\"\nimport * as NS from './my-namespace.js';\nimport send from 'stats';\nsend(NS);\n```\n\nThe intention of export usage is not always clear. In the example above is\n`version` or `getRocket` used? We're not sure, but we _probably_ don't want them\nto be reported as unused. The same goes for the next example:\n\n```ts title=\"my-module.ts\"\nimport * as NS from './my-namespace.js';\n\nexport { NS };\n```\n\nIf this is all usage of the `NS` namespace object, we also don't know whether\nindividual exports like `version` or `getRocket` will be used. However, if at\nleast one reference to a property such as `NS.version` is found, then the\nindividual exports are considered separately again and `getRocket` will be\nmarked as unused:\n\n```ts title=\"index.ts\"\nimport { NS } from './my-module.js';\n\nconst version = NS.version;\n```\n\n## The default heuristic\n\nKnip uses the following heuristic to determine which of the individual exports\nare used:\n\n- If there's one or more references to the import namespace object, but without\n  any property access, all exports on that namespace are considered used.\n- Otherwise, exports are considered separately.\n\nBelow are a few more examples, and a way to disable this default behavior.\n\n## Examples\n\nLet's take a look at more examples:\n\n```ts title=\"my-namespace.ts\"\nexport const start = 1;\n\nexport const end = 1;\n```\n\nIn the following cases all exports of `my-namespace.ts` are considered used:\n\n```ts title=\"index.ts\"\nimport * as NS from './my-namespace.js';\nimport send from 'stats';\n\nsend(NS);\n\nconst spread = { ...NS };\n\nconst shorthand = { NS };\n\nconst assignment = NS;\n\nconst item = [NS];\n\ntype TypeOf = typeof NS;\n\nObject.values(NS);\n\nfor (const fruit in NS) {\n  //\n}\n\nexport { NS };\n\nexport { NS as AliasedNS };\n\nexport = NS;\n```\n\nHowever, this is no longer the case when one of the properties is accessed:\n\n```ts title=\"index.js\"\nimport * as NS from './namespace.js';\n\nconst begin = NS.start;\n\nsend(NS);\n```\n\nIn this case, the `end` export will be reported as unused, even though the `NS`\nobject itself is referenced on its own as well.\n\n## Include `nsExports` and `nsTypes`\n\nTo disable the heuristic as explained above, and enforce Knip to consider each\nexport on a namespace individually, include the `nsExports` issue type:\n\n```json\n{\n  \"include\": [\"nsExports\"]\n}\n```\n\nOr use the `--include nsExports` argument from the CLI. The `nsTypes` can be\nadded as well to do the same for exported types.\n\nIncluding these _adds_ them to the report; all other issue types are still\nreported.\n","packages/docs/src/content/docs/guides/performance.md":"---\ntitle: Performance\ndescription: How to profile and speed up Knip using the `--cache`, `--performance`, and `--debug` flags, file patterns, and per-workspace linting.\n---\n\nThis page describes a few topics around Knip's performance, and how you might\nimprove it.\n\nKnip does not want to tell you how to structure files or how to write your code,\nbut it might still be good to understand inefficient patterns for Knip.\n\nUse the `--debug` and `--performance` flags to find potential bottlenecks.\n\n## Cache\n\nUse `--cache` to speed up consecutive runs.\n\n## Ignoring files\n\nFiles matching the `ignore` patterns are not excluded from the analysis. They're\njust not printed in the report. Use negated `entry` and `project` patterns to\nexclude files from the analysis.\n\nRead [configuring project files][1] for details and examples. Improving\nconfiguration may have a significant impact on performance.\n\n## Metrics\n\nUse [the `--performance` flag][2] to see how many times potentially expensive\nfunctions (e.g. `findReferences`) are invoked and how much time is spent in\nthose functions. Example usage:\n\n```sh\nknip --performance\n```\n\n## ignoreExportsUsedInFile\n\nThe [ignoreExportsUsedInFile][3] option slows down the process slightly.\nTypically, anywhere between 0.25% and 10% of total running time. To find out:\n\n```sh\nknip --performance-fn hasRefsInFile\n```\n\n## A last resort\n\nIn case Knip is unbearably slow (or even crashes), you could resort to [lint\nindividual workspaces][4].\n\n[1]: ./configuring-project-files.md\n[2]: ../reference/cli.md#--performance\n[3]: ../reference/configuration.md#ignoreexportsusedinfile\n[4]: ../features/monorepos-and-workspaces.md#filter-workspaces\n","packages/docs/src/content/docs/guides/troubleshooting.md":"---\ntitle: Troubleshooting\ndescription: Troubleshoot Knip lint issues and exceptions using exit codes, `--debug`, and `--trace` to see where exports and dependencies are used.\n---\n\nWe can distinguish two types of issues:\n\n- [Lint issues reported by Knip][1]\n- [Exceptions thrown by Knip][2]\n\nAlso see the [debug][3] and [trace][4] options below that can help to\ntroubleshoot issues.\n\n:::note[Rationale]\n\nThe JavaScript/TypeScript ecosystem has a vast amount of frameworks and tools.\nAdditionally, file locations, configuration semantics, command-line arguments\nand so on vary wildly. Files and dependencies are referenced in many ways. Knip\ntries harder than you think to cover it all.\n\nKnip is intentionally strict to maximize its potential. It may initially report\nmany unused files. However, getting this right will result in great reports and\ntidy codebases.\n\nIf it doesn't work out at first, a small change can go a long way.\n\n:::\n\n## Lint issues reported by Knip\n\nKnip reports lint issues in your codebase. See [handling issues][5] to deal with\nthe reported issues.\n\nIf you're considering filing an issue, please read [issue reproduction][6]\nfirst.\n\nExit code 1 indicates a successful run, but lint issues were found.\n\n## Exceptions thrown by Knip\n\nKnip may throw an exception, resulting in an unsuccessful run.\n\nSee [known issues][7] as it may be listed there and a workaround may be\navailable. If it isn't clear what's throwing the exception, try another run with\n`--debug` to locate the cause of the issue with more details.\n\nIf you're considering filing an issue, please read [issue reproduction][6]\nfirst.\n\nExit code 2 indicates an exception was thrown by Knip.\n\n## Debug\n\nTo better understand why Knip reports what it does, run it in debug mode by\nadding `--debug` to the command:\n\n```sh\nknip --debug\n```\n\nThis will give a lengthy output, including:\n\n- Included workspaces\n- Used configuration per workspace\n- Enabled plugins per workspace\n- Glob patterns and options followed by matching file paths\n- Plugin config file paths and found dependencies per plugin\n- Compiled non-standard source files\n\n## Trace\n\nUse `--trace` to see where exports or dependencies are used:\n\n- Use `--trace-file [path]` to output this only for the given file.\n- Use `--trace-export [name]` to output this only for the given export name.\n- Use `--trace-dependency [name]` to find where a dependency is imported\n- Use both to trace a specific named or default export of a certain file.\n\nThis works across re-exports, barrel files and workspaces. Here's an example\nscreenshot:\n\n<img src=\"/screenshots/trace-export.png\" alt=\"trace export\" class=\"mw500\" />\n\nIt's like a reversed module graph. Instead of traversing imports it goes in the\nopposite direction and shows where exports are imported.\n\nThe `--trace-dependency` accepts strings for exact matches, but if it looks like\na regex that works too:\n\n<img src=\"/screenshots/trace-dependency.png\" alt=\"trace dependency\" class=\"mw500\" />\n\nUse [--workspace \\[filter\\]][8] to filter accordingly.\n\n#### Legend\n\n| Marker | Description                         |\n| ------ | :---------------------------------- |\n| `✓`    | Referenced (not reported as unused) |\n| `✗`    | Reported as unused                  |\n| `⎆`    | Entry file                          |\n\nEach child node is prefixed with how the export is consumed: `import`,\n`importAs` (shown as `original → alias`), `importNS`, or a re-export\n(`reExport`, `reExportAs`, `reExportNS`, `reExportStar`). A `refs:` line lists\nthe references found in that file; a `members:` line shows per-member status for\nnamespaces and enums. An `[ambiguous]` line lists the competing definitions when\na name reaches the file through more than one `export *`. A name that reaches\nthe file only through `export *` is traced from its definition.\n\n## Opening an issue\n\nIf you want to open an issue, please see [issue reproduction][6].\n\n## Understanding Knip\n\nLooking to better understand how Knip works? The [entry files][9] and\n[plugins][10] explanations cover two core concepts. After this you might want to\ncheck out features like [production mode][11] and [monorepos & workspaces][12].\n\nIn a more general sense, [Why use Knip?][13] explains what Knip can do for you.\n\n## Asking for help\n\nIf you can't find your answer in any of the aforementioned resources, feel free\nto [open an issue on GitHub][14].\n\n[1]: #lint-issues-reported-by-knip\n[2]: #exceptions-thrown-by-knip\n[3]: #debug\n[4]: #trace\n[5]: ../guides/handling-issues.mdx\n[6]: ./issue-reproduction.md\n[7]: ../reference/known-issues.md\n[8]: ../reference/cli.md#--workspace-filter\n[9]: ../explanations/entry-files.md\n[10]: ../explanations/plugins.md\n[11]: ../features/production-mode.md\n[12]: ../features/monorepos-and-workspaces.md\n[13]: ../explanations/why-use-knip.md\n[14]: https://github.com/webpro-nl/knip/issues\n","packages/docs/src/content/docs/guides/using-knip-in-ci.md":"---\ntitle: Using Knip in CI\ndescription: Run Knip in continuous integration to catch regressions, with a GitHub Actions workflow example, exit codes, caching, and reporters.\n---\n\nKnip is your companion during local development. But it is even more valuable in\na continuous integration (CI) environment to prevent regressions over time. Knip\nwill notify you of unused dependencies, exports and files if you forgot to\nremove them.\n\nKnip will exit the process with code `1` if there are one or more issues.\n\n## GitHub Actions\n\nHere's an example workflow configuration for GitHub Actions:\n\n```yaml\nname: Lint project\n\non: push\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    name: Ubuntu/Node v24\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions/setup-node@v6\n        with:\n          node-version: 24\n      - name: Install dependencies\n        run: npm install --ignore-scripts\n      - name: Run knip\n        run: npm run knip\n```\n\n## Notes\n\n- Use [--cache][1] to speed up consecutive runs (default location:\n  `./node_modules/.cache/knip`).\n- See [Reporters][2] including the GitHub Actions reporter.\n- Consider running Knip twice: a default run and a [production mode][3] run.\n- See [CLI arguments → Output][4] for some relevant options such as\n  `--treat-config-hints-as-errors` and `--no-exit-code`.\n- In CI environments, the [--no-progress][5] flag is set automatically.\n\n[1]: ../reference/cli.md#--cache\n[2]: ../features/reporters.md\n[3]: ../features/production-mode.md\n[4]: ../reference/cli.md#output\n[5]: ../reference/cli.md#--no-progress\n","packages/docs/src/content/docs/guides/working-with-commonjs.md":"---\ntitle: Working with CommonJS\ndescription: Conventions for `module.exports` and `require()` so Knip detects CommonJS named and default exports correctly and avoids false positives.\n---\n\nCommonJS is the JavaScript module system using `require()` and `module.exports`\nstatements.\n\nKnip works well with CommonJS. You don't need to use ES Modules or a\n`tsconfig.json` to use Knip.\n\nThe dynamic nature of CommonJS leaves room for ambiguity: it's sometimes unclear\nwhether an export is a default or a named export (and thus how it should be\nimported). So we'll have to agree on a few conventions to prevent false\npositives. Those conventions are designed to minimize impact on existing\ncodebases, improve consistency, and ease migration to ES Modules or TypeScript.\n\nFor **named exports**, the recommendation is to assign keys to `module.exports`:\n\n```js\nconst B = function () {};\n\nmodule.exports.A = { option: true };\nmodule.exports.B = B;\n```\n\nAlternatively, assign an object with ONLY shorthand property assignments to\n`module.exports`:\n\n```js\nconst A = function () {};\nconst B = { option: true };\n\nmodule.exports = { A, B };\n```\n\nAnything else assigned to `module.exports` is considered a default export, and\nshould be imported as such.\n\nThe following **default import** of the **named exports** above will result in\nall those exports reported as unused, even when referenced like below:\n\n```js\nconst DefaultImport = require('./common.js');\nconst runtime = [DefaultImport.A, DefaultImport.B];\n```\n\nInstead, do this:\n\n```js\nconst { A, B } = require('./common.js');\nconst runtime = [A, B];\n```\n\nNot recommended per se, but the following import syntax also results in the\nnamed export `A` being used:\n\n```js\nconst runtime = [require('./common.js').A];\n```\n\nAdd a non-shorthand property to turn the named object notation into a single\n**default export**:\n\n```js\nconst A = function () {};\nconst B = { option: true };\n\nmodule.exports = { __esModule: true, A, B };\n```\n\nThe `__esModule` key could be named differently (but makes sense given it's an\ninformal \"CJS/ESM interop\" standard amongst compilers and bundlers).\n","packages/docs/src/content/docs/overview/configuration.md":"---\ntitle: Configuration\ndescription: config\n---\n\n## Defaults\n\nKnip has good defaults and aims for \"zero config\". Here's a simplified version\nof the default `entry` and `project` values:\n\n```json\n{\n  \"entry\": [\"index.{js,ts}\", \"src/index.{js,ts}\"],\n  \"project\": [\"**/*.{js,ts}\"]\n}\n```\n\nEntry files are the starting point for Knip to find more source files and\nexternal dependencies.\n\n## Location\n\nBy default, Knip will look for a configuration file with the following names:\n\n- `knip.json`\n- `knip.jsonc`\n- `.knip.json`\n- `.knip.jsonc`\n- `knip.ts`\n- `knip.js`\n- `knip.config.ts`\n- `knip.config.js`\n- `package.json` (in the `\"knip\"` property)\n\nIf you want to use a custom file name or path, use the `--config` flag:\n\n```sh\nknip --config path/to/knip.json\n```\n\n## Customize\n\nYour project structure may not match the default `entry` and `project` files.\nHere's an example custom configuration to include `.js` files in the `scripts`\nfolder:\n\n```json title=\"knip.json\"\n{\n  \"$schema\": \"https://unpkg.com/knip@6/schema.json\",\n  \"entry\": [\"src/index.ts\", \"scripts/{build,create}.js\"],\n  \"project\": [\"src/**/*.ts\", \"scripts/**/*.js\"]\n}\n```\n\nThe set of `project` files determines the analysis scope. Use negated `project`\npatterns to exclude files from the analysis. See [configuring project files][1]\nfor details.\n\nThe values you set override the default values, they are not merged.\n\n:::tip\n\nBe specific with `entry` files. Minimize the number of entry files and wildcards\nfor better results.\n\nPlugins are enabled automatically, and their entry files are added\nautomatically. Such as for Next.js, Astro, Remix, Vitest, Playwright and many\nmore.\n\n:::\n\nKnip looks for entry files in many places. Learn more in the next page about\n[entry files][2].\n\n## Configuration Options\n\nSee [configuration file options][3].\n\nUse JavaScript or TypeScript in a [dynamic configuration file][4].\n\n## What's next?\n\nThe best way to understand Knip and what it can do for you is to read the pages\nin the \"Understanding Knip\" sections, starting with [entry files][2].\n\nWant to learn more about some of the main features?\n\n- Working with [monorepos & workspaces][5].\n- Learn more about [production mode][6].\n\nHaving trouble configuring Knip?\n\n- [Configuring project files][1]\n- [Troubleshooting][7]\n\nSearch this website using the bar at the top (`Ctrl+K` or `⌘+K`).\n\n[1]: ../guides/configuring-project-files.md\n[2]: ../explanations/entry-files.md\n[3]: ../reference/configuration.md\n[4]: ../reference/dynamic-configuration.mdx\n[5]: ../features/monorepos-and-workspaces.md\n[6]: ../features/production-mode.md\n[7]: ../guides/troubleshooting.md\n","packages/docs/src/content/docs/overview/features.md":"---\ntitle: Features\ndescription: Table of Knip capabilities including auto-fix, cache, compilers, monorepos, plugins, reporters, production mode, trace and watch mode.\n---\n\nOverview of capabilities in support of the core feature: find many [types of\nissues][1].\n\nAlso see [related tooling][2].\n\n## Overview\n\n| Name                         | Description or example                                                |\n| :--------------------------- | :-------------------------------------------------------------------- |\n| [Auto-fix][3]                | Use `--fix` to auto-fix issues                                        |\n| [Cache][4]                   | Use `--cache` to speed up consecutive runs                            |\n| [Catalog][5]                 | Report & fix unused catalog entries                                   |\n| [CommonJS][6]                | CommonJS is still widely used & supported, but conditions apply       |\n| [Compilers][7]               | Support for Astro, MDX, Svelte, Vue and custom compilers              |\n| Configuration hints          | Display configuration hints to keep `knip.json` tidy                  |\n| [Debug][8]                   | Use `--debug` for troubleshooting                                     |\n| [Filters][9]                 | Exclude or focus on specific issue types                              |\n| [Format][10]                 | Use `--format` with `--fix` to auto-format modified files             |\n| [JSDoc tags][11]             | Tag and exclude specific exports from the report                      |\n| [Memory usage][12]           | Use `--memory` for detailed memory usage insights                     |\n| [Monorepos][13]              | Workspaces are first-class citizen                                    |\n| [Performance][14]            | Use `--performance` for detailed timing insights                      |\n| [Plugins][15]                | Over 100 plugins with custom entry paths and config parsing           |\n| [Plugins: inputs][16]        | Inputs are an affective mechanism to add entries, dependencies & more |\n| [Plugins: CLI arguments][17] | Tool-specific CLI argument parsing make plugins go the extra mile     |\n| [Preprocessors][18]          | Preprocess issues before being reported                               |\n| [Production mode][19]        | Use `--production` to lint only production code                       |\n| [Reporters][20]              | Choose from many built-in reporters or use your own                   |\n| [Rules][21]                  | Exclude or focus on specific issue types                              |\n| [Script parser][22]          | Shell scripts and `package.json` contain entry paths and dependencies |\n| [Source mapping][23]         | Map `dist` files back to `src` files                                  |\n| [Strict mode][24]            | Use `--strict` to tighten and lint only production `dependencies`     |\n| [Trace][25]                  | Trace exports to find where they are used                             |\n| [Watch mode][26]             | Use `--watch` for live updates of unused files and exports            |\n| [Workspace][27]              | Use `--workspace` to filter workspaces in a monorepo                  |\n\n[1]: ../reference/issue-types.md\n[2]: ../reference/related-tooling.md\n[3]: ../features/auto-fix.mdx\n[4]: ../reference/cli.md#--cache\n[5]: ../features/catalogs.md\n[6]: ../guides/working-with-commonjs.md\n[7]: ../features/compilers.md\n[8]: ../guides/troubleshooting.md#debug\n[9]: ../features/rules-and-filters.md#filters\n[10]: ../features/auto-fix.mdx#format\n[11]: ../reference/jsdoc-tsdoc-tags.md\n[12]: ../reference/cli.md#--memory\n[13]: ../features/monorepos-and-workspaces.md\n[14]: ../reference/cli.md#--performance\n[15]: ../explanations/plugins.md\n[16]: ../writing-a-plugin/inputs.md\n[17]: ../writing-a-plugin/argument-parsing.md\n[18]: ../features/reporters.md#preprocessors\n[19]: ../features/production-mode.md\n[20]: ../features/reporters.md\n[21]: ../features/rules-and-filters.md#rules\n[22]: ../features/script-parser.md\n[23]: ../features/source-mapping.md\n[24]: ../features/production-mode.md#strict-mode\n[25]: ../guides/troubleshooting.md#trace\n[26]: ../reference/cli.md#--watch\n[27]: ../features/monorepos-and-workspaces.md#filter-workspaces\n","packages/docs/src/content/docs/overview/screenshots-videos.md":"---\ntitle: Screenshots & videos\ndescription: Screenshots and videos showing Knip watch mode, auto-fix, export and file trace, and performance output in action.\n---\n\n## Watch & auto-fix\n\nThis video demonstrates using the `--watch` and `--fix` options inside Visual\nStudio Code:\n\n<video controls width=\"500\">\n  <source src=\"/screenshots/watch-fix.mp4\" type=\"video/mp4\" />\n\n  <source src=\"/screenshots/watch-fix.webm\" type=\"video/webm\" />\n</video>\n\nThis works in any terminal. See [--watch][1] and [auto-fix][2] for more details.\n\n## Trace\n\nHere's an example screenshot that traces the `mapIterator` export in the\nTypeScript codebase:\n\n<img src=\"/screenshots/trace-export.png\" alt=\"trace export\" class=\"mw500\" />\n\nInspect complicated import and re-export chains at a glance:\n\n<img src=\"/screenshots/trace-file.png\" alt=\"trace file\" class=\"mw500\" />\n\nSee [Trace][3] for more details.\n\n## Performance\n\nAn example screenshot showing `--performance` output for the Knip codebase:\n\n<img src=\"/screenshots/performance.png\" alt=\"performance\" class=\"mw500\" />\n\nAlso see [--performance][4].\n\n[1]: ../reference/cli.md#--watch\n[2]: ../features/auto-fix.mdx\n[3]: ../guides/troubleshooting.md#trace\n[4]: ../reference/cli.md#--performance\n","packages/docs/src/content/docs/reference/cli.md":"---\ntitle: CLI Arguments\ndescription: Every Knip command-line flag, grouped by mode, scope, fix, output and troubleshooting, with shortcuts and exit codes.\n---\n\n## General\n\n### `--help`\n\nShortcut: `-h`\n\nPrints a summary of this page.\n\n### `--version`\n\nShortcut: `-V`\n\nPrint the version number.\n\n### `--no-progress`\n\nShortcut: `-n`\n\nDon't show dynamic progress updates. Progress is automatically disabled in CI\nenvironments.\n\n### `--config [file]`\n\nUse an alternative path for the configuration file. Default locations:\n\n- `knip.json`\n- `knip.jsonc`\n- `.knip.json`\n- `.knip.jsonc`\n- `knip.ts`\n- `knip.js`\n- `knip.config.ts`\n- `knip.config.js`\n- `package.json#knip`\n\nShortcut: `-c`\n\n### `--use-tsconfig-files`\n\nPer workspace, take project files from `tsconfig.json` (`files` + `include`,\nminus `exclude`, `node_modules` and `outDir`) and from the tsconfig files in its\n`references` instead of the `project` patterns. Workspaces without a\n`tsconfig.json` fall back to their `project` patterns.\n\nImplicitly enabled in the [editor extension, MCP server and language server][1]\nwhen there is no Knip configuration file.\n\n### `--tsConfig [file]`\n\nShortcut: `-t`\n\nUse an alternative path for the TypeScript configuration file.\n\nUsing `-t jsconfig.json` is also supported.\n\nDefault location: `tsconfig.json`\n\n### `knip-bun`\n\nRun Knip using the Bun runtime (instead of Node.js + jiti).\n\n```shell\nknip-bun\n```\n\nThis is equal to `bunx --bun knip`\n\nRequires [Bun][2] to be installed. Also see [known issues][3] for the type of\nissues this might help with.\n\n### NO\\_COLOR\n\nThe built-in reporters use the [NO\\_COLOR][4] friendly [picocolors][5]:\n\n```sh\nNO_COLOR=1 knip\n```\n\n### KNIP\\_DISABLE\\_RAW\\_TRANSFER\n\nSet `KNIP_DISABLE_RAW_TRANSFER=1` to disable oxc-parser raw transfer and use the\nnormal parser path.\n\n## Mode\n\n### `--cache`\n\nEnable caching.\n\nConsecutive runs are 10-40% faster as the results of file analysis (AST\ntraversal) are cached. Conservative. Cache strategy based on file meta data\n(modification time + file size).\n\nSee [stale cache results][6] for limitations and workarounds.\n\n### `--cache-location`\n\nProvide alternative cache location.\n\nDefault location: `./node_modules/.cache/knip`\n\n### `--include-entry-exports`\n\nWhen a repository is self-contained or private, you may want to include entry\nfiles when reporting unused exports:\n\n```sh\nknip --include-entry-exports\n```\n\nAlso see [includeEntryExports][7].\n\n### `--no-gitignore`\n\nIgnore `.gitignore` files.\n\n### `--production`\n\nShortcut: `-p`\n\nLint only production source files. This excludes:\n\n- entry files defined by plugins:\n  - test files\n  - configuration files\n  - Storybook stories\n- `devDependencies` from `package.json`\n\nRead more at [Production Mode][8].\n\n### `--strict`\n\nShortcut: `-s`\n\nIsolate workspaces and consider only direct dependencies. Implies [production\nmode][9].\n\nRead more at [Production Mode][8].\n\n### `--watch`\n\nShortcut: `-w`\n\nWatch current directory, and update reported issues when a file is modified,\nadded or deleted.\n\nWatch mode focuses on imports and exports in source files. During watch mode,\nchanges in `package.json` or `node_modules` may not cause an updated report.\n\n## Scope\n\n### `--workspace [filter]`\n\nSelect one or multiple workspaces (including its ancestor, dependency and\ndependent workspaces). The default behavior is to lint all configured\nworkspaces.\n\nShortcut: `-W`\n\nSee [filter workspaces][10] for more details and examples.\n\n### `--directory [dir]`\n\nShortcut: `-D`\n\nDefault: `cwd` (current directory)\n\nRun the process from a different directory.\n\n### `--exclude`\n\nExclude provided issue types from report. Can be comma-separated or repeated.\n\nExample:\n\n```sh\nknip --exclude enumMembers\n```\n\n### `--include`\n\nReport only provided issue types. Can be comma-separated or repeated.\n\nExample:\n\n```sh\nknip --include files,dependencies\nknip --include files --include dependencies\n```\n\n`nsExports` and `nsTypes` are [off by default][11]; including only those _adds_\nthem to the default report instead of narrowing it.\n\nAvailable [issue types][12] when filtering output using `--include` or\n`--exclude`:\n\n- `files`\n- `dependencies`\n- `unlisted`\n- `binaries`\n- `unresolved`\n- `exports`\n- `nsExports`\n- `types`\n- `nsTypes`\n- `enumMembers`\n- `namespaceMembers`\n- `duplicates`\n- `catalog`\n- `catalogReferences`\n\n### `--dependencies`\n\nShortcut to report only all types of dependency issues:\n\n```sh\n--include dependencies,unlisted,binaries,unresolved,catalog,catalogReferences\n```\n\n### `--exports`\n\nShortcut to report only all types of export issues:\n\n```sh\n--include exports,nsExports,types,nsTypes,enumMembers,namespaceMembers,duplicates\n```\n\n### `--files`\n\nShortcut to report only file issues:\n\n```sh\n--include files\n```\n\n### `--cycles`\n\nShortcut to report only circular dependencies:\n\n```sh\n--include cycles\n```\n\nAlso see the [cycles reporter][13].\n\n### `--tags`\n\nExports can be tagged with known or arbitrary JSDoc/TSDoc tags:\n\n```ts\n/**\n * Description of my exported value\n *\n * @type number\n * @internal Important matters\n * @lintignore\n */\nexport const myExport = 1;\n```\n\nAnd then include (`+`) or exclude (`-`) these tagged exports from the report\nlike so:\n\n```shell\nknip --tags=-lintignore,-internal\nknip --tags=+custom\n```\n\nThis way, you can either focus on or ignore specific tagged exports with tags\nyou define yourself. This also works for individual enum and namespace members.\n\nThe default directive is `+` (include) and the `@` prefix is ignored, so the\nnotation below is valid and will report only exports tagged `@lintignore` or\n`@internal`:\n\n```shell\nknip --tags @lintignore --tags @internal\n```\n\n## Fix\n\n### `--fix`\n\nShortcut: `-f`\n\nRead more at [auto-fix][14].\n\n### `--fix-type`\n\nFix only issues of type, can be comma-separated or repeated.\n\nMore info about fixable types at [issue types][12]\n\n### `--allow-remove-files`\n\nAllow Knip to remove files (with `--fix`).\n\n### `--format`\n\nShortcut: `-F`\n\nFormat modified files after `--fix` using the local formatter.\n\n## Output\n\n### `--preprocessor [preprocessor]`\n\nPreprocess the results before providing it to the [reporter(s)][15].\n\nCan be repeated. Examples:\n\n```sh\nknip --preprocessor ./my-preprocessor.ts\n```\n\n```sh\nknip --preprocessor preprocessor-package\n```\n\nPreprocessors can also be configured in the Knip configuration file.\n\nAlso see [Reporters & Preprocessors][16].\n\n### `--preprocessor-options [json]`\n\nPass extra options to the preprocessor as JSON string.\n\n```sh\nknip --preprocessor ./preproc.ts --preprocessor-options '{\"key\":\"value\"}'\n```\n\n### `--reporter [reporter]`\n\nAvailable reporters:\n\n- `symbols` (default)\n- `compact`\n- `codeowners`\n- `json`\n- `codeclimate`\n- `markdown`\n- `disclosure`\n- `github-actions`\n- `sarif`\n\nCan be repeated. Example:\n\n```sh\nknip --reporter compact\n```\n\nAlso see [Reporters & Preprocessors][16].\n\n### `--reporter-options [json]`\n\nPass extra options to the reporter (as JSON string):\n\nExample:\n\n```sh\nknip --reporter codeowners --reporter-options '{\"path\":\".github/CODEOWNERS\"}'\n```\n\n### `--no-config-hints`\n\nSuppress configuration hints.\n\n### `--no-tag-hints`\n\nSuppress tag hints.\n\n### `--treat-config-hints-as-errors`\n\nExit with non-zero exit code (`1`) if there are any configuration hints.\n\n### `--treat-tag-hints-as-errors`\n\nExit with non-zero exit code (`1`) if there are any tag hints.\n\n### `--max-issues`\n\nMaximum number of issues before non-zero exit code. Default: `0`\n\n### `--max-show-issues`\n\nMaximum number of issues per type to display (does not affect exit code).\n\n### `--no-exit-code`\n\nExit with code zero (`0`) even when there are lint issues. Config load failures\nand internal errors still exit with code `2`.\n\nThe default exit codes:\n\n| Code | Description                                                                                     |\n| :--: | :---------------------------------------------------------------------------------------------- |\n| `0`  | Knip ran successfully, no lint issues                                                           |\n| `1`  | Knip ran successfully, but there is at least one lint issue                                     |\n| `2`  | Knip did not run successfully due to bad input, a plugin config load error or an internal error |\n\n## Troubleshooting\n\n### `--debug`\n\nShortcut: `-d`\n\nShow [debug output][17].\n\n### `--memory`\n\n```txt frame=terminal\nknip --memory\n\n(results)\n\n # heapUsed  heapTotal  freemem\n-- --------  ---------  -------\n 0    42.09      70.91  2251.00\n 1   927.04    1042.58  1166.47\n 2   973.29    1047.33  1160.92\n 3   971.54    1079.83  1121.66\n 4   997.80    1080.33  1120.34\n 5  1001.88    1098.08  1100.72\n 6  1038.69    1116.58  1100.72\n 7  1082.12    1166.33  1100.72\n 8  1145.46    1224.50  1100.72\n 9  1115.82    1240.25  1100.72\n10  1182.35    1249.75   973.05\n11   637.32    1029.17   943.63\n12   674.30    1029.33   943.39\n13   682.24    1029.33   941.63\n14   707.70    1029.33   937.48\n\nTotal running time: 4.3s\n```\n\n### `--memory-realtime`\n\nUse this if Knip crashes to still see memory usage info over time:\n\n```txt frame=terminal\nknip --memory-realtime\n\n#  heapUsed  heapTotal  freemem\n-  --------  ---------  -------\n0     42.09      70.91  2251.00\n1    927.04    1042.58  1166.47\n...mem info keeps being logged...\n\n(results)\n```\n\n### `--performance`\n\nUse this flag to get the count and execution time of potentially expensive\nfunctions in a table. Example:\n\n```txt frame=terminal\n$ knip --performance\n\n(results)\n\nName                           size  min       max       median    sum\n-----------------------------  ----  --------  --------  --------  --------\nfindReferences                  648     84.98   7698.61     96.41  70941.70\ncreateProgram                     2   6295.84   7064.68   6680.26  13360.52\nglob                              6      0.05    995.78    513.82   3150.87\nfindESLintDependencies            2      0.01     74.41     37.21     74.41\nfindGithubActionsDependencies     6      0.16     12.71      0.65     23.45\nfindBabelDependencies             2      0.00     38.75     19.37     38.75\n...\n\nTotal running time: 5s\n```\n\n- `name`: the internal Knip function name\n- `size`: number of function invocations\n- `min`: the fastest invocation\n- `max`: the slowest invocation\n- `median`: the median invocation\n- `sum` the accumulated time of all invocations\n\nThis is not yet available in Bun, since it does not support\n`performance.timerify` ([GitHub issue][18]).\n\n### `--duration`\n\nShortcut: `-u`\n\nPrint total running time. Zero overhead — no `timerify` instrumentation, unlike\n`--performance`.\n\n### `--performance-fn`\n\nLimit the output of `--performance` to a single function to minimize the\noverhead of the `timerify` Node.js built-in and focus on that function alone:\n\n```txt frame=terminal\n$ knip --performance-fn resolveSync\n\n(results)\n\nName         size   min   max   median   sum\n-----------  -----  ----  ----  ------  ------\nresolveSync  66176  0.00  5.69    0.00  204.85\n\nTotal running time: 12.9s\n```\n\n### `--trace`\n\nTrace exports to see where they are imported.\n\nAlso see [Trace][19].\n\n### `--trace-dependency [name]`\n\nTrace package or binary name to see where it's referenced. Implies\n[--trace][20].\n\n### `--trace-export [name]`\n\nTrace export name to see where it's imported. Implies [--trace][20].\n\n### `--trace-file [path]`\n\nTrace file to see where its exports are imported. Implies [--trace][20].\n\n[1]: ./integrations.md\n[2]: https://bun.sh\n[3]: ../reference/known-issues.md\n[4]: https://no-color.org/\n[5]: https://www.npmx.dev/package/picocolors\n[6]: ./known-issues.md#stale-cache-results\n[7]: ./configuration.md#includeentryexports\n[8]: ../features/production-mode.md\n[9]: #--production\n[10]: ../features/monorepos-and-workspaces.md#filter-workspaces\n[11]: ../guides/namespace-imports.md\n[12]: ./issue-types.md\n[13]: ../features/reporters.md#cycles\n[14]: ../features/auto-fix.mdx\n[15]: #--reporter-reporter\n[16]: ../features/reporters.md\n[17]: ../guides/troubleshooting.md#debug\n[18]: https://github.com/oven-sh/bun/issues/9271\n[19]: ../guides/troubleshooting.md#trace\n[20]: #--trace\n","packages/docs/src/content/docs/reference/configuration-hints.md":"---\ntitle: Configuration Hints\ndescription: The configuration hints Knip emits to keep your config tidy, what each one means, and how to resolve it.\n---\n\nKnip emits configuration hints to help keep your configuration file tidy and\nreduce drift.\n\nThey're warnings by default, not lint findings. But addressing the hints might\nimprove results significantly. The hints on this page are sorted by\nimpact/importance (most impactful first).\n\nUse [`--treat-config-hints-as-errors`][1] or [`treatConfigHintsAsErrors`][2] to\nmake any configuration hint an error and result in a non-zero exit code to fail\nCI.\n\n## Unconfigured projects\n\nToo many unused files in a single workspace-codebase, caused by a missing\nconfiguration file or incomplete configuration:\n\n```\nCreate knip.json configuration file, and add entry and/or refine project files (42 unused files)\n```\n\nOr if you have a config file:\n\n```\nAdd entry and/or refine project files (42 unused files)\n```\n\n**Solution**: Add and refine `entry` and/or `project` patterns.\n\nRelated resources:\n\n- [Configuration][3]\n- [Monorepos & Workspaces][4]\n\n## Unconfigured workspaces\n\nToo many unused files in a monorepo, caused by a missing configuration file or\nincomplete configuration:\n\n```\nCreate knip.json configuration file with workspaces[\"packages/app\"] object (42 unused files)\n```\n\nOr if you have a config file:\n\n```\nAdd entry and/or refine project files in workspaces[\"packages/app\"] (42 unused files)\n```\n\n**Solution**: add a `workspaces` object to configuration. Add and refine `entry`\nand/or `project` patterns. For instance, the example message translates to\nconfiguration like this:\n\n```json\n{\n  \"workspaces\": {\n    \"packages/app\": {\n      \"entry\": [\"src/App.tsx\"],\n      \"project\": [\"src/**/*.ts\"]\n    }\n  }\n}\n```\n\nRelated resources:\n\n- [Configuring Project Files][5]\n- [Monorepos & Workspaces][4]\n\n## Top-level entry/project\n\nIn monorepos, Knip uses only `entry` and `project` under `workspaces`. The\ntop-level keys with the same name are ignored.\n\n```\nRemove, or move unused top-level entry to one of \"workspaces\"\nRemove, or move unused top-level project to one of \"workspaces\"\n```\n\n**Solution**: Remove top-level `entry` and `project` keys, use these options in\n`workspaces` instead.\n\n```jsonc\n{\n  \"entry\": [\"src/App.tsx\"], // move entry/project from here... ↴\n  \"project\": [\"src/**/*.ts\"],\n  \"workspaces\": {\n    \".\": {\n      \"entry\": [\"src/App.tsx\"], // ...to the correct workspace(s) ↲\n      \"project\": [\"src/**/*.ts\"],\n    },\n  },\n}\n```\n\n## Stale workspace configuration\n\nA key in the `workspaces` configuration matches no workspace in the project, for\ninstance after the workspace was removed or renamed.\n\n```\nRemove from workspaces\n```\n\n**Solution**: Remove the stale key from `workspaces`, or correct its path.\n\n## Unused entry in ignore group\n\nAn entry of an ignore list is no longer needed, remove it.\n\n```\nRemove from ignoreWorkspaces\nRemove from ignoreDependencies\nRemove from ignoreBinaries\nRemove from ignoreUnresolved\n```\n\n**Solution**: Remove the entry from the array.\n\n## Useless patterns\n\nA glob pattern in `entry` or `project` does not match any files.\n\n```\nRefine entry pattern (no matches)\nRefine project pattern (no matches)\n```\n\n**Solution**: Refine or remove the `entry` or `project` entry.\n\n## Redundant patterns\n\nA glob/pattern is redundant, because it's already covered by defaults or added\nby an enabled plugin.\n\n```\nRemove redundant entry pattern\nRemove redundant project pattern\n```\n\n**Solution**: Remove the `entry` or `project` entry.\n\n## Missing package entry file\n\n```\nPackage entry file not found\n```\n\n**Solution**: Refine or remove the entry in `package.json`.\n\n[1]: ./cli.md#--treat-config-hints-as-errors\n[2]: ./configuration.md#treatconfighintsaserrors\n[3]: ../overview/configuration.md\n[4]: ../features/monorepos-and-workspaces.md\n[5]: ../guides/configuring-project-files.md\n","packages/docs/src/content/docs/reference/configuration.md":"---\ntitle: Configuration\ndescription: Every knip.json option, including entry, project, paths, workspaces, plugins, rules, tags, ignores and compilers.\n---\n\nThis page lists all configuration file options.\n\n## File Types\n\n### JSON Schema\n\nA `$schema` field is a URL that you put at the top of your JSON file. This\nallows you to get red squiggly lines inside of your IDE when you make a typo or\nprovide an otherwise invalid configuration option.\n\nIn JSON, use the provided JSON schema:\n\n```json title=\"knip.json\"\n{\n  \"$schema\": \"https://unpkg.com/knip@6/schema.json\"\n}\n```\n\n### JSONC\n\nIn JSONC, use the provided JSONC schema:\n\n```json title=\"knip.jsonc\"\n{\n  \"$schema\": \"https://unpkg.com/knip@6/schema-jsonc.json\"\n}\n```\n\nUse JSONC if you want to use comments and/or trailing commas.\n\n### TypeScript\n\nSee [dynamic configuration][1] about dynamic and typed configuration files.\n\n## Project\n\n### `entry`\n\nArray of glob patterns to find entry files. Prefix with `!` for negation.\nExample:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts\", \"scripts/*.ts\", \"!scripts/except-this-one.ts\"]\n}\n```\n\nAlso see [configuration][2] and [entry files][3].\n\n### `project`\n\nArray of glob patterns to find project files. Example:\n\n```json title=\"knip.json\"\n{\n  \"project\": [\"src/**/*.ts\", \"scripts/**/*.ts\"]\n}\n```\n\nAlso see [configuration][2] and [entry files][3].\n\n### `paths`\n\nTools like TypeScript, webpack and Babel support import aliases in various ways.\nKnip automatically includes `compilerOptions.paths` from the TypeScript\nconfiguration, but does not automatically use other types of import aliases.\nThey can be configured manually:\n\n```json title=\"knip.json\"\n{\n  \"paths\": {\n    \"@lib\": [\"./lib/index.ts\"],\n    \"@lib/*\": [\"./lib/*\"]\n  }\n}\n```\n\nEach workspace can have its own `paths` configured. Knip `paths` follow the\nTypeScript semantics:\n\n- Path values are an array of relative paths.\n- Paths without an `*` are exact matches.\n\n## Workspaces\n\n### `workspaces`\n\nConfigure `entry`, `project`, plugins and most other options per workspace. Keys\nare workspace directories (globs allowed); the root workspace is `\".\"`.\n\n```json title=\"knip.json\"\n{\n  \"workspaces\": {\n    \".\": {\n      \"entry\": [\"scripts/*.ts\"],\n      \"project\": [\"scripts/**/*.ts\"]\n    },\n    \"packages/*\": {\n      \"entry\": [\"src/index.ts\"],\n      \"project\": [\"src/**/*.ts\"]\n    }\n  }\n}\n```\n\nWorkspaces configured here that aren't already defined in the root\n`package.json` (or `pnpm-workspace.yaml`) are added to the analysis. Also see\n[Monorepos & Workspaces][4].\n\nIndividual workspace configurations may contain all other options listed on this\npage, except for the following root-only options:\n\n- `exclude` / `include`\n- `ignoreWorkspaces`\n- `workspaces`\n\nWorkspaces can't be nested in a Knip configuration, but they can be nested in a\nmonorepo folder structure.\n\nAlso see [Monorepos and workspaces][4].\n\n## Plugins\n\nThere are a few options to modify the behavior of a plugin:\n\n- Override a plugin's `config` or `entry` location\n- Force-enable a plugin by setting its value to `true`\n- Disable a plugin by setting its value to `false`\n\n```json title=\"knip.json\"\n{\n  \"mocha\": {\n    \"config\": \"config/mocha.config.js\",\n    \"entry\": [\"**/*.spec.js\"]\n  },\n  \"playwright\": true,\n  \"webpack\": false\n}\n```\n\nIt should be rarely necessary to override the `entry` patterns, since plugins\nalso read custom entry file patterns from the tooling configuration (see\n[Plugins → entry files][5]).\n\nPlugin configuration can be set on root and on a per-workspace level. If enabled\non root level, it can be disabled on workspace level by setting it to `false`\nthere, and vice versa.\n\nAlso see [Plugins][6].\n\n## Rules & Filters\n\n### `rules`\n\nSee [Rules & Filters][7].\n\n### `include`\n\nSee [Rules & Filters][7].\n\n### `exclude`\n\nSee [Rules & Filters][7].\n\n### `tags`\n\nExports can be tagged with known or arbitrary JSDoc/TSDoc tags:\n\n```ts\n/**\n * Description of my exported value\n *\n * @type number\n * @internal Important matters\n * @lintignore\n */\nexport const myExport = 1;\n```\n\nAnd then include (`+`) or exclude (`-`) these tagged exports from the report\nlike so:\n\n```json\n{\n  \"tags\": [\"-lintignore\"]\n}\n```\n\nThis way, you can either focus on or ignore specific tagged exports with tags\nyou define yourself. This also works for individual enum and namespace members.\n\nThe default directive is `+` (include) and the `@` prefix is ignored, so the\nnotation below is valid and will report only exports tagged `@lintignore` or\n`@internal`:\n\n```json\n{\n  \"tags\": [\"@lintignore\", \"@internal\"]\n}\n```\n\n:::caution\n\nTags must not contain hyphens or plus symbols, so it is recommended to stick to\nletters and avoid snake-case.\n\n:::\n\nAlso see [JSDoc & TSDoc Tags][8].\n\n### `preprocessor`\n\nPreprocess the results before providing them to the reporter(s). Can be a single\npreprocessor or an array of preprocessors. Each value is a path to a local file\nor an npm package name.\n\n```json title=\"knip.json\"\n{\n  \"preprocessor\": [\"./first.ts\", \"./second.ts\"]\n}\n```\n\nAlso see [Preprocessors][9].\n\n### `preprocessorOptions`\n\nExtra options to pass to the preprocessor.\n\n```json title=\"knip.json\"\n{\n  \"preprocessor\": \"./my-preprocessor.ts\",\n  \"preprocessorOptions\": { \"key\": \"value\" }\n}\n```\n\n### `treatConfigHintsAsErrors`\n\nExit with non-zero code (1) if there are any configuration hints.\n\n```json title=\"knip.json\"\n{\n  \"treatConfigHintsAsErrors\": true\n}\n```\n\n### `treatTagHintsAsErrors`\n\nExit with non-zero code (1) if there are any tag hints.\n\n```json title=\"knip.json\"\n{\n  \"treatTagHintsAsErrors\": true\n}\n```\n\n## Ignore Issues\n\n### `ignore`\n\n:::tip\n\nPlease read [configuring project files][10] before using the `ignore` option.\n\n:::\n\nAvoid `ignore` patterns. There is almost always a better solution:\n\n- Follow up on configuration hints (if there are any).\n- Fine-tune `entry` and `project` patterns.\n- Use [production mode][11].\n- Other `ignore*` options.\n\n**NOTE**: An exception to the rule: to _temporarily_ report only issues in files\nthat match the negated `ignore` pattern:\n\n```json title=\"knip.json\"\n{\n  \"ignore\": [\"!src/dir/**\"]\n}\n```\n\n### `ignoreFiles`\n\nArray of glob patterns of files to exclude from the \"Unused files\" section only.\n\nUnlike `ignore`, which suppresses all issue types for matching files,\n`ignoreFiles` only affects the `files` issue type. Use this when a file should\nremain analyzed for other issues (exports, dependencies, unresolved) but should\nnot be considered for unused file detection.\n\n```json title=\"knip.json\"\n{\n  \"ignoreFiles\": [\"src/generated/**\", \"fixtures/**\"]\n}\n```\n\nSuffix an item with `!` to enable it only in production mode.\n\n### `ignoreBinaries`\n\nExclude binaries that are used but not provided by any dependency from the\nreport. Value is an array of binary names or regular expressions. Example:\n\n```json title=\"knip.json\"\n{\n  \"ignoreBinaries\": [\"zip\", \"docker-compose\", \"pm2-.+\"]\n}\n```\n\nActual regular expressions can be used in dynamic configurations:\n\n```ts title=\"knip.ts\"\nexport default {\n  ignoreBinaries: [/^pm2-.+/],\n};\n```\n\nSuffix an item with `!` to enable it only in production mode.\n\n### `ignoreGlobalBinaries`\n\nDefaults to `true`, suppressing missing-binary reports for common global commands such as `git` and `docker`. Set it to `false` to report these commands where a project dependency is expected:\n\n```json title=\"knip.json\"\n{\n  \"ignoreGlobalBinaries\": false,\n  \"ignoreBinaries\": [\"git\"]\n}\n```\n\nDependencies that provide a referenced binary still count as used, and `ignoreBinaries` still applies. Optional commands, including bare CI/hook commands and commands installed on demand, produce no missing-binary reports. Workspaces inherit the top-level value unless they override it.\n\n### `ignoreDependencies`\n\nArray of package names to exclude from the report. Regular expressions allowed.\nExample:\n\n```json title=\"knip.json\"\n{\n  \"ignoreDependencies\": [\"hidden-package\", \"@org/.+\"]\n}\n```\n\nActual regular expressions can be used in dynamic configurations:\n\n```ts title=\"knip.ts\"\nexport default {\n  ignoreDependencies: [/@org\\/.*/, /^lib-.+/],\n};\n```\n\nSuffix an item with `!` to enable it only in production mode.\n\nAlso see [Unused dependencies][12].\n\n### `ignoreMembers`\n\nArray of enum and namespace members to exclude from the report. Regular\nexpressions allowed. Example:\n\n```json title=\"knip.json\"\n{\n  \"ignoreMembers\": [\"render\", \"on.+\"]\n}\n```\n\nActual regular expressions can be used in dynamic configurations.\n\n### `ignoreUnresolved`\n\nArray of specifiers to exclude from the report. Regular expressions allowed.\nExample:\n\n```json title=\"knip.json\"\n{\n  \"ignoreUnresolved\": [\"ignore-unresolved-import\", \"#virtual/.+\"]\n}\n```\n\nActual regular expressions can be used in dynamic configurations:\n\n```ts title=\"knip.ts\"\nexport default {\n  ignoreUnresolved: [/^#virtual\\/.+/],\n};\n```\n\n### `ignoreWorkspaces`\n\nArray of workspaces to ignore, globs allowed. Example:\n\n```json title=\"knip.json\"\n{\n  \"ignoreWorkspaces\": [\n    \"packages/go-server\",\n    \"packages/flat/*\",\n    \"packages/deep/**\"\n  ]\n}\n```\n\nSuffix an item with `!` to enable it only in production mode.\n\nPrefix an item with `!` to override an earlier wildcard.\n\n### `ignoreIssues`\n\nIgnore specific issue types for specific file patterns. Keys are glob patterns\nand values are arrays of issue types to ignore for matching files. This allows\nignoring specific issues (like unused exports) in generated files while still\nreporting other issues in those same files.\n\n```json title=\"knip.json\"\n{\n  \"ignoreIssues\": {\n    \"src/generated/**\": [\"exports\", \"types\"],\n    \"**/*.generated.ts\": [\"exports\", \"enumMembers\", \"namespaceMembers\"]\n  }\n}\n```\n\n### `cycles`\n\nConfigure circular dependency (`cycles`) detection.\n\nSet `dynamicImports` to include dynamic `import()` edges, which are excluded by\ndefault (a dynamic import defers evaluation, so it does not cause the\ninitialization hazard cycles are meant to catch).\n\nUse `allow` to accept specific cycles by exact path while keeping other `cycles`\nissues enabled. Path entries are relative to the project root and omit the\nclosing repeat of the first file.\n\n```json title=\"knip.json\"\n{\n  \"cycles\": {\n    \"dynamicImports\": true,\n    \"allow\": [[\"src/i18n/index.ts\", \"src/i18n/middleware.ts\"]]\n  }\n}\n```\n\n## Exports\n\n### `ignoreExportsUsedInFile`\n\nIn files with multiple exports, some of them might be used only internally. If\nthese exports should not be reported, there is a `ignoreExportsUsedInFile`\noption available. With this option enabled, when something is also no longer\nused internally, it will be reported as unused.\n\n```json title=\"knip.json\"\n{\n  \"ignoreExportsUsedInFile\": true\n}\n```\n\nIn a more fine-grained manner, to ignore only specific issue types:\n\n```json title=\"knip.json\"\n{\n  \"ignoreExportsUsedInFile\": {\n    \"interface\": true,\n    \"type\": true\n  }\n}\n```\n\nValid keys are the symbol types Knip distinguishes: `class`, `enum`, `function`,\n`interface`, `member`, `namespace`, `type` and `variable`.\n\nSet this option at root level to enable this globally, or within workspace\nconfigurations individually.\n\n### `includeEntryExports`\n\nBy default, Knip does not report unused exports in entry files. When a\nrepository (or workspace) is self-contained or private, you may want to include\nentry files when reporting unused exports:\n\n```json title=\"knip.json\"\n{\n  \"includeEntryExports\": true\n}\n```\n\nIf enabled, Knip will report unused exports in entry source files. But not in\nentry and configuration files as configured by plugins, such as `next.config.js`\nor `src/routes/+page.svelte`. Entry files discovered only through `package.json`\nscripts are also excluded; add them to `entry` to include their exports.\n\nThis will also enable reporting unused members of exported enums and namespaces.\n\nSet this option at root level to enable this globally, or within workspace\nconfigurations individually.\n\n## Compilers\n\nKnip supports custom compilers to transform files before analysis.\n\n:::note\n\nSince compilers are functions, they can only be used in dynamic configuration\nfiles (`.js` or `.ts`), not in JSON configuration files.\n\n:::\n\n### `compilers`\n\nOverride built-in compilers or add custom compilers for additional file types.\n\nAlso see [Compilers][13].\n\n[1]: ../reference/dynamic-configuration.mdx\n[2]: ../overview/configuration.md\n[3]: ../explanations/entry-files.md\n[4]: ../features/monorepos-and-workspaces.md\n[5]: ../explanations/plugins.md#entry-files\n[6]: ../explanations/plugins.md\n[7]: ../features/rules-and-filters.md#filters\n[8]: ./jsdoc-tsdoc-tags.md\n[9]: ../features/reporters.md#preprocessors\n[10]: ../guides/configuring-project-files.md\n[11]: ../features/production-mode.md\n[12]: ../guides/handling-issues.mdx#unused-dependencies\n[13]: ../features/compilers.md\n","packages/docs/src/content/docs/reference/faq.md":"---\ntitle: FAQ\ndescription: Design decisions behind Knip, common pitfalls, how it compares to ESLint and tree-shaking, and how the module graph works.\ndate: 2024-08-20\n---\n\n## Introduction\n\nKnip finds and fixes unused dependencies, exports and files. As a \"kitchen sink\"\nin the npm ecosystem, it creates a comprehensive module graph of your project.\n\n:::note[Rationale]\n\nThe JavaScript/TypeScript ecosystem has a vast amount of frameworks and tools.\nAdditionally, file locations, configuration semantics, command-line arguments\nand so on vary wildly. Files and dependencies are referenced in many ways. Knip\ntries harder than you think to cover it all.\n\n:::\n\nThis FAQ explains a few design decisions and why certain things work the way\nthey do, here and there in more depth than the rest of the docs.\n\n:::tip\n\nTry the [Knip MCP Server][1] or the [Knip Editor Extension][2]. Let your coding\nagent use the built-in MCP Server and create a custom `knip.json` for you, so\nyou don't have to.\n\n:::\n\n## Common Pitfalls\n\n### Why shouldn't I ignore or disable configuration hints?\n\nConfiguration hints are critical for building a healthy and accurate module\ngraph. They usually indicate that Knip cannot resolve a dependency, plugin, or\nentry file. If you ignore or disable these hints, Knip's understanding of your\nproject will be incomplete, which inevitably leads to false positives (reporting\nused code as unused). Always address configuration hints first before looking at\nother reported issues.\n\n### Why is it a bad idea to use `ignore` patterns like I do in ESLint?\n\nKnip is not a regular file-based linter like ESLint. It works by analyzing the\nentire interconnected module graph of your project. Using `ignore` patterns does\nnot exclude files from the analysis, it only suppresses the reporting of issues\nin those files. This hides real issues and creates blind spots. Instead of\nignoring files, ensure your entry points and plugins are configured correctly,\nand use `project` patterns to define the boundaries of your codebase. Read more:\n[Configuring Project Files][3].\n\nIf you have specific exports (such as types) that are only used within the file\nthey are defined, use the [ignoreExportsUsedInFile][4] configuration option\nrather than ignoring the file entirely.\n\n### How should I exclude tests and development tools from the analysis?\n\nA common mistake is trying to exclude test files, storybooks, or development\ntools using `project` or `ignore` patterns. The correct approach is to use\n[production mode][5]. This mode is specifically designed to strictly analyze\nonly your production source code and `dependencies`, automatically excluding\ntests and `devDependencies` without requiring complex ignore rules.\n\n### Why shouldn't I run `knip --fix` immediately?\n\nRunning `knip --fix` before your configuration is fully settled is dangerous. If\nyour configuration is missing entry points or has unresolved hints, Knip might\nthink perfectly valid, actively used code is unused. Auto-fixing in this state\ncan lead to deleting code that your application relies on. Always verify the\nreported issues manually and ensure your configuration is solid before using the\n`--fix` flag.\n\n## Comparison\n\n### Why isn't Knip an ESLint plugin?\n\nLinters like ESLint analyze files separately, while Knip lints projects as a\nwhole.\n\nKnip requires a full module and dependency graph to find clutter across the\nproject. Building the graph is substantial work, especially in monorepos.\n\nFile-oriented linters like ESLint are complementary to Knip.\n\n### Isn't tree-shaking enough?\n\nNo. They share a goal: improving UX by removing unused code. But tree-shaking\nand Knip are different, complementary tools.\n\nTree-shaking is a build-time optimization to reduce production bundle size. It\noperates on bundled production code, which might include external code, and runs\nautomatically (out of your hands).\n\nOn the other hand, Knip is a project linter for the development and QA phase. It\nreports and fixes only your own source code, and leaves the changes for you to\nreview. It focuses on inter-file dependencies, so dead code within a single file\nmay slip through.\n\nBesides those differences, Knip has a broader scope:\n\n- Improve DX (see [less is more][6]).\n- Unless using [production mode][5], also lint all source code like tests,\n  scripts and Storybook stories.\n- Handle more [types of issues][7] (such as unlisted dependencies).\n\nFor how Knip compares to other unused-code tools and how to migrate from them,\nsee [Comparison & Migration][8].\n\n## Synergy\n\n### Why does Knip have plugins?\n\nPlugins are an essential part of Knip. They save you a lot of configuration out\nof the box, by adding entry files as accurately as possible and only for the\ntools actually installed. More powerful still are their custom parsers for\nconfiguration files and command-line argument definitions.\n\nFor instance, Vitest has the `environment` configuration option. The Vitest\nplugin knows `\"node\"` is the default value for `environment` which does not\nrequire an extra package, but will translate `\"edge-runtime\"` to the\n`@edge-runtime/vm` package. This allows Knip to report it if this package is not\nlisted in `package.json`, or when it is no longer used after changes in the\nVitest configuration.\n\nConfiguration files may also contain references to entry files. For instance,\nJest has `setupFilesAfterEnv: \"<rootDir>/jest.setup.js\"` or a reference may\npoint to a file in another workspace in the same monorepo, e.g. `setupFiles:\n['@org/shared/jest-setup.ts']`. Those entry files may also contain imports of\ninternal modules or external dependencies, and so on.\n\n### Why is Knip so heavily engineered?\n\nEven though a modular approach has its merits, for Knip it makes sense to have\nall the pieces in a single tool.\n\nBuilding up the module and dependency graph takes more than standard module\nresolution. It needs dynamic analysis, not just static: plugin parsers actually\nload and execute dynamic tooling configuration files to read their exported\nvalue. On top of that, [exports consumed by external libraries][9] require type\ninformation. And shell script parsing is needed to find the right entry files,\nconfiguration files and dependencies accurately.\n\nThe rippling effect of plugins recursively pulling in more entry files and\ndependencies is exactly what [\"comprehensive\"][10] refers to.\n\n## Design decisions\n\n### Why isn't production mode the default?\n\nThe default mode of Knip includes all source files, tests, dependencies, dev\ndependencies and tooling configuration.\n\nOn the other hand, production mode considers only source files and production\ndependencies. Plugins add only production entry files.\n\nWhich mode should've been the default? They both have their merits:\n\n- Production mode catches dead production code and dependencies. This mode has\n  the most impact on UX, since less code tends to be faster and safer.\n- Default mode potentially catches more issues, e.g. lots of unused plugins of\n  tooling, including most issues found in production mode. This mode has the\n  most impact on DX, for the same reason.\n\nAlso see [production mode][5].\n\n### Why doesn't Knip just read the lockfile?\n\nKnip reads the `package.json` file of each dependency. Most of the information\nrequired is in the lockfile as well, which would be more efficient. However,\nlockfiles lack some data, including:\n\n- It requires lockfile parsing for each lockfile format and version of each\n  package manager.\n- The lockfile doesn't contain whether the package [has types included][11].\n- The lockfile doesn't contain entry point fields (`main`, `module`, `exports`)\n  needed to resolve what a dependency actually exposes.\n- The lockfile doesn't contain `bin` entries to determine installed binaries.\n\n### Why doesn't Knip use an existing module resolver?\n\nIt does: Knip uses [oxc-resolver][12]. A runtime or bundler resolver can't be\nused as-is, because Knip resolves imports to your source across every workspace\nin a (mono)repo. It has to:\n\n- Resolve to source (`src/module.ts`), not type definitions (`module.d.ts`) or\n  the build artifact a `package.json#main` like `dist/module.js` points to\n- Resolve non-standard extensions like `.svelte`, `.astro` and `.css` so those\n  files enter the module graph\n\noxc-resolver is configurable enough for this. Combined with a thin layer for\nKnip-configured `paths` and plugin aliases. This covers resolution across all\nworkspaces and[script parsing][13] and references to files in other workspaces.\n\n### Why doesn't Knip match my TypeScript project structure?\n\nRepositories and workspaces in a monorepo aren't necessarily structured like\nTypeScript projects. Put simply, the location of `package.json` files isn't\nalways adjacent to `tsconfig.json` files. Knip follows the structure of\nworkspaces in a monorepo.\n\nAn additional layering of TypeScript projects would complicate things. The\ndownside is that a `tsconfig.json` file not used by Knip may have conflicting\nmodule resolution settings, potentially resulting in missed files.\n\nIn practice, this is rarely an issue. Knip sticks to the workspaces structure\nand installs a single \"kitchen sink\" module resolver function per workspace.\nDifferent strategies might add more complexity and performance penalties, while\nthe current strategy is simple, fast and good enough.\n\nNote that any directory with a `package.json` not listed in the root\n`package.json#workspaces` can be added to the Knip configuration manually to\nhave it handled as a separate workspace.\n\nIf you do want Knip to take its project files from `tsconfig.json` rather than\nits own `project` patterns, see [`--use-tsconfig-files`][14].\n\n### Why doesn't Knip just use `ts.findReferences`?\n\nTypeScript has a very good \"Find references\" feature, that you might be using in\nyour IDE as well. There are a few reasons Knip doesn't use it:\n\n- It requires the full TypeScript language service, which is heavy to\n  initialize.\n- It must be called per symbol. A project with thousands of exports would need\n  thousands of calls, each scanning potentially all files. Knip parses each file\n  once and resolves all export usages from the resulting graph.\n- It operates within a single TypeScript program. Monorepos with multiple\n  `tsconfig.json` files would need separate language service instances.\n- It cannot see into non-standard files like `.vue`, `.svelte` and `.astro`.\n\nKnip's module graph is also serializable and cacheable, and usable for other\ntools to build upon.\n\n### Why doesn't Knip have...?\n\nExamples of features that have been requested include:\n\n- Expose programmatic API\n- Add local/custom plugins\n- Expose the module and dependency graph\n- Custom AST visitors, e.g. to find and return:\n  - Unused interface/type members\n  - Unused object members (and e.g. React component props)\n  - Unused object props in function return values\n- Analyze workspaces in parallel\n- Support Deno\n\nThese are all interesting ideas, but most increase the API surface area, and all\nrequire more development efforts and maintenance. Time is limited and\n[sponsorships][15] currently don't cover - this can change though!\n\n## Under the hood\n\n### Where does Knip look for entry files?\n\nKnip discovers them from defaults, `package.json`, enabled plugins, source-code\nimports and resolution calls (`require.resolve`, `import.meta.resolve`, `new\nURL`, `new Worker`, `module.register`), and parsed scripts. See [Entry\nFiles][16] for the complete list. Entry files are added to the module graph, and\n[module resolution][17] may result in more entry files recursively until none\nremain.\n\n### What does Knip look for in source files?\n\nKnip uses oxc-parser to parse source files, it's powerful and fault-tolerant.\nKnip visits all nodes of the generated AST to find:\n\n- Imports and dynamic imports of internal modules and external dependencies\n- Exports\n- Accessed properties on namespace imports and re-exports to track individual\n  export usage\n- Entry files from `require.resolve`, `import.meta.resolve`, `new URL(specifier,\nimport.meta.url)`, `new Worker(…)`, `child_process` `fork`/`spawn`/`execFile`,\n  and `module.register()`\n- Scripts passed to the [script parser][13]: tagged `$` templates (`bun`,\n  `execa`, `zx`) and `node:child_process`, `execa` and `nano-spawn` calls\n\n### What's in the graph?\n\nOnce built, the graph holds everything needed to produce the report: every\n[issue type][7], from unused files and dependencies to unused exports, types and\nenum members.\n\nThe graph also surfaces more interesting details, such as:\n\n- Circular references\n- Usage numbers per export\n- Export usage across workspaces in a monorepo\n- List of all binaries used\n- List of all used (OS) binaries not installed in `node_modules`\n\n### How does Knip handle non-standard import syntax?\n\nKnip tries to be resilient against import syntax like what's used by e.g.\nwebpack loaders or Vite asset imports. Knip strips off the prefixes and suffixes\nin import specifiers like this:\n\n```ts title=\"component.ts\"\nimport Icon from './icon.svg?raw';\nimport Styles from '-!style-loader!css-loader?modules!./styles.css';\n```\n\nIn this example, the `style-loader` and `css-loader` dependencies should be\ndependencies found in webpack configuration, handled by Knip's webpack plugin.\n\n## TypeScript\n\n### What's the difference between workspaces, projects and programs?\n\nA workspace is a directory with a `package.json` file. They're configured in\n`package.json#workspaces` (or `pnpm-workspaces.yml`). In case a directory has a\n`package.json` file, but is not a workspace (from a package manager\nperspective), it can be added as a workspace to the Knip configuration.\n\nProjects - in the context of TypeScript - are directories with a `tsconfig.json`\nfile. They're not a concept in Knip.\n\nKnip analyzes all workspaces using a single module graph with a shared module\nresolver.\n\n### What's up with that configurable `tsconfig.json` location?\n\nTwo settings point Knip at a `tsconfig.json`, and they do different things:\n\n- [`--tsConfig [file]`][18] (CLI, root only) sets an alternative location for\n  the root `tsconfig.json`. Knip reads its `compilerOptions`, notably `paths`\n  and `moduleResolution`.\n- [`typescript.config`][19] (plugin, per workspace) sets the location the\n  TypeScript plugin reads to extract referenced dependencies from `extends`,\n  `compilerOptions.types` and JSX settings:\n\n```json title=\"tsconfig.json\"\n{\n  \"extends\": \"@tsconfig/node20/tsconfig.json\",\n  \"compilerOptions\": {\n    \"jsxImportSource\": \"hastscript/svg\"\n  }\n}\n```\n\nFrom this example, Knip can tell whether `@tsconfig/node20` and `hastscript` are\nlisted in `package.json`.\n\nNote that the TypeScript plugin doesn't add TypeScript support to Knip (that's\nbuilt-in); like other plugins, it extracts dependencies from `tsconfig.json`. If\npath aliases from `compilerOptions.paths` aren't picked up, either point\n`--tsConfig` at the right `tsconfig.json` or add [paths][20] to the Knip config\n(per workspace).\n\n### What does `--use-tsconfig-files` do?\n\nBy default Knip discovers project files with its own `project` patterns. The\n[`--use-tsconfig-files`][14] flag instead takes them from `tsconfig.json` per\nworkspace. Those become TypeScript program files, so Knip analyzes their exports\nand dependencies but does not report them as unused files: delegating project\ndefinition to `tsconfig.json` declares them intentional, including empty files.\nThis is by design: use the default `project` patterns (discovery mode) to flag\ndangling files. Implicitly enabled in the [editor extension, MCP server and\nlanguage server][21] without a Knip configuration file.\n\n## Compilers\n\n### How does Knip handle Svelte or Astro files?\n\nTo further increase the coverage of the module graph, non-standard files other\nthan JavaScript and TypeScript modules should be included as well. For instance,\n`.mdx` and `.astro` files can import each other, internal modules and external\ndependencies.\n\nKnip includes basic \"compilers\" for a few common file types (Astro, MDX, Svelte,\nVue). These are lightweight regex-based extractors, not actual compilers. You\ncan override the built-in compilers with your project's actual compiler, and add\nadditional ones for other file types.\n\n### Why are the exports of my `.vue` files not used?\n\nThe built-in compilers extract `import` statements only, so the exports declared\nin a `.vue` or `.svelte` file aren't analyzed and may be reported as unused.\nOverride the built-in with a real compiler. See [Compilers][22].\n\n[1]: ../reference/integrations.md#mcp-server\n[2]: ../reference/integrations.md#vs-code-extension\n[3]: ../guides/configuring-project-files.md\n[4]: ../reference/configuration.md#ignoreexportsusedinfile\n[5]: ../features/production-mode.md\n[6]: ../explanations/why-use-knip.md#less-is-more\n[7]: ./issue-types.md\n[8]: ../explanations/comparison-and-migration.md\n[9]: ../guides/handling-issues.mdx#external-libraries\n[10]: ../explanations/why-use-knip.md#comprehensive\n[11]: ../guides/handling-issues.mdx#type-definition-packages\n[12]: https://oxc.rs/docs/guide/usage/resolver.html\n[13]: ../features/script-parser.md\n[14]: ../reference/cli.md#--use-tsconfig-files\n[15]: /sponsors\n[16]: ../explanations/entry-files.md#where-knip-looks-for-entry-files\n[17]: #why-doesnt-knip-use-an-existing-module-resolver\n[18]: ../reference/cli.md#--tsconfig-file\n[19]: ../explanations/plugins.md#configuration-files\n[20]: ../reference/configuration.md#paths\n[21]: ../reference/integrations.md\n[22]: ../features/compilers.md\n","packages/docs/src/content/docs/reference/integrations.md":"---\ntitle: Integrations\ndescription: Knip's VS Code extension, JetBrains plugin, MCP server and language server for editor diagnostics and coding agents.\n---\n\n- [VS Code/VSX Extension][1]\n- [JetBrains Plugin][2]\n- [MCP Server][3]\n- [Language Server][4]\n\n## VS Code Extension\n\nThe official VS Code extension provides a rich integration with the [Knip\nLanguage Server][4]:\n\n- **Diagnostics**: Inline warnings for unused dependencies, exports and files\n- **Hover Information**: Hover over exports to see import and usage locations\n- **Imports Tree View**: Direct links to implementations\n- **Exports Tree View**: Direct links to import and usage locations\n- **Contention Detection**: Warnings for circular dependencies, ambiguous,\n  shadowed and diamond-shaped import chains\n- **Built-in MCP Server**: Automated configuration support for coding agents\n\nFind [Knip on the VS Code Marketplace][5] and find [Knip in the Open VSX\nRegistry][6].\n\nSee below for [screenshots][7].\n\n## JetBrains Plugin\n\nA community plugin is available for JetBrains IDEs including WebStorm, IntelliJ\nIDEA, and others. The plugin is powered by the [Knip Language Server][4] and\nprovides diagnostics. Find [Knip on the JetBrains Marketplace][8].\n\n## MCP Server\n\nThe standalone MCP Server enables coding agents to configure Knip automatically.\nTell your agent to \"configure knip\" and it will use the available tools to\ncreate, analyze and optimize your `knip.json` configuration.\n\nThe [Knip MCP Server][9] is available separately and built into the [Knip VS\nCode Extension][1].\n\nStart:\n\n```sh\nnpx @knip/mcp\n```\n\nNote: The VS Code extension has this MCP Server built-in.\n\n## Language Server\n\nThe IDE integrations are powered by the Knip Language Server. It builds the full\nmodule graph of your project and provides a session with a graph explorer. See\nthe [Knip Language Server documentation][10] for more details and information on\nintegrating Knip.\n\n## VS Code Extension Screenshots\n\n### Lint Findings\n\n![Lint Findings][11]\n\n### Imports & Exports\n\n![Hover over imports and exports][12]\n\n### Contention\n\nThe extension shows circular dependencies and three kinds of export contention:\nambiguous, shadowed, and converged.\n\n#### Circular Dependencies\n\n![Circular Dependencies][13]\n\n#### Ambiguous\n\nDifferent bindings compete for the same name, with no winner. Knip lists the\ncompeting bindings:\n\n![Ambiguous][14]\n\n#### Shadowed\n\nAn explicit export hides bindings from `export *`. Knip labels the site as\n\"shadowing\" and lists the winning and hidden bindings:\n\n![Shadowed][15]\n\n#### Converged\n\nThe same binding arrives through multiple re-export paths. Knip shows where\nthose paths meet and the binding they share.\n\n![Converged][16]\n\n### Settings\n\n![VS Code Extension Settings][17]\n\n[1]: #vs-code-extension\n[2]: #jetbrains-plugin\n[3]: #mcp-server\n[4]: #language-server\n[5]: https://marketplace.visualstudio.com/items?itemName=webpro.vscode-knip\n[6]: https://open-vsx.org/extension/webpro/vscode-knip\n[7]: #vs-code-extension-screenshots\n[8]: https://plugins.jetbrains.com/plugin/29765-knip\n[9]: https://www.npmx.dev/package/@knip/mcp\n[10]: https://github.com/webpro-nl/knip/blob/main/packages/language-server/README.md\n[11]: /screenshots/editors-and-agents/diagnostics.webp\n[12]: /screenshots/editors-and-agents/imports-exports.webp\n[13]: /screenshots/editors-and-agents/circular-dependency.webp\n[14]: /screenshots/editors-and-agents/ambiguous.webp\n[15]: /screenshots/editors-and-agents/shadow.webp\n[16]: /screenshots/editors-and-agents/branch.webp\n[17]: /screenshots/editors-and-agents/vscode-extension-settings.webp\n","packages/docs/src/content/docs/reference/issue-types.md":"---\ntitle: Issue Types\ndescription: Every issue type Knip reports, from unused files and dependencies to unused exports, enum and namespace members, with their filter keys.\ntableOfContents: false\n---\n\nKnip reports the following types of issues:\n\n| Title                                | Description                                                |       | Key                 |\n| :----------------------------------- | :--------------------------------------------------------- | ----- | :------------------ |\n| Unused files                         | Unable to find a reference to this file                    | 🔧    | `files`             |\n| Unused dependencies                  | Unable to find a reference to this dependency              | 🔧    | `dependencies`      |\n| Unused devDependencies               | Unable to find a reference to this devDependency           | 🔧    | `dependencies`²     |\n| Referenced optional peerDependencies | Optional peer dependency is referenced                     |       | `dependencies`²     |\n| Unlisted dependencies                | Used dependencies not listed in package.json               |       | `unlisted`          |\n| Unlisted binaries                    | Binaries from dependencies not listed in package.json      |       | `binaries`          |\n| Unused catalog entries               | Unable to find a reference to this catalog entry           | 🔧    | `catalog`           |\n| Unresolved catalog references        | Catalog does not contain the referenced package            |       | `catalogReferences` |\n| Unresolved imports                   | Unable to resolve this (import) specifier                  |       | `unresolved`        |\n| Unused exports                       | Unable to find a reference to this export                  | 🔧    | `exports`           |\n| Unused exported types                | Unable to find a reference to this exported type           | 🔧    | `types`             |\n| Exports in used namespace            | Namespace with export is referenced, but not export itself | 🔧 🟠 | `nsExports`         |\n| Exported types in used namespace     | Namespace with type is referenced, but not type itself     | 🔧 🟠 | `nsTypes`           |\n| Unused exported enum members         | Unable to find a reference to this enum member             | 🔧    | `enumMembers`       |\n| Unused exported namespace members    | Unable to find a reference to this namespace member        | 🔧    | `namespaceMembers`  |\n| Duplicate exports                    | This is exported more than once                            |       | `duplicates`        |\n| Circular dependencies                | These files (in)directly import each other at runtime      | 🟠    | `cycles`            |\n\n## Legend\n\n|     | Description                                         |\n| --- | :-------------------------------------------------- |\n| 🔧  | [Auto-fixable][1] issue types                       |\n| 🟠  | Not included by default (include with [filters][2]) |\n\n## Notes\n\n1. When an issue type has zero issues, it is not shown.\n2. Including or excluding `dependencies` (via CLI or configuration)\n   automatically includes or excludes `devDependencies` and\n   `optionalPeerDependencies`. In [rules][3], each key can be set individually.\n3. In [strict production mode][4], `devDependencies` are not included.\n4. The `types` issue type includes `enum`, `interface` and `type` exports.\n5. `cycles` defaults to the `warn` [rule][3] (reported, but not counted as an\n   error). Set `rules.cycles` to `error` to fail on circular dependencies.\n\n[1]: ../features/auto-fix.mdx\n[2]: ../features/rules-and-filters.md#filters\n[3]: ../features/rules-and-filters.md#rules\n[4]: ../features/production-mode.md#strict-mode\n","packages/docs/src/content/docs/reference/jsdoc-tsdoc-tags.md":"---\ntitle: JSDoc & TSDoc Tags\ndescription: Use JSDoc and TSDoc tags like `@public`, `@internal`, `@alias` and custom tags to include or exclude exports from Knip's report.\n---\n\nJSDoc or TSDoc tags can be used to make exceptions for unused or duplicate\nexports.\n\nKnip tries to minimize configuration and introduces no new syntax. That's why it\nhooks into JSDoc and TSDoc tags.\n\n:::caution\n\nAdding tags or excluding a certain type of issues from the report is usually not\nrecommended. It hides issues, which is often a sign of code smell or ambiguity\nand ends up harder to maintain. It's usually better to refactor the code (or\nreport an issue with Knip for false positives).\n\n:::\n\nTags also work in regular block comments (`/* ... */`) and standalone line\ncomments (`// ...`) before a declaration. These comments keep suppression tags\nout of JSDoc hover information.\n\nTags in consecutive comments are combined. Trailing `//` comments are ignored.\n\n## Tags\n\nUse arbitrary [tags][1] to exclude or include tagged exports from the report.\nExample:\n\n```ts\n/** @lintignore */\nexport const myUnusedExport = 1;\n\n// @lintignore\nimport Unresolved from './generated/lib.js';\n```\n\nAnd then include (`+`) or exclude (`-`) these tagged exports from the report\nlike so:\n\n```shell\nknip --tags=-lintignore,-internal\n```\n\nTags can also be [configured in `knip.json`][2].\n\nWhen an excluded tag is no longer necessary because the export is actually used,\nKnip reports a **tag hint**:\n\n```sh\nTag hints (1)\nignored  unimported.ts  Unused tag in unimported.ts: ignored → @custom\n```\n\nThis helps you clean up tags that were added to suppress issues that have since\nbeen resolved.\n\n## `@public`\n\nBy default, Knip reports unused exports in non-entry files.\n\nTag the export as `@public` and Knip will not report it.\n\nExample:\n\n```ts\n/**\n * @public\n */\nexport const unusedFunction = () => {};\n```\n\nThis tag can also be used to make exceptions in entry files when using\n[--include-entry-exports][3].\n\n[JSDoc: @public][4] and [TSDoc: @public][5]\n\n## `@internal`\n\nInternal exports are not meant for public consumption, but only for internal\nusage such as tests. This means they would be reported in [production mode][6].\n\nMark the export with `@internal` and Knip will not report the export in\nproduction mode.\n\nExample:\n\n```ts\n/** @internal */\nexport const internalTestedFunction = () => {};\n```\n\nIn general it's not recommended to expose and test implementation details, but\nexceptions are possible. Those should not be reported as false positives, so\nwhen using production mode you'll need to help Knip out by tagging them as\n`@internal`.\n\n[TSDoc: @internal][7]\n\n## `@alias`\n\nKnip reports duplicate exports. To prevent this, tag one of the exports as\n`@alias`.\n\nExample:\n\n```ts\nexport const Component = () => {};\n\n/** @alias */\nexport default Component;\n```\n\nAn alternative solution is to use `--exclude duplicates` and exclude all\nduplicates from being reported.\n\n[JSDoc: @alias][8]\n\n## `@beta`\n\nWorks identical to [`@public`][9]. Knip ignores other tags like `@alpha` and\n`@experimental`.\n\n[TSDoc: @beta][10]\n\n[1]: ../reference/cli.md#--tags\n[2]: ./configuration.md#tags\n[3]: ./cli.md#--include-entry-exports\n[4]: https://jsdoc.app/tags-public.html\n[5]: https://tsdoc.org/pages/tags/public/\n[6]: ../features/production-mode.md\n[7]: https://tsdoc.org/pages/tags/internal/\n[8]: https://jsdoc.app/tags-alias.html\n[9]: #public\n[10]: https://tsdoc.org/pages/tags/beta/\n","packages/docs/src/content/docs/reference/known-issues.md":"---\ntitle: Known Issues\ndescription: Known limitations and workarounds for caching, config file errors, path aliases in config files, and the Nx daemon.\n---\n\nKnown limitations and workarounds for errors during a Knip run.\n\nSee [handling issues][1] to learn more about dealing with lint issues.\n\n## Exceptions from config files\n\nKnip plugins may fail to load a JavaScript or TypeScript configuration file such\nas `webpack.config.js` or `vite.config.ts`:\n\n```sh\n$ knip\nERROR: Error loading vite.config.ts\n```\n\nKnip exits with code `2` when a plugin config file fails to load.\n`--no-exit-code` does not suppress this error.\n\nKnip may load such files differently, in a different environment, with missing\nenvironment variables, missing path aliases, etcetera. Use `--debug` to locate\nthe cause of the issue with more details.\n\nPotential workarounds:\n\n- For \"Cannot find module\" and \"ENOENT: no such file/dir, open './file'\" errors:\n  - Install dependencies\n  - Use absolute paths, e.g. with `path.join()` or `path.resolve()`\n  - [Set path aliases][2]\n- Set missing environment variable(s), potential solutions:\n  - Use a helper package like [dotenvx][3]\n  - `KEY=VAL knip`\n  - `node --env-file .env $(which knip)`\n- Run the build script to generate required files.\n- Disable loading the file by overriding the default `config` for that plugin.\n  - Example: `vite: { config: [] }`\n  - In a monorepo, be more specific like so: `workspaces: { \"packages/lib\": {\nvite: { config: [] } } }`\n  - If this helps, add the file as an `entry` file for static analysis.\n- Disable the related plugin.\n  - Example: `eslint: false`\n  - In a monorepo, be more specific like so: `workspaces: { \"packages/lib\": {\neslint: false } }`\n  - If this helps, add the file as an `entry` file for static analysis.\n- As a last resort, ignore the workspace: `ignoreWorkspaces: [\"packages/lib\"]`.\n\n## Path aliases in config files\n\nLoading the configuration file (e.g. `cypress.config.ts`) for one of Knip's\nplugins may give an error:\n\n```sh\n$ knip\nAnalyzing workspace ....\nError loading .../cypress.config.ts\nReason: Cannot find module '@alias/name'\nRequire stack:\n- .../cypress.config.ts\n```\n\nSome tools (such as Cypress and Jest) support using TypeScript path aliases in\nthe configuration file.\n\nPotential workarounds:\n\n- Rewrite the import in the configuration file to a relative import.\n- Inject support with a module like `tsx`: `NODE_OPTIONS=\"--import tsx\" knip`\n- Or `tsconfig-paths`: `NODE_OPTIONS=\"--import tsconfig-paths/register.js\" knip`\n- Use Bun with [knip-bun][4].\n- See [exceptions from config files][5] for more potential workarounds.\n\n## Nx Daemon\n\nIn Nx projects you might encounter this error:\n\n```sh\nNX   Daemon process terminated and closed the connection\n```\n\nThe solution is to [disable the Nx Daemon][6]:\n\n```sh\nNX_DAEMON=false knip\n```\n\n## Raw transfer memory errors\n\nOn machines with low RAM or Windows with Node.js >=22, oxc-parser raw transfer\nmay fail under memory pressure:\n\n```sh\nRangeError: Array buffer allocation failed\n```\n\nDisable raw transfer to use the normal parser path:\n\n```sh\nKNIP_DISABLE_RAW_TRANSFER=1 knip\n```\n\n## Stale cache results\n\nWith `--cache`, configuration or path alias changes may leave results stale. An\nimport may still be reported as unresolved after the missing file is added.\nNewly added `.gitignore` files are also not detected automatically.\n\nRun without `--cache` for fresh results, or delete the cache directory\n(`node_modules/.cache/knip` by default, configurable with `--cache-location`)\nbefore running with `--cache` again.\n\n[1]: ../guides/handling-issues.mdx\n[2]: #path-aliases-in-config-files\n[3]: https://dotenvx.com/\n[4]: ./cli.md#knip-bun\n[5]: #exceptions-from-config-files\n[6]: https://nx.dev/concepts/nx-daemon#turning-it-off\n","packages/docs/src/content/docs/reference/plugins.md":"---\ntitle: Plugins (177)\ndescription: 'The full list of Knip plugins for frameworks, build tools, test runners and linters, each linking to its reference page.'\ntableOfContents: false\n---\n\n:::section{.columns.min200}\n\n- [Angular][1]\n- [Astro][2]\n- [Astro DB][3]\n- [Astro Markdoc][4]\n- [astro-og-canvas][5]\n- [Ava][6]\n- [Babel][7]\n- [Biome][8]\n- [bumpp][9]\n- [Bun][10]\n- [c8][11]\n- [Capacitor][12]\n- [Catalyst][13]\n- [Changelogen][14]\n- [Changelogithub][15]\n- [Changesets][16]\n- [Commitizen][17]\n- [commitlint][18]\n- [Convex][19]\n- [create-typescript-app][20]\n- [CSpell][21]\n- [Cucumber][22]\n- [Cypress][23]\n- [Danger][24]\n- [dependency-cruiser][25]\n- [Docusaurus][26]\n- [dotenv][27]\n- [Drizzle][28]\n- [electron-vite][29]\n- [Eleventy][30]\n- [esbuild][31]\n- [ESLint][32]\n- [eve][33]\n- [execa][34]\n- [Expo][35]\n- [Expressive Code][36]\n- [FAST][37]\n- [Fumadocs][38]\n- [Gatsby][39]\n- [GitHub Action][40]\n- [GitHub Actions][41]\n- [glob][42]\n- [GraphQL Codegen][43]\n- [Hardhat][44]\n- [husky][45]\n- [i18next Parser][46]\n- [Jest][47]\n- [Karma][48]\n- [Knex][49]\n- [Ladle][50]\n- [laravel-vite-plugin][51]\n- [Lefthook][52]\n- [lint-staged][53]\n- [LintHTML][54]\n- [Lit][55]\n- [lockfile-lint][56]\n- [Lost Pixel][57]\n- [Lunaria][58]\n- [markdownlint][59]\n- [MDX][60]\n- [mdxlint][61]\n- [Metro][62]\n- [Mocha][63]\n- [moonrepo][64]\n- [Mock Service Worker][65]\n- [nano-spawn][66]\n- [Nano Staged][67]\n- [Nest][68]\n- [Netlify][69]\n- [Next.js][70]\n- [next-intl][71]\n- [Next.js MDX][72]\n- [Nitro][73]\n- [Node.js][74]\n- [node-modules-inspector][75]\n- [nodemon][76]\n- [npm-package-json-lint][77]\n- [Nuxt][78]\n- [@nuxtjs/i18n][79]\n- [Nx][80]\n- [nyc][81]\n- [oclif][82]\n- [openapi-ts][83]\n- [orval][84]\n- [Oxfmt][85]\n- [Oxlint][86]\n- [Panda CSS][87]\n- [Parcel][88]\n- [Payload CMS][89]\n- [pino][90]\n- [Playwright][91]\n- [Playwright for components][92]\n- [playwright-test][93]\n- [Plop][94]\n- [pm2][95]\n- [pnpm][96]\n- [PostCSS][97]\n- [Preconstruct][98]\n- [Prettier][99]\n- [Prisma][100]\n- [Quasar][101]\n- [Qwik][102]\n- [Raycast][103]\n- [React Cosmos][104]\n- [React Email][105]\n- [React Native][106]\n- [React Router][107]\n- [Relay][108]\n- [Release It!][109]\n- [Remark][110]\n- [Remix][111]\n- [Rolldown][112]\n- [Rollup][113]\n- [Rsbuild][114]\n- [Rslib][115]\n- [Rspack][116]\n- [Rstest][117]\n- [Sanity][118]\n- [Semantic Release][119]\n- [Sentry][120]\n- [Serverless Framework][121]\n- [simple-git-hooks][122]\n- [size-limit][123]\n- [SST][124]\n- [Starlight][125]\n- [Stencil][126]\n- [Storybook][127]\n- [Stryker][128]\n- [Stylelint][129]\n- [Svelte][130]\n- [@sveltejs/package][131]\n- [SvelteKit][132]\n- [SVGO][133]\n- [SVGR][134]\n- [SWC][135]\n- [Syncpack][136]\n- [Tailwind][137]\n- [TanStack Router][138]\n- [Taskfile][139]\n- [Tauri][140]\n- [Temporal.io][141]\n- [Travis CI][142]\n- [ts-node][143]\n- [tsdown][144]\n- [tsup][145]\n- [tsx][146]\n- [TypeDoc][147]\n- [TypeScript][148]\n- [unbuild][149]\n- [UnoCSS][150]\n- [unplugin-auto-import][151]\n- [unplugin-icons][152]\n- [unplugin-vue-components][153]\n- [@intlify/unplugin-vue-i18n][154]\n- [unplugin-vue-markdown][155]\n- [unplugin-vue-router][156]\n- [Vercel][157]\n- [Vercel OG][158]\n- [Vike][159]\n- [Vite][160]\n- [vite-plugin-pages][161]\n- [vite-plugin-pwa][162]\n- [vite-plugin-vue-layouts-next][163]\n- [vite-plus][164]\n- [@vite-pwa/assets-generator][165]\n- [VitePress][166]\n- [Vitest][167]\n- [Vue][168]\n- [WebdriverIO][169]\n- [webpack][170]\n- [Wireit][171]\n- [Wrangler][172]\n- [WXT][173]\n- [xo][174]\n- [Yarn][175]\n- [yorkie][176]\n- [zx][177]\n\n:::\n\n[1]: /reference/plugins/angular\n[2]: /reference/plugins/astro\n[3]: /reference/plugins/astro-db\n[4]: /reference/plugins/astro-markdoc\n[5]: /reference/plugins/astro-og-canvas\n[6]: /reference/plugins/ava\n[7]: /reference/plugins/babel\n[8]: /reference/plugins/biome\n[9]: /reference/plugins/bumpp\n[10]: /reference/plugins/bun\n[11]: /reference/plugins/c8\n[12]: /reference/plugins/capacitor\n[13]: /reference/plugins/catalyst\n[14]: /reference/plugins/changelogen\n[15]: /reference/plugins/changelogithub\n[16]: /reference/plugins/changesets\n[17]: /reference/plugins/commitizen\n[18]: /reference/plugins/commitlint\n[19]: /reference/plugins/convex\n[20]: /reference/plugins/create-typescript-app\n[21]: /reference/plugins/cspell\n[22]: /reference/plugins/cucumber\n[23]: /reference/plugins/cypress\n[24]: /reference/plugins/danger\n[25]: /reference/plugins/dependency-cruiser\n[26]: /reference/plugins/docusaurus\n[27]: /reference/plugins/dotenv\n[28]: /reference/plugins/drizzle\n[29]: /reference/plugins/electron-vite\n[30]: /reference/plugins/eleventy\n[31]: /reference/plugins/esbuild\n[32]: /reference/plugins/eslint\n[33]: /reference/plugins/eve\n[34]: /reference/plugins/execa\n[35]: /reference/plugins/expo\n[36]: /reference/plugins/expressive-code\n[37]: /reference/plugins/fast\n[38]: /reference/plugins/fumadocs\n[39]: /reference/plugins/gatsby\n[40]: /reference/plugins/github-action\n[41]: /reference/plugins/github-actions\n[42]: /reference/plugins/glob\n[43]: /reference/plugins/graphql-codegen\n[44]: /reference/plugins/hardhat\n[45]: /reference/plugins/husky\n[46]: /reference/plugins/i18next-parser\n[47]: /reference/plugins/jest\n[48]: /reference/plugins/karma\n[49]: /reference/plugins/knex\n[50]: /reference/plugins/ladle\n[51]: /reference/plugins/laravel-vite-plugin\n[52]: /reference/plugins/lefthook\n[53]: /reference/plugins/lint-staged\n[54]: /reference/plugins/linthtml\n[55]: /reference/plugins/lit\n[56]: /reference/plugins/lockfile-lint\n[57]: /reference/plugins/lost-pixel\n[58]: /reference/plugins/lunaria\n[59]: /reference/plugins/markdownlint\n[60]: /reference/plugins/mdx\n[61]: /reference/plugins/mdxlint\n[62]: /reference/plugins/metro\n[63]: /reference/plugins/mocha\n[64]: /reference/plugins/moonrepo\n[65]: /reference/plugins/msw\n[66]: /reference/plugins/nano-spawn\n[67]: /reference/plugins/nano-staged\n[68]: /reference/plugins/nest\n[69]: /reference/plugins/netlify\n[70]: /reference/plugins/next\n[71]: /reference/plugins/next-intl\n[72]: /reference/plugins/next-mdx\n[73]: /reference/plugins/nitro\n[74]: /reference/plugins/node\n[75]: /reference/plugins/node-modules-inspector\n[76]: /reference/plugins/nodemon\n[77]: /reference/plugins/npm-package-json-lint\n[78]: /reference/plugins/nuxt\n[79]: /reference/plugins/nuxtjs-i18n\n[80]: /reference/plugins/nx\n[81]: /reference/plugins/nyc\n[82]: /reference/plugins/oclif\n[83]: /reference/plugins/openapi-ts\n[84]: /reference/plugins/orval\n[85]: /reference/plugins/oxfmt\n[86]: /reference/plugins/oxlint\n[87]: /reference/plugins/panda-css\n[88]: /reference/plugins/parcel\n[89]: /reference/plugins/payload\n[90]: /reference/plugins/pino\n[91]: /reference/plugins/playwright\n[92]: /reference/plugins/playwright-ct\n[93]: /reference/plugins/playwright-test\n[94]: /reference/plugins/plop\n[95]: /reference/plugins/pm2\n[96]: /reference/plugins/pnpm\n[97]: /reference/plugins/postcss\n[98]: /reference/plugins/preconstruct\n[99]: /reference/plugins/prettier\n[100]: /reference/plugins/prisma\n[101]: /reference/plugins/quasar\n[102]: /reference/plugins/qwik\n[103]: /reference/plugins/raycast\n[104]: /reference/plugins/react-cosmos\n[105]: /reference/plugins/react-email\n[106]: /reference/plugins/react-native\n[107]: /reference/plugins/react-router\n[108]: /reference/plugins/relay\n[109]: /reference/plugins/release-it\n[110]: /reference/plugins/remark\n[111]: /reference/plugins/remix\n[112]: /reference/plugins/rolldown\n[113]: /reference/plugins/rollup\n[114]: /reference/plugins/rsbuild\n[115]: /reference/plugins/rslib\n[116]: /reference/plugins/rspack\n[117]: /reference/plugins/rstest\n[118]: /reference/plugins/sanity\n[119]: /reference/plugins/semantic-release\n[120]: /reference/plugins/sentry\n[121]: /reference/plugins/serverless-framework\n[122]: /reference/plugins/simple-git-hooks\n[123]: /reference/plugins/size-limit\n[124]: /reference/plugins/sst\n[125]: /reference/plugins/starlight\n[126]: /reference/plugins/stencil\n[127]: /reference/plugins/storybook\n[128]: /reference/plugins/stryker\n[129]: /reference/plugins/stylelint\n[130]: /reference/plugins/svelte\n[131]: /reference/plugins/sveltejs-package\n[132]: /reference/plugins/sveltekit\n[133]: /reference/plugins/svgo\n[134]: /reference/plugins/svgr\n[135]: /reference/plugins/swc\n[136]: /reference/plugins/syncpack\n[137]: /reference/plugins/tailwind\n[138]: /reference/plugins/tanstack-router\n[139]: /reference/plugins/taskfile\n[140]: /reference/plugins/tauri\n[141]: /reference/plugins/temporal\n[142]: /reference/plugins/travis\n[143]: /reference/plugins/ts-node\n[144]: /reference/plugins/tsdown\n[145]: /reference/plugins/tsup\n[146]: /reference/plugins/tsx\n[147]: /reference/plugins/typedoc\n[148]: /reference/plugins/typescript\n[149]: /reference/plugins/unbuild\n[150]: /reference/plugins/unocss\n[151]: /reference/plugins/unplugin-auto-import\n[152]: /reference/plugins/unplugin-icons\n[153]: /reference/plugins/unplugin-vue-components\n[154]: /reference/plugins/unplugin-vue-i18n\n[155]: /reference/plugins/unplugin-vue-markdown\n[156]: /reference/plugins/unplugin-vue-router\n[157]: /reference/plugins/vercel\n[158]: /reference/plugins/vercel-og\n[159]: /reference/plugins/vike\n[160]: /reference/plugins/vite\n[161]: /reference/plugins/vite-plugin-pages\n[162]: /reference/plugins/vite-plugin-pwa\n[163]: /reference/plugins/vite-plugin-vue-layouts-next\n[164]: /reference/plugins/vite-plus\n[165]: /reference/plugins/vite-pwa-assets-generator\n[166]: /reference/plugins/vitepress\n[167]: /reference/plugins/vitest\n[168]: /reference/plugins/vue\n[169]: /reference/plugins/webdriver-io\n[170]: /reference/plugins/webpack\n[171]: /reference/plugins/wireit\n[172]: /reference/plugins/wrangler\n[173]: /reference/plugins/wxt\n[174]: /reference/plugins/xo\n[175]: /reference/plugins/yarn\n[176]: /reference/plugins/yorkie\n[177]: /reference/plugins/zx\n","packages/docs/src/content/docs/reference/related-tooling.md":"---\ntitle: Related Tooling\ndescription: Tools that complement Knip for things it does not cover, like unused imports and variables, and unused properties of objects and types.\n---\n\nThis is an overview of related tooling for features Knip does not support.\n\n## Unused imports & variables\n\nKnip doesn't look for unused imports and variables within a file. The focus is\non exported values and types across files.\n\nUse [ESLint][1], [Biome][2] or [oxlint][3] to find unused variables within\nfiles.\n\nUse [remove-unused-vars][4] to remove unused code within files, but in a more\nvaliant way. Using input from any of the above linters, it actually removes a\nlot more unused code. This pairs great with Knip.\n\n## Unused properties\n\nKnip does not yet support finding unused members of types, interfaces and\nobjects. This includes returned objects from exported functions and objects\npassed as React component props.\n\nKnip does support finding unused members of enums and classes, and exported\nvalues and types on imported namespaces.\n\n## Circular dependencies\n\nKnip reports circular dependencies as an opt-in [`cycles`][5] issue type. The\n[editor integrations][6] show cyclic paths directly in IDE.\n\nOther dedicated tools include [DPDM][7], [Madge][8] and [skott][9]. Linters such\nas ESLint have similar plugins and rules, e.g. the `eslint-plugin-import-x`\nplugin has the [import-x/no-cycle][10] and oxlint has the [import/no-cycle][11]\nrule.\n\n## Cleanup\n\nThe [e18e.dev][12] website and in particular the [Cleanup][13] section is a\ngreat resource when dealing with technical debt.\n\n[1]: https://eslint.org\n[2]: https://biomejs.dev/linter/\n[3]: https://oxc.rs/docs/guide/usage/linter.html\n[4]: https://github.com/webpro-nl/remove-unused-vars\n[5]: ./issue-types.md\n[6]: ./integrations.md#circular-dependencies\n[7]: https://github.com/acrazing/dpdm\n[8]: https://github.com/pahen/madge\n[9]: https://github.com/antoine-coulon/skott\n[10]: https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-cycle.md\n[11]: https://oxc.rs/docs/guide/usage/linter/rules/import/no-cycle.html\n[12]: https://e18e.dev\n[13]: https://e18e.dev/guide/cleanup.html\n","packages/docs/src/content/docs/typescript/unused-dependencies.md":"---\ntitle: Unused dependencies\ndescription: Find and remove unused dependencies with Knip\nprev: false\nnext: false\n---\n\nOne of Knip's core features is finding unused dependencies in your JavaScript\nand TypeScript projects. And it comes with many more features to remove clutter\nand keep your projects in great shape.\n\n## Why are unused dependencies a problem?\n\nHaving unused dependencies in your `package.json` is an issue for various\nreasons:\n\n- They might end up in the final production bundle, increasing size and load\n  times for end users.\n- They waste space in `node_modules` and add to the installation time of the\n  project.\n- They slow down tooling such as linters and bundlers that analyze dependencies.\n- They are confusing and noisy in `package.json`.\n- They cause unnecessary extra work when managing and upgrading dependencies.\n- They can cause version conflicts with other dependencies in use.\n- They can cause false security alerts.\n- They might have restrictive licenses and make your project subject to theirs.\n- They usually come with transitive dependencies that have the same issues.\n\n## How do I find unused dependencies?\n\nUse Knip to find and remove unused dependencies. It also finds dependencies that\nare missing in `package.json` and has a lot more features to keep your\nJavaScript and TypeScript projects tidy.\n\nIt's easy to [get started][1] and make package management easier and more fun!\n\n<div style=\"display: flex; justify-content: center; margin: 4rem auto;\">\n  <img src=\"/logo.svg\" alt=\"Logo of Knip, to find unused dependencies, exports and files\" class=\"logo-border\" />\n</div>\n\n## How does Knip identify unused dependencies?\n\nKnip works by analyzing `package.json` files, source code and configuration\nfiles for other tooling in the project to find unused and missing dependencies.\nKnip has many heuristics, [plugins][2] and [compilers][3] to fully automate the\nprocess.\n\n## Can Knip remove unused dependencies?\n\nYes, Knip can automatically remove unused dependencies installed by a package\nmanager like npm or pnpm for you. Add the `--fix` argument to [auto-fix][4] and\nremove unused dependencies from `package.json`.\n\n## Can Knip detect missing dependencies?\n\nYes, Knip detects missing dependencies. It analyzes `package.json` files, and\nreports packages that are missing. They should be added to `package.json` to\navoid relying on transitive dependencies that can cause version mismatches and\nbreakage.\n\n## Does Knip work with monorepos?\n\nYes, Knip has first-class support for [monorepos and workspaces][5]. It analyzes\nall workspaces in the project and understands their relationship.\n\nFor instance, if a dependency is listed in the root `package.json` it does not\nneed to be listed in other workspaces. Except if you enable `--strict` checking.\n\n## Does Knip separate dependencies and devDependencies?\n\nYes, Knip understands the difference between dependencies and devDependencies.\nIt has a [production mode][6] to focus on production code only and find dead\ncode and dependencies that would otherwise only be referenced by tests and other\ntooling. This allows you to remove both unused exported code and their tests.\n\n## Does Knip work with my package manager?\n\nYes, Knip works with any package manager: npm, pnpm, Bun and Yarn are all\nsupported. It's easy to [get started][1] with any package manager.\n\n[1]: ../overview/getting-started.mdx\n[2]: ../reference/plugins.md\n[3]: ../features/compilers.md\n[4]: ../features/auto-fix.mdx\n[5]: ../features/monorepos-and-workspaces.md\n[6]: ../features/production-mode.md\n","packages/docs/src/content/docs/typescript/unused-exports.md":"---\ntitle: Unused exports\ndescription: Find and remove unused exports with Knip\nprev: false\nnext: false\n---\n\nFinding unused exports in your JavaScript and TypeScript projects is one of\nKnip's core features. And it comes with even more features to identify and\nremove clutter to keep your projects in great shape.\n\n## Why are unused exports a problem?\n\nHaving unused exports in your codebase is problematic for several reasons:\n\n- They increase bundle sizes if not properly eliminated by tree-shaking.\n- They clutter the codebase and make it harder to navigate and understand.\n- They mislead developers into thinking certain code is used when it's not.\n- They make refactoring and maintaining the codebase more difficult.\n- They slow down tooling that analyze the codebase, such as bundlers, linters\n  and type checkers.\n- They may represent dead code that is no longer needed but hasn't been cleaned\n  up.\n\n## How do I find unused exports?\n\nKnip is a powerful tool that can help you find and remove unused exports in your\nJavaScript and TypeScript projects. It analyzes the codebase, identifies exports\nthat are not imported anywhere, and reports them.\n\n[Get started and install Knip][1] to run it on your project. Knip will scan your\nfiles and provide a detailed report of unused exports, and much more.\n\n<div style=\"display: flex; justify-content: center; margin: 4rem auto;\">\n  <img src=\"/logo.svg\" alt=\"Logo of Knip, to find unused dependencies, exports and files\" class=\"logo-border\" />\n</div>\n\n## How does Knip identify unused exports?\n\nKnip performs both static and dynamic analysis to determine which exports are\nactually being used in your codebase. It looks at import statements, export\nusage, and [a lot more code patterns][2] to identify unused exports.\n\nKnip supports JavaScript and TypeScript projects, and handles both [CommonJS][3]\nand ES Modules syntax.\n\n## Can Knip remove unused exports?\n\nYes, Knip not only finds unused exports but can also remove them for you. Run\nKnip with the `--fix` flag to enable [the auto-fix feature][4], and it will\nmodify your source code and remove the unused exports.\n\nIt's always recommended to review the changes made by Knip before committing\nthem to ensure no unintended modifications were made.\n\n## Can Knip handle large codebases?\n\nAbsolutely. Knip supports [monorepos with workspaces][5] to efficiently analyze\nlarge monorepos. This makes it easier and more fun to manage and optimize large\nmulti-package projects.\n\n## Does Knip work with my favorite editor or IDE?\n\nKnip is a command-line tool that runs independently of your editor or IDE.\nHowever, if you run Knip inside an integrated IDE terminal, the report contains\nfile names and positions in a format IDEs like VS Code and WebStorm understand\nto easily navigate around.\n\n## How is Knip different from ESLint for finding unused exports?\n\nWhile linters like ESLint can find unused imports and variables within\nindividual files, Knip analyzes the entire project to determine which exports\nare actually unused. By building [a comprehensive module graph][6], Knip\nidentifies exports that are not imported or used anywhere in the codebase. This\nallows Knip to catch unused exports and dead code that ESLint and other linters\nwould miss.\n\nAlso see [Why isn't Knip an ESLint plugin?][7]\n\n[1]: ../overview/getting-started.mdx\n[2]: ../reference/faq.md#what-does-knip-look-for-in-source-files\n[3]: ../guides/working-with-commonjs.md\n[4]: ../features/auto-fix.mdx\n[5]: ../features/monorepos-and-workspaces.md\n[6]: ../reference/faq.md#whats-in-the-graph\n[7]: ../reference/faq.md#why-isnt-knip-an-eslint-plugin\n","packages/docs/src/content/docs/writing-a-plugin/argument-parsing.md":"---\ntitle: Argument Parsing\ndescription: Reference for a Knip plugin `arg` object to parse a tool's command-line arguments and find dependencies and entry files in scripts.\n---\n\nSome plugins have an `arg` object in their implementation. It's a way for\nplugins to customize how command-line arguments are parsed for their tool's\nexecutables. Argument parsing in plugins help Knip identify dependencies and\nentry files from scripts.\n\nKnip parses these arguments with a built-in parser. The options below customize\nhow a tool's scripts are parsed. Here's an example:\n\n```ts\nconst args = {\n  args: (args) => args  // modify/filter the array of raw args\n  config: true,         // shorthand to add `--config [config file]` (and shortcut `-c`) as a `config` file\n  fromArgs: ['exec'],   // re-parse what's behind `exec` as a new script\n};\n\nexport default {\n  title: 'my-plugin',\n  args\n}\n```\n\nAlso see [type definitions][1] and [examples in existing plugins][2].\n\n- [alias][3]\n- [args][4]\n- [binaries][5]\n- [boolean][6]\n- [config][7]\n- [fromArgs][8]\n- [nodeImportArgs][9]\n- [positional][10]\n- [resolve][11]\n- [resolveInputs][12]\n- [string][13]\n\n## alias\n\nDefine aliases.\n\nExample:\n\n```ts\n{\n  require: ['r'];\n}\n```\n\nAlso see [nodeImportArgs][9].\n\n## args\n\nModify or filter arguments before parsing. For edge cases preprocessing is\nuseful, e.g. if the parser has trouble parsing or to modify/discard arguments.\n\nExample:\n\n```ts\n{\n  args: (args: string[]) => args.filter(arg => arg !== 'omit');\n}\n```\n\n## binaries\n\nExecutables for the dependency.\n\nExample:\n\n```ts\n{\n  binaries: ['tsc'];\n}\n```\n\nDefault: plugin name, e.g. for the ESLint plugin the value is `[\"eslint\"]`\n\n## boolean\n\nMark arguments as boolean. By default, arguments are expected to have string\nvalues.\n\n## config\n\nDefine arguments that contain the configuration file path. Usually you'll want\nto set aliases too. Use `true` for shorthand to set `alias` + `string` +\n`config`.\n\nExample:\n\n```ts\n{\n  config: true;\n}\n```\n\nThe `tsup` plugin has this. Now `tsup --config tsup.client.json` will have\n`tsup.client.json` go through `resolveConfig` (also `-c` alias).\n\nExample:\n\n```ts\n{\n  config: ['p'];\n}\n```\n\nThis will mark e.g. `tsc -p tsconfig.lib.json` as a configuration file and it\nwill be handled by `resolveConfig` of the (typescript) plugin.\n\n## fromArgs\n\nParse return value as a new script. Can be a an array of strings, or function\nthat returns an array of strings and those values will be parsed separately.\n\nExample:\n\n```ts\n{\n  fromArgs: ['exec'];\n}\n```\n\nThen this script:\n\n```sh\nnodemon --exec \"node index.js\"\n```\n\nWill have `\"node index.js\"` being parsed as a new script.\n\n## nodeImportArgs\n\nSet to `true` as a shorthand for this [alias][3]:\n\n```ts\n{\n  import: ['r', 'experimental-loader', 'require', 'loader']\n}\n```\n\nExample:\n\n```ts\n{\n  nodeImportArgs: true;\n}\n```\n\n## positional\n\nSet to `true` to use the first positional argument as an entry point.\n\nExample:\n\n```ts\n{\n  positional: true;\n}\n```\n\nThe `tsx` plugin has this and `\"tsx script.ts\"` as a script will result in the\n`script.ts` file being an entry point.\n\n## resolve\n\nList of arguments to resolve to a dependency or entry file path.\n\nExample:\n\n```ts\n{\n  resolve: ['plugin'];\n}\n```\n\nNow for a script like `\"program --plugin package\"` this will result in\n`\"package\"` being resolved as a dependency.\n\n## resolveInputs\n\nReturn inputs from parsed arguments\n\n```ts\n{\n  resolveInputs: (parsed: ParsedArgs) =>\n    parsed['flag'] ? [toDependency('package')] : [];\n}\n```\n\n## string\n\nMark arguments as string. This is the default, but number-looking arguments are\nreturned as numbers.\n\n[1]: https://github.com/webpro-nl/knip/blob/main/packages/knip/src/types/args.ts\n[2]: https://github.com/search?q=repo%3Awebpro-nl%2Fknip++path%3Apackages%2Fknip%2Fsrc%2Fplugins+%22const+args+%3D%22&type=code\n[3]: #alias\n[4]: #args\n[5]: #binaries\n[6]: #boolean\n[7]: #config\n[8]: #fromargs\n[9]: #nodeimportargs\n[10]: #positional\n[11]: #resolve\n[12]: #resolveinputs\n[13]: #string\n","packages/docs/src/content/docs/writing-a-plugin/index.md":"---\ntitle: Writing A Plugin\ndescription: Tutorial for writing a Knip plugin with entry, config, resolveConfig, resolveFromAST and resolve to find entry files and dependencies.\n---\n\nPlugins provide Knip with entry files and dependencies it would be unable to\nfind otherwise. Plugins always do at least one of the following:\n\n1. Define entry file patterns\n2. Find dependencies in configuration files\n\nKnip v5.1.0 introduced a new plugin API, which makes them a breeze to write and\nmaintain.\n\n:::tip[The new plugin API]\n\nEasy things should be easy, and complex things possible.\n\n:::\n\nThis tutorial walks through example plugins so you'll be ready to write your\nown! The following examples demonstrate the elements a plugin can implement.\n\nThere's a handy command available to easily [create a new plugin][1] and get\nstarted right away.\n\n## Example 1: entry\n\nLet's dive right in. Here's the entire source code of the Tailwind plugin:\n\n```ts\nimport type { IsPluginEnabled, Plugin } from '../../types/config.js';\nimport { hasDependency } from '../../util/plugin.js';\n\nconst title = 'Tailwind';\n\nconst enablers = ['tailwindcss'];\n\nconst isEnabled: IsPluginEnabled = ({ dependencies }) =>\n  hasDependency(dependencies, enablers);\n\nconst entry = ['tailwind.config.{js,cjs,mjs,ts}'];\n\nconst plugin: Plugin = {\n  title,\n  enablers,\n  isEnabled,\n  entry,\n};\n\nexport default plugin;\n```\n\nYes, that's the entire plugin! Let's go over each item one by one:\n\n### 1. `title`\n\nThe title of the plugin displayed in the [list of plugins][2] and in debug\noutput.\n\n### 2. `enablers`\n\nAn array of strings to match one or more dependencies in `package.json` so the\n`isEnabled` function can determine whether the plugin should be enabled or not.\nRegular expressions are allowed as well.\n\n### 3. `isEnabled`\n\nThis function checks whether a match is found in the `dependencies` or\n`devDependencies` in `package.json`. The plugin is enabled if the dependency is\nlisted in `package.json`.\n\nThis function can be kept straightforward with the `hasDependency` helper.\n\n### 4. `entry`\n\nThis plugin exports `entry` file patterns. This means that if the Tailwind\nplugin is enabled, then `tailwind.config.*` files are added as entry files. A\nTailwind configuration file does not contain anything particular, so adding it\nas an `entry` to treat it as a regular source file is enough.\n\nThe next example shows how to handle a tool that has its own particular\nconfiguration object.\n\n## Example 2: config\n\nHere's the full source code of the `nyc` plugin:\n\n```ts\nimport { toDeferResolve } from '../../util/input.js';\nimport { hasDependency } from '../../util/plugin.js';\nimport type { NycConfig } from './types.js';\nimport type {\n  IsPluginEnabled,\n  Plugin,\n  ResolveConfig,\n} from '../../types/config.js';\n\nconst title = 'nyc';\n\nconst enablers = ['nyc'];\n\nconst isEnabled: IsPluginEnabled = ({ dependencies }) =>\n  hasDependency(dependencies, enablers);\n\nconst config = [\n  '.nycrc',\n  '.nycrc.{json,yml,yaml}',\n  'nyc.config.js',\n  'package.json',\n];\n\nconst resolveConfig: ResolveConfig<NycConfig> = config => {\n  const extend = config?.extends ?? [];\n  const requires = config?.require ?? [];\n  return [extend, requires].flat().map(id => toDeferResolve(id));\n};\n\nconst plugin: Plugin = {\n  title,\n  enablers,\n  isEnabled,\n  config,\n  resolveConfig,\n};\n\nexport default plugin;\n```\n\nHere's an example `config` file that will be handled by this plugin:\n\n```json title=\".nycrc.json\"\n{\n  \"extends\": \"@istanbuljs/nyc-config-typescript\",\n  \"check-coverage\": true\n}\n```\n\nCompared to the first example, this plugin has two new variables:\n\n### 5. `config`\n\nThe `config` array contains all possible locations of the config file for the\ntool. Knip loads matching files and passes the results (i.e. its default export)\ninto the `resolveConfig` function:\n\n### 6. `resolveConfig`\n\nThis function receives the exported value of the `config` file, and executes the\n`resolveConfig` function with this object. The plugin should return the entry\npaths and dependencies referenced in this object.\n\nKnip supports JSON, YAML, TOML, JavaScript and TypeScript config files. Files\nwithout an extension are provided as plain text strings.\n\n:::tip[Should I implement resolveConfig?]\n\nYou should implement `resolveConfig` if any of these are true:\n\n- The `config` file contains one or more options that represent [entry\n  points][3]\n- The `config` file references dependencies by strings (not import statements)\n\n:::\n\n## Example 3: entry paths\n\n### 7. entry and production\n\nSome tools operate mostly on entry files, some examples:\n\n- Mocha looks for test files at `test/*.{js,cjs,mjs}`\n- Storybook looks for stories at `*.stories.@(mdx|js|jsx|tsx)`\n\nAnd some of those tools allow to configure those locations and patterns in\nconfiguration files, such as `next.config.js` or `vite.config.ts`. If that's the\ncase we can define `resolveConfig` in our plugin to take this from the\nconfiguration object and return it to Knip:\n\nHere's an example from the Mocha plugin:\n\n```ts\nconst entry = ['**/test/*.{js,cjs,mjs}'];\n\nconst resolveConfig: ResolveConfig<MochaConfig> = localConfig => {\n  const entryPatterns = localConfig.spec ? [localConfig.spec].flat() : entry;\n  return entryPatterns.map(id => toEntry(id));\n};\n\nexport default {\n  entry,\n  resolveConfig,\n};\n```\n\nWith Mocha, you can configure `spec` file patterns. The result of implementing\n`resolveConfig` is that users don't need to duplicate this configuration in both\nthe tool (e.g. Mocha) and Knip.\n\nUse `production` entries to target source files that represent production code.\n\n:::tip\n\nRegardless of the presence of `resolveConfig`, add `entry` and `production` to\nthe default export so they will be displayed in the plugin's documentation as\ndefault values.\n\n:::\n\n## Example 4: Use the AST directly\n\nIf the `resolveConfig` function is implemented, Knip loads the configuration\nfile and passes the default-exported object to this plugin function. However,\nthat object might then not contain the information we need.\n\nHere's an example `astro.config.ts` configuration file with a Starlight\nintegration:\n\n```ts\nimport starlight from '@astrojs/starlight';\nimport { defineConfig } from 'astro/config';\n\nexport default defineConfig({\n  integrations: [\n    starlight({\n      components: {\n        Head: './src/components/Head.astro',\n        Footer: './src/components/Footer.astro',\n      },\n    }),\n  ],\n});\n```\n\nWith Starlight, components can be defined to override the default internal ones.\nThey're not otherwise referenced in your source code, so you'd have to manually\nadd them as entry files ([Knip itself did this][4]).\n\nIn the Astro plugin, there's no way to access this object containing\n`components` to add the component files as entry files if we were to try:\n\n```ts\nconst resolveConfig: ResolveConfig<AstroConfig> = async config => {\n  console.log(config); //  ¯\\_(ツ)_/¯\n};\n```\n\nThis is why plugins can implement the `resolveFromAST` function.\n\n### 8. resolveFromAST\n\nLet's take a look at the Astro plugin implementation. This example assumes some\nfamiliarity with Abstract Syntax Trees (AST). Knip provides AST helpers to make\nimplementing plugins more fun and a little less tedious.\n\nAnyway, let's dive in. Here's how we're adding the Starlight `components` paths\nto the default `production` file patterns:\n\n```ts\nimport type { Program } from 'oxc-parser';\nimport {\n  findCallArg,\n  getDefaultImportName,\n  getImportMap,\n  getPropertyValues,\n} from '../../typescript/ast-helpers.ts';\n\nconst title = 'Astro';\n\nconst production = [\n  'src/pages/**/*.{astro,mdx,js,ts}',\n  'src/content/**/*.mdx',\n  'src/middleware.{js,ts}',\n  'src/actions/index.{js,ts}',\n];\n\nconst getComponentPaths = (program: Program) => {\n  const importMap = getImportMap(program);\n  const importName = getDefaultImportName(importMap, '@astrojs/starlight');\n  if (!importName) return new Set<string>();\n  const starlightConfig = findCallArg(program, importName);\n  return getPropertyValues(starlightConfig, 'components');\n};\n\nconst resolveFromAST: ResolveFromAST = (program: Program) => {\n  const componentPaths = getComponentPaths(program);\n  return [...production, ...componentPaths].map(id => toProductionEntry(id));\n};\n\nconst plugin: Plugin = {\n  title,\n  production,\n  resolveFromAST,\n};\n\nexport default plugin;\n```\n\n## None Of The Above\n\n### 9. `resolve`\n\nIf there is no configuration file to parse or there is a need for customization,\nuse `resolve`:\n\n```ts\nconst resolve: Resolve = async options => {\n  return toDependency('troublesome', { optional: true });\n};\n```\n\n## Inputs\n\nYou may have noticed functions like `toDeferResolve` and `toEntry`. They're a\nway for plugins to tell what they've found and how Knip should handle those. The\nmore precision a plugin can provide here, the better results and performance\nwill be.\n\nFind all the details over at [Writing A Plugin → Inputs][5].\n\n## Argument Parsing\n\nAs part of the [script parser][6], Knip parses command-line arguments. Plugins\ncan implement the `arg` object to add custom argument parsing tailored to the\ntool.\n\nRead more in [Writing A Plugin → Argument Parsing][7].\n\n## Create a new plugin\n\nThe easiest way to create a new plugin is to use the `create-plugin` script:\n\n```sh\ncd packages/knip\npnpm create-plugin --name tool\n```\n\nThis adds source and test files and fixtures to get you started. Keep fixtures\ntidy, remove clutter that isn't required to test the plugin properly. E.g. using\na starterkit, script or wizard often creates more than what we need here.\n\nThe script adds the plugin to the JSON Schema and type definitions.\n\nRun the test for your new plugin using one of the following commands:\n\n```sh\nnode --test test/plugins/tool.test.ts\nbun test test/plugins/tool.test.ts\n```\n\nYou're ready to implement and submit a new Knip plugin! 🆕 🎉\n\n## Wrapping Up\n\nFeel free to check out the implementation of other similar plugins, and borrow\nideas and code from those!\n\nThe documentation website takes care of generating the [plugin list and the\nindividual plugin pages][2] from the exported plugin values.\n\nThanks for reading. If you have been following this guide to create a new\nplugin, this might be the right time to open a pull request!\n\n[1]: #create-a-new-plugin\n[2]: ../reference/plugins.md\n[3]: ../explanations/plugins.md#entry-files-from-config-files\n[4]: https://github.com/webpro-nl/knip/blob/6a6954386b33ee8a2919005230a4bc094e11bc03/knip.json#L12\n[5]: ../writing-a-plugin/inputs.md\n[6]: ../features/script-parser.md\n[7]: ../writing-a-plugin/argument-parsing.md\n","packages/docs/src/content/docs/writing-a-plugin/inputs.md":"---\ntitle: Inputs\ndescription: Reference for Knip plugin input functions like toEntry, toDependency, toDeferResolve, toConfig, toBinary and toAlias, plus their options.\n---\n\nYou may have noticed functions like `toDeferResolve` and `toEntry`. They're a\nway for plugins to tell what they've found and how Knip should handle those. The\nmore precise a plugin can be, the better it is for results and performance.\nHere's an overview of all input type functions:\n\n- [toEntry][1]\n- [toProductionEntry][2]\n- [toProject][3]\n- [toDependency][4]\n- [toProductionDependency][5]\n- [toDeferResolve][6]\n- [toDeferResolveEntry][7]\n- [toConfig][8]\n- [toBinary][9]\n- [toAlias][10]\n- [Options][11]\n\n## toEntry\n\nAn `entry` input is just like an `entry` in the configuration. It should either\nbe an absolute or relative path, and glob patterns are allowed.\n\n## toProductionEntry\n\nA production `entry` input is just like an `production` in the configuration. It\nshould either be an absolute or relative path, and it can have glob patterns.\n\n## toProject\n\nA `project` input is the equivalent of `project` patterns in the configuration.\nIt should either be an absolute or relative path, and (negated) glob patterns\nare allowed.\n\n## toDependency\n\nThe `dependency` indicates the entry is a dependency, belonging in either the\n`\"dependencies\"` or `\"devDependencies\"` section of `package.json`. Use it for\npackage names referenced from configuration, such as a plugin or transformer a\ntool loads at build time.\n\nKnip marks the package as referenced, and reports it as an unlisted dependency\nif it isn't listed at all. Such a reference is development-only: in [production\nmode][12] the package is still marked as referenced, but an unlisted one is no\nlonger reported.\n\n## toProductionDependency\n\nThe production `dependency` indicates the entry is a production dependency,\nexpected to be listed in `\"dependencies\"`. Unlike [toDependency][4] it's also\nreported as unlisted in production mode.\n\n## toDeferResolve\n\nThe `deferResolve` input type is used to defer the resolution of a specifier.\nThis could be resolved to a dependency or an entry file. For instance, the\nspecifier `\"input\"` could be resolved to `\"input.js\"`, `\"input.tsx\"`,\n`\"input/index.js\"` or the `\"input\"` package name. Local files are added as entry\nfiles, package names are external dependencies.\n\nIf this does not lead to a resolution, the specifier will be reported under\n\"unresolved imports\".\n\n## toDeferResolveEntry\n\nThe `deferResolveEntry` input type is similar to `deferResolve`, but it's used\nfor entry files only (not dependencies) and unresolved inputs are ignored. It's\ndifferent from `toEntry` as glob patterns are not supported.\n\n## toConfig\n\nThe `config` input type is a way for plugins to reference a configuration file\nthat should be handled by a different plugin. The specifier is a path to that\nfile.\n\nFor instance, `angular.json` has `tsConfig` and `karmaConfig` options pointing\nto files the TypeScript and Karma plugins know how to handle, so the Angular\nplugin hands them over:\n\n```ts\ntoConfig('typescript', 'tsconfig.app.json');\ntoConfig('karma', 'karma.conf.js');\n```\n\n## toBinary\n\nThe `binary` input type isn't used by plugins directly, but by the shell script\nparser (through the `getInputsFromScripts` helper). Think of GitHub Actions\nworkflow YAML files or husky scripts. Using this input type, a binary is\n\"assigned\" to the dependency that has it as a `\"bin\"` in their `package.json`.\n\n## toAlias\n\nThe `alias` input type adds path aliases to the core module resolver. They're\nadded to `compilerOptions.paths` so the syntax is identical.\n\n## Options\n\nWhen creating inputs from specifiers, an extra `options` object as the second\nargument can be provided.\n\n### dir\n\nThe optional `dir` option assigns the input to a different workspace. For\ninstance, GitHub Action workflows are always stored in the root workspace, and\nsupport `working-directory` in job steps. For example:\n\n```yaml\njobs:\n  stylelint:\n    runs-on: ubuntu-latest\n    steps:\n      - run: npx esbuild\n        working-directory: packages/app\n```\n\nThe GitHub Action plugin understands `working-directory` and adds this `dir` to\nthe input:\n\n```ts\ntoDependency('esbuild', { dir: 'packages/app' });\n```\n\nKnip now understands `esbuild` is a dependency of the workspace in the\n`packages/app` directory.\n\n### optional\n\nUse the `optional` flag to indicate the dependency is optional. Then, a\ndependency won't be flagged as unlisted if it isn't.\n\n### isTypeOnly\n\nUse `isTypeOnly` when only the types of a package are used, such as the packages\nlisted in `compilerOptions.types`. A `@types/pkg` dependency then satisfies the\nreference on its own, without `pkg` itself being installed. Don't use it for\npackages the tool actually loads, even if it does so only at build time.\n\n### allowIncludeExports\n\nBy default, exports of entry files such as `src/index.ts` or the files in\n`package.json#exports` are not reported as unused. When using the\n`--include-entry-exports` flag or `isIncludeExports: true` option, unused\nexports on such entry files are also reported.\n\nExports of entry files coming from plugins are not included in the analysis,\neven with the option enabled. This is because certain tools and frameworks\nconsume named exports from entry files, causing false positives.\n\nThe `allowIncludeExports` option allows the exports of entry files to be\nreported as unused when using `--include-entry-exports`. This option is\ntypically used with the [toProductionEntry][2] input type.\n\nExample:\n\n```ts\ntoProductionEntry('./entry.ts', { allowIncludeExports: true });\n```\n\n[1]: #toentry\n[2]: #toproductionentry\n[3]: #toproject\n[4]: #todependency\n[5]: #toproductiondependency\n[6]: #todeferresolve\n[7]: #todeferresolveentry\n[8]: #toconfig\n[9]: #tobinary\n[10]: #toalias\n[11]: #options\n[12]: ../features/production-mode.md\n","packages/docs/tsconfig.json":"{\n  \"extends\": \"astro/tsconfigs/strict\"\n}\n","packages/knip/README.md":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fknip%2FREADME.md -->","packages/language-server/README.md":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Flanguage-server%2FREADME.md -->","packages/mcp-server/README.md":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fmcp-server%2FREADME.md -->","packages/vscode-knip/README.md":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fvscode-knip%2FREADME.md -->"},"files":{".github/copilot-instructions.md":"See [AGENTS.md][1].\n\n[1]: ../AGENTS.md\n","AGENTS.md":"# Knip\n\nKnip is a tool to find and fix unused dependencies, exports and files in\nJavaScript and TypeScript projects.\n\n## Project overview\n\n- Monorepo, managed with pnpm\n- Main package is core in `packages/knip` (TypeScript)\n- Language Server in `packages/language-server` (JS + JSDoc for types)\n- VS Code Extension in `packages/vscode-knip` (JS + JSDoc for types)\n- [Documentation][1] content in `packages/docs` (Astro + MD/MDX)\n- Tracked `.agents` guides live in the checkout; there might be shared lessons and tasks in the workspace's `.agents`.\n\n## Code style\n\n- Performance is key, both high level (design) and low level (impl).\n- Avoid redundant code and abstractions; avoid unnecessary complexity and nesting.\n- Concise one-liners are fine, but prioritize clarity over cleverness.\n- Don't add comments to code, unless explicitly asked for.\n- Prefer AST-based tools and codemods (jscodeshift) over manual or regex-based refactors — except for tiny edits.\n- JavaScript\n  - Prefer plain `for..in/of` loops over iterator methods like `map`/`reduce`.\n- TypeScript\n  - Avoid `any` and type casting (`as`).\n  - Avoid runtime overhead just to get the types right.\n- Lint and check formatting from root: `pnpm run ci`; format with `pnpm fmt`\n- Format Markdown/MDX with `pnpm remark` in `packages/docs` (auto-numbers link refs, validates links)\n\n## Domain Knowledge\n\n- Unused file → unused exports/dependencies is a chain, not a bug\n- Non-JS/TS files (.css, .mdx, .vue) enter the graph via (usually plugin-registered) compilers (`registerCompilers`)\n- Library-specific AST patterns are caught by plugin-registered visitors (`registerVisitors`)\n- Use `--performance` or `--performance-fn [name]` to profile (→ [timerify][2])\n- If creating, modifying, or reviewing a plugin, read [PLUGINS.md][3] first.\n- If modifying core module graph, AST traversal, or CLI sequence, read [MODULE-GRAPH.md][4] first.\n- For issues re. exported identifiers (following refs, shadowing, `ignoreExportsUsedInFile`), see [EXPORTS.md][5].\n- Before any significant performance tuning, consult [PERFORMANCE.md][6].\n- When modifying or reviewing built-in compilers, read [COMPILERS.md][10].\n- For test/fixture structure, conventions, and where a new test goes, see [TESTS.md][7].\n\n## Issues and Pull Requests\n\n- Use `gh` for PR metadata, diffs, comments, and checks. Reuse retrieved evidence; browse upstream documentation separately.\n- When given a bug report, first confirm the behavior is actually wrong. Reproduce, then check if the reported behavior is correct-by-design before writing any fix.\n- Find repositories/CodeSandbox/StackBlitz source files and local fixtures to actually reproduce the issue at hand.\n- To fetch a stackblitz.com reproduction: `pnpx stackblitz-zip https://stackblitz.com/edit/{name} {filename}.zip`\n- For a fix, revert the source change and confirm the new test fails for the reported reason.\n- For a new plugin or a change in how a tool finds files, verify against the tool's source, not only its docs, and run Knip on the tool's examples or starters when available.\n- Follow the [AI contribution policy][11]: before opening an issue or PR, make sure the person you work for understands and stands behind it. Keep descriptions concise.\n\n## Run & Debug\n\nImportant: debug, don't guess.\n\nRun the CLI directly using `node` or `bun`. This document shows `knip` in\ncommands for consistency. Replace it with `node (path/to/)src/cli.ts` or\n`bun (path/to/)src/cli.ts` and keep using what works.\n\n- Run `knip` directly in a fixture or temp directory (over creating test scripts that import the `main` function).\n- Knip requires `package.json` in root dir.\n- Enable [debug & helpers][8] with `--debug` (not `DEBUG=`). Warning: noisy.\n- Use [trace][9] to debug\n  - exported identifiers (`knip --trace-export [name] --trace-file [file]`)\n  - external dependencies (`knip --trace-dependency [name] --workspace [dir]`)\n\n## Test\n\nPrefer TDD: add or update tests (and fixtures) before implementing.\n\nPrefer `bun` over `node` for speed. Don't run all tests at once (slow & noisy).\nStart out with running the relevant test(s) first:\n\n```sh\ncd packages/knip\nbun test test/util/get-inputs-from-scripts.test.ts\nnode --test test/commonjs.test.ts\n```\n\nRun smoke tests with Bun:\n\n```sh\ncd packages/knip\npnpm test --runtime bun --smoke\n```\n\nRun smoke tests with Node.js:\n\n```sh\ncd packages/knip\nnode --test test/commonjs.test.ts\npnpm test --runtime node --smoke\n```\n\nBuild core package and run all tests only if there are changes in auto-fix,\nformatting and reporter related functionality:\n\n```sh\ncd packages/knip\npnpm build\npnpm test\n```\n\nSee [TESTS.md][7] for test and fixture conventions and placements.\n\n## Build\n\nTo type-check `knip` with `tsc`:\n\n```sh\ncd packages/knip\npnpm build\n```\n\n[1]: https://knip.dev\n[2]: ./packages/knip/src/util/Performance.ts\n[3]: ./.agents/PLUGINS.md\n[4]: ./.agents/MODULE-GRAPH.md\n[5]: ./.agents/EXPORTS.md\n[6]: ./.agents/PERFORMANCE.md\n[7]: ./.agents/TESTS.md\n[8]: ./packages/knip/src/util/debug.ts\n[9]: ./packages/docs/src/content/docs/guides/troubleshooting.md#trace\n[10]: ./.agents/COMPILERS.md\n[11]: ./AI_POLICY.md\n","CLAUDE.md":"AGENTS.md","packages/create-config/README.md":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fcreate-config%2FREADME.md -->","packages/docs/README.md":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fdocs%2FREADME.md -->","packages/docs/mock/contributors.json":"[\n  {\n    \"login\": \"webpro\",\n    \"id\": 456426,\n    \"node_id\": \"MDQ6VXNlcjQ1NjQyNg==\",\n    \"avatar_url\": \"https://avatars.githubusercontent.com/u/456426?v=4\",\n    \"gravatar_id\": \"\",\n    \"url\": \"https://api.github.com/users/webpro\",\n    \"html_url\": \"https://github.com/webpro\",\n    \"followers_url\": \"https://api.github.com/users/webpro/followers\",\n    \"following_url\": \"https://api.github.com/users/webpro/following{/other_user}\",\n    \"gists_url\": \"https://api.github.com/users/webpro/gists{/gist_id}\",\n    \"starred_url\": \"https://api.github.com/users/webpro/starred{/owner}{/repo}\",\n    \"subscriptions_url\": \"https://api.github.com/users/webpro/subscriptions\",\n    \"organizations_url\": \"https://api.github.com/users/webpro/orgs\",\n    \"repos_url\": \"https://api.github.com/users/webpro/repos\",\n    \"events_url\": \"https://api.github.com/users/webpro/events{/privacy}\",\n    \"received_events_url\": \"https://api.github.com/users/webpro/received_events\",\n    \"type\": \"User\",\n    \"site_admin\": false,\n    \"contributions\": 1282\n  }\n]\n","packages/docs/package.json":"{\n  \"name\": \"@knip/docs\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"description\": \"Documentation for Knip, hosted at knip.dev\",\n  \"homepage\": \"https://knip.dev\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"github:webpro-nl/knip\",\n    \"directory\": \"packages/docs\"\n  },\n  \"type\": \"module\",\n  \"scripts\": {\n    \"prebuild\": \"node ./scripts/generate-plugin-docs.ts\",\n    \"build\": \"astro check && astro build\",\n    \"postbuild\": \"[ \\\"$CF_PAGES\\\" = \\\"1\\\" ] && find dist -mindepth 2 -type f -name 'index.html' -exec bash -c 'f=\\\"$1\\\"; d=$(dirname \\\"$f\\\"); bn=$(basename \\\"$d\\\"); mv -v \\\"$f\\\" \\\"$d/../$bn.html\\\"' _ {} \\\\; && find dist -mindepth 1 -type d -empty -print -delete || true\",\n    \"dev\": \"astro dev\",\n    \"remark\": \"remark README.md 'src/content/docs/**/*.md' --verbose -o && mdxlint 'src/content/docs/**/*.mdx' --verbose -o\"\n  },\n  \"dependencies\": {\n    \"@astro-community/astro-embed-youtube\": \"0.5.10\",\n    \"@astrojs/starlight\": \"0.42.6\",\n    \"@octokit/graphql\": \"^9.0.5\",\n    \"astro\": \"7.3.8\",\n    \"sharp\": \"0.35.5\"\n  },\n  \"devDependencies\": {\n    \"@astrojs/check\": \"0.9.10\",\n    \"@astrojs/markdown-satteri\": \"0.4.3\",\n    \"picocolors\": \"^1.1.1\",\n    \"satteri\": \"0.10.5\",\n    \"starlight-blog\": \"^0.30.2\",\n    \"typescript\": \"6.0.3\"\n  },\n  \"engines\": {\n    \"node\": \">=22.12.0\"\n  }\n}\n","packages/docs/public/manifest.json":"{\n  \"name\": \"Knip\",\n  \"short_name\": \"Knip\",\n  \"icons\": [\n    {\n      \"src\": \"/favicon.svg\",\n      \"type\": \"image/svg+xml\",\n      \"sizes\": \"512x512\"\n    },\n    {\n      \"src\": \"/icon-192x192.png\",\n      \"sizes\": \"192x192\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icon-512x512.png\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/png\"\n    }\n  ],\n  \"theme_color\": \"#fbfbfb\",\n  \"background_color\": \"#f56e0f\",\n  \"display\": \"standalone\",\n  \"scope\": \"/\",\n  \"start_url\": \"/overview/getting-started/\"\n}\n","packages/docs/src/assets/testimonials.json":"{\n  \"data\": [\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"2061954856638967917\",\n      \"author_id\": \"5\",\n      \"created_at\": \"2026-06-02T23:35:21.000Z\",\n      \"text\": \"Knip is still my all time favorite piece of software.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"2061775207518343569\",\n      \"author_id\": \"20\",\n      \"created_at\": \"2026-06-02T11:41:30.000Z\",\n      \"text\": \"adding knip to our CI after deleting like 100k LOC of dead code was a game changer\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3mn5ccucpvk2z\",\n      \"author_id\": \"13\",\n      \"created_at\": \"2026-05-31T09:54:50.000Z\",\n      \"text\": \"Knip is essential tooling.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"2059921462891622770\",\n      \"author_id\": \"21\",\n      \"created_at\": \"2026-05-28T08:55:22.000Z\",\n      \"text\": \"Please dont ask your ai agent to find unused, dead code and remove them. Instead for js/ts projects install knip and see the magic it does. Save tokens🙏😂\"\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webpro.nl\"\n          }\n        ],\n        \"urls\": []\n      },\n      \"id\": \"3mgkwe4digs2l\",\n      \"author_id\": \"19\",\n      \"created_at\": \"2026-03-25T12:00:00.000Z\",\n      \"text\": \"Two things about knip.dev I don't get:\\n- how did we live without it for so long\\n- how did @webpro.nl NAIL the timing? Gave it to us right when AI started to produce left-overs in our codes faster than we ever could.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"cdn.bsky.app/img/dummy-02\",\n            \"display_url\": \"cdn.bsky.app/img/julien.deniau.me\",\n            \"media_key\": \"4\"\n          }\n        ]\n      },\n      \"id\": \"3mdrubg3y5c2z\",\n      \"author_id\": \"11\",\n      \"created_at\": \"2026-02-01T07:57:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Done on a mono-repo in two times.\\nWhat's impressive is that there were no false positive!\\ncdn.bsky.app/img/dummy-02\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/EwIeRiHaXf\",\n            \"display_url\": \"pic.x.com/EwIeRiHaXf\",\n            \"media_key\": \"6\"\n          }\n        ]\n      },\n      \"id\": \"2017122504914161979\",\n      \"author_id\": \"16\",\n      \"created_at\": \"2026-01-30T06:27:00.000Z\",\n      \"text\": \"Good morning 🌄\\nA tool I discovered lately.\\nIf you care about clean codebases, this one's a gem 💎\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3mcky5ps3r22p\",\n      \"author_id\": \"12\",\n      \"created_at\": \"2026-01-16T20:53:09.000Z\",\n      \"text\": \"Knip is a cracking-looking open source tool for trimming unused JavaScript.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"cdn.bsky.app/img/dummy-03\",\n            \"display_url\": \"cdn.bsky.app/img/patak.dev\",\n            \"media_key\": \"5\"\n          }\n        ]\n      },\n      \"id\": \"3mcjtmv35wc2y\",\n      \"author_id\": \"15\",\n      \"created_at\": \"2026-01-16T09:59:29.000Z\",\n      \"attachments\": {},\n      \"text\": \"From the report, we could improve the situation if we stop sending unused JavaScript. @webpro.nl is doing an incredible job growing the usage of knip.dev, and that should hopefully make a dent in the future.\\ncdn.bsky.app/img/dummy-03\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://knip.dev/blog/for-editors-and-agents\",\n            \"expanded_url\": \"https://knip.dev/blog/for-editors-and-agents\",\n            \"display_url\": \"knip.dev/blog/for-edi...\"\n          }\n        ]\n      },\n      \"id\": \"3mby3zkzhfs2t\",\n      \"author_id\": \"13\",\n      \"created_at\": \"2026-01-09T08:41:49.000Z\",\n      \"text\": \"The VSCode/Cursor extension is ace!\\nAnd you can use the Knip MCP to create the config file.\\nIt works for Svelte as well.\\nKnip is really really good 🙏\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/6rcslWBqIV\",\n            \"display_url\": \"pic.x.com/6rcslWBqIV\",\n            \"media_key\": \"6\"\n          }\n        ]\n      },\n      \"id\": \"2007481125610914217\",\n      \"author_id\": \"17\",\n      \"created_at\": \"2026-01-03T15:56:00.000Z\",\n      \"attachments\": { \"media_keys\": [\"6\"] },\n      \"text\": \"This is both embarrassing and satisfying after running @Knip https://t.co/6rcslWBqIV\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/hneEWMqdnm\",\n            \"expanded_url\": \"https://knip.dev\",\n            \"display_url\": \"Knip.dev\"\n          }\n        ]\n      },\n      \"id\": \"2007221517562904675\",\n      \"author_id\": \"18\",\n      \"created_at\": \"2026-01-02T23:44:00.000Z\",\n      \"text\": \"You can't spell Opus without https://t.co/hneEWMqdnm\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3mbggqrihuk2r\",\n      \"author_id\": \"14\",\n      \"created_at\": \"2026-01-02T08:05:50.000Z\",\n      \"text\": \"Knip is amazing and you should be using it.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3lvwax6bemc22\",\n      \"author_id\": \"22\",\n      \"created_at\": \"2025-08-08T22:02:18.000Z\",\n      \"text\": \"Just used `npx knip` to find my unused files, components, and packages and 😱! So cool. \\n\\nHow have I not come across it before?\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1932778410691949034\",\n      \"author_id\": \"10\",\n      \"created_at\": \"2025-06-11T14:34:00.000Z\",\n      \"text\": \"\\\"Thanks Knip!\\\"\\neveryday,\\nevery team member,\\nliterally..\\nknip.dev 🏅\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"url\": \"https://github.com/webpro-nl/knip/issues/1120#issuecomment-2943978262\",\n      \"author_id\": \"9\",\n      \"created_at\": \"2025-06-05T14:00:00.000Z\",\n      \"text\": \"Thank you so much for this incredible piece of software! Knip is one of the most impressive tools I've seen in my career.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://github.com/webpro-nl/knip/pull/1022\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip/pull/1022\",\n            \"display_url\": \"https://github.com/webpro-nl/knip/pull/1022\",\n            \"title\": \"feat: add create-typescript-app plugin\",\n            \"description\": \"feat: add create-typescript-app plugin\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip/pull/1022\"\n          }\n        ]\n      },\n      \"id\": \"3lmhgsj2n622o\",\n      \"author_id\": \"7\",\n      \"created_at\": \"2025-04-10T13:50:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Got my first plugin merged into Knip by @webpro.nl today! ☺️\\n\\nThe contribution experience was fantastic: the docs were super clear, the code was straightforward to navigate, and the helper script to generate a new plugin got me 90% of the way there. Awesome. Thanks Lars!\\n\\nhttps://github.com/webpro-nl/knip/pull/1022\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1904580358307250634\",\n      \"author_id\": \"6\",\n      \"created_at\": \"2025-03-25T18:05:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"All of the TanStack monorepos make use of knip.dev\\n\\nIt's like eslint for detecting unused dependencies or even your own files/modules.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"cdn.bsky.app/img/dummy-01\",\n            \"display_url\": \"cdn.bsky.app/img/opw3iapscc55nlgrx6q2yjah\",\n            \"media_key\": \"2\"\n          }\n        ]\n      },\n      \"id\": \"3ll5ioywml223\",\n      \"author_id\": \"8\",\n      \"created_at\": \"2025-03-24T20:32:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"The joy of adding knip.dev (by @webpro.nl) on a codebase! Right in time for spring cleaning 🧹🍃\\ncdn.bsky.app/img/dummy-01\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1874692207472726401\",\n      \"author_id\": \"5\",\n      \"created_at\": \"2025-01-02T06:40:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Knip helped us delete ~300k lines of unused code at Vercel.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/kA81p5gkmP\",\n            \"expanded_url\": \"https://www.npmx.dev/package/knip\",\n            \"display_url\": \"npmx.dev/package/knip\",\n            \"title\": \"Knip\",\n            \"description\": \"Find unused dependencies, exports and files in your TypeScript and JavaScript projects.\",\n            \"unwound_url\": \"https://www.npmx.dev/package/knip\"\n          }\n        ]\n      },\n      \"id\": \"1850975288362221628\",\n      \"author_id\": \"5\",\n      \"created_at\": \"2024-10-28T19:57:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Knip may be the greatest tool ever conceived.\\nhttps://t.co/kA81p5gkmP\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3k3obqi65oy2p\",\n      \"author_id\": \"4\",\n      \"created_at\": \"2023-07-29T17:33:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"`knip` is the best code maintenance tool I've used in my 20 years of development, just an absolute work of art\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1808672067900092505\",\n      \"author_id\": \"3\",\n      \"created_at\": \"2024-07-04T03:19:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"knip is great.\\n\\nA great example of stuff just working. It detects your environment so well and its defaults are almost too good because I didn’t realise it was doing everything automatically.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1808808208229707835\",\n      \"author_id\": \"3\",\n      \"created_at\": \"2024-07-04T12:20:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Then was like “this is how tooling should be, this has taken me an hour not a day and it’s faster and more accurate and more future proof”\\n\\nFive stars ⭐️⭐️⭐️⭐️⭐️\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1803013555907698921\",\n      \"author_id\": \"2\",\n      \"created_at\": \"2024-06-18T12:35:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Crazy useful tool. Thought it would be a nightmare to setup in my Next.js+Workers repo but it has crazy good automatic detection for code dependencies. In short, Knip creates a graph of code use and highlights dead code for you to snip (knip).\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1793913676896031033\",\n      \"author_id\": \"44217212\",\n      \"created_at\": \"2024-05-24T09:55:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Lars is singlehandedly building the best tool to keep your code clean and your dependencies minimal. And he's so engaging and helpful. Can't imagine going back to not using knip 👏\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/dummy-01\",\n            \"display_url\": \"pic.twitter.com/uOuO1ch5ij\",\n            \"media_key\": \"1\"\n          }\n        ]\n      },\n      \"id\": \"1745972825490604506\",\n      \"author_id\": \"1\",\n      \"created_at\": \"2024-01-13T01:55:00.000Z\",\n      \"attachments\": { \"media_keys\": [\"1\"] },\n      \"text\": \"warning: do not use a tool like knip.dev + code search to delete a ton of unused code. It works too well.\\n\\nI just did this in https://github.com/sourcegraph/cody/pull/2705, and my boss said if I end the week with net negative lines of code committed, I'm in deep trouble. https://t.co/dummy-01\"\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"argos_ci\",\n            \"id\": \"1554000987022663681\"\n          },\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"annotations\": [\n          {\n            \"probability\": 0.6699,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Prettier\"\n          },\n          {\n            \"probability\": 0.7586,\n            \"type\": \"Other\",\n            \"normalized_text\": \"ESLint\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/uOuO1ch5ij\",\n            \"expanded_url\": \"https://twitter.com/gregberge_/status/1730180003453927560/photo/1\",\n            \"display_url\": \"pic.twitter.com/uOuO1ch5ij\",\n            \"media_key\": \"3_1730179997682552832\"\n          }\n        ]\n      },\n      \"author_id\": \"22918124\",\n      \"text\": \"Ran knip.dev in @argos_ci, and boom 💥! Dead code detected instantly. With a good config, it can run on CI to keep projects clean. Installing this tool should be a no-brainer, like Prettier or ESLint.\\n\\nKudos, @webprolific! 👏 https://t.co/uOuO1ch5ij\",\n\n      \"id\": \"1730180003453927560\",\n      \"created_at\": \"2023-11-30T11:00:32.000Z\",\n      \"edit_history_tweet_ids\": [\"1730180003453927560\"],\n      \"attachments\": { \"media_keys\": [\"3_1730179997682552832\"] }\n    },\n    {\n      \"note_tweet\": {\n        \"text\": \"Problem: \\n🚫 Your project has unused files.\\n🚫 It has unused npm dependencies.\\n🚫 It has unused TypeScript exports.\\n\\nBut you haven't noticed, because these things are hard to spot.\\n\\nSolution: knip\\n\\nI just used knip to find and resolve dozens of issues.\\n\\nhttps://t.co/QmN3sNlmbm\",\n        \"entities\": {\n          \"urls\": [\n            {\n              \"url\": \"https://t.co/QmN3sNlmbm\",\n              \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n              \"display_url\": \"github.com/webpro-nl/knip\"\n            }\n          ]\n        }\n      },\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.8569,\n            \"type\": \"Other\",\n            \"normalized_text\": \"TypeScript\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/grbeTqMtt6\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n            \"display_url\": \"github.com/webpro-nl/knip\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig\",\n                \"width\": 1280,\n                \"height\": 640\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!\",\n            \"description\": \"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip\"\n          },\n          {\n            \"url\": \"https://t.co/qaOXBlD3eo\",\n            \"expanded_url\": \"https://twitter.com/i/web/status/1691460974518353920\",\n            \"display_url\": \"twitter.com/i/web/status/1…\"\n          }\n        ]\n      },\n      \"author_id\": \"19268321\",\n      \"text\": \"Problem: \\n🚫 Your project has unused files.\\n🚫 It has unused npm dependencies.\\n🚫 It has unused TypeScript exports.\\n\\nBut you haven't noticed, because these things are hard to spot.\\n\\nSolution: knip\\n\\nI just used knip to find and resolve dozens of issues.\\n\\nhttps://t.co/grbeTqMtt6 https://t.co/qaOXBlD3eo\",\n\n      \"id\": \"1691460974518353920\",\n      \"created_at\": \"2023-08-15T14:44:56.000Z\",\n      \"edit_history_tweet_ids\": [\"1691460974518353920\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"annotations\": [\n          {\n            \"probability\": 0.6322,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ]\n      },\n      \"author_id\": \"3126044440\",\n      \"text\": \"@webprolific Knip helped me get rid of over 41k lines of code in legacy codebase 🥺🥺💕\",\n\n      \"id\": \"1729181106715632088\",\n      \"created_at\": \"2023-11-27T16:51:17.000Z\",\n      \"edit_history_tweet_ids\": [\"1729181106715632088\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"contra\",\n            \"id\": \"973313523790082053\"\n          }\n        ],\n        \"annotations\": [\n          {\n            \"probability\": 0.8474,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/UgCunYQWzu\",\n            \"expanded_url\": \"https://twitter.com/webprolific/status/1729105865683435542\",\n            \"display_url\": \"twitter.com/webprolific/st…\"\n          }\n        ]\n      },\n      \"author_id\": \"95668959\",\n      \"text\": \"Big fans of Knip at @Contra. Such an extremely well developed and maintained project https://t.co/UgCunYQWzu\",\n\n      \"id\": \"1729157761215369264\",\n      \"created_at\": \"2023-11-27T15:18:31.000Z\",\n      \"edit_history_tweet_ids\": [\"1729157761215369264\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/ZUYYdvkBJc\",\n            \"expanded_url\": \"https://github.com/getsentry/sentry/\",\n            \"display_url\": \"github.com/getsentry/sent…\",\n            \"title\": \"GitHub - getsentry/sentry: Developer-first error tracking and performance monitoring\",\n            \"description\": \"Developer-first error tracking and performance monitoring - GitHub - getsentry/sentry: Developer-first error tracking and performance monitoring\",\n            \"unwound_url\": \"https://github.com/getsentry/sentry/\"\n          }\n        ]\n      },\n      \"author_id\": \"1632752318994153472\",\n      \"text\": \"@webprolific Just tried this on https://t.co/ZUYYdvkBJc - got some super useful results! Nice work.\",\n\n      \"id\": \"1727040036334424406\",\n      \"created_at\": \"2023-11-21T19:03:26.000Z\",\n      \"edit_history_tweet_ids\": [\"1727040036334424406\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          { \"username\": \"TkDodo\", \"id\": \"44217212\" },\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          },\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ]\n      },\n      \"author_id\": \"1513218780167655427\",\n      \"text\": \"@TkDodo @webprolific I've manage to delete 6k LOC in the last 30 minutes 🫣\\n\\nGreat job here @webprolific 👍🏽\",\n\n      \"id\": \"1726807293583609935\",\n      \"created_at\": \"2023-11-21T03:38:35.000Z\",\n      \"edit_history_tweet_ids\": [\"1726807293583609935\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/Tg5E6C7gqa\",\n            \"expanded_url\": \"https://twitter.com/housecor/status/1713975785273303286\",\n            \"display_url\": \"twitter.com/housecor/statu…\"\n          }\n        ]\n      },\n      \"author_id\": \"44217212\",\n      \"text\": \"knip is an amazing tool. Shoutout to @webprolific for building it 🙌.\\n\\nNot cleaning up correctly has a real maintenance cost. I've deleted lots of dead code - functions that were only used in tests and components that were only used in stories - all thanks to knip 🚀. https://t.co/Tg5E6C7gqa\",\n\n      \"id\": \"1714023231689031941\",\n      \"created_at\": \"2023-10-16T20:59:18.000Z\",\n      \"edit_history_tweet_ids\": [\"1714023231689031941\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9562,\n            \"type\": \"Other\",\n            \"normalized_text\": \"JavaScript\"\n          },\n          {\n            \"probability\": 0.8666,\n            \"type\": \"Other\",\n            \"normalized_text\": \"TypeScript\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/f3fzC5UPtR\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n            \"display_url\": \"github.com/webpro-nl/knip\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig\",\n                \"width\": 1280,\n                \"height\": 640\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!\",\n            \"description\": \"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip\"\n          }\n        ]\n      },\n      \"author_id\": \"481186762\",\n      \"text\": \"🛠️ Knip\\n\\n👉🏻 Knip finds unused dependencies, exports and files in your JavaScript and TypeScript projects.\\n👉🏻 Less code and dependencies lead to improved performance, less maintenance and easier refactorings. \\n\\nhttps://t.co/f3fzC5UPtR\",\n      \"id\": \"1696221274039595363\",\n      \"created_at\": \"2023-08-28T18:00:40.000Z\",\n      \"edit_history_tweet_ids\": [\"1696221274039595363\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9354,\n            \"type\": \"Other\",\n            \"normalized_text\": \"JavaScript\"\n          },\n          {\n            \"probability\": 0.7027,\n            \"type\": \"Other\",\n            \"normalized_text\": \"TypeScript\"\n          },\n          {\n            \"probability\": 0.7208,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Josh\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/nKtvr2wEg6\",\n            \"expanded_url\": \"https://twitter.com/JoshuaKGoldberg/status/1693713311836115286\",\n            \"display_url\": \"twitter.com/JoshuaKGoldberg\"\n          }\n        ]\n      },\n      \"author_id\": \"416394303\",\n      \"text\": \"Knip is wonderful at finding out unused code/dependencies in a legacy JavaScript/TypeScript application\\n\\nRecommend 💯\\n\\nHere's how Josh used it to remove code bloat in Centered: https://t.co/nKtvr2wEg6\",\n      \"id\": \"1693944495472046382\",\n      \"created_at\": \"2023-08-22T11:13:34.000Z\",\n      \"edit_history_tweet_ids\": [\"1693944495472046382\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.5513,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/L8w9V11PRL\",\n            \"expanded_url\": \"https://www.smashingmagazine.com/2023/08/knip-automated-tool-find-unused-files-exports-dependencies/\",\n            \"display_url\": \"smashingmagazine.com/2023/08/knip-a…\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1727384011872366592/W-M5klkJ?format=jpg&name=orig\",\n                \"width\": 1200,\n                \"height\": 675\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1727384011872366592/W-M5klkJ?format=jpg&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"Knip: An Automated Tool For Finding Unused Files, Exports, And Dependencies — Smashing Magazine\",\n            \"description\": \"Most of the projects have at least a few unused files, exports, and dependencies lying around, often because it’s difficult knowing when one thing relies on another and scary removing something you’re not sure is in use. Lars Kappert shares a tool he’s been working on that offers a solution.\",\n            \"unwound_url\": \"https://www.smashingmagazine.com/2023/08/knip-automated-tool-find-unused-files-exports-dependencies/\"\n          }\n        ]\n      },\n      \"author_id\": \"15736190\",\n      \"text\": \"Unused files, exports, and dependencies often clutter projects, as it’s difficult knowing when one thing relies on another and scary to remove something you’re not sure is in use. 👀\\n\\n↬ Meet Knip, which scours projects for these unused artifacts: https://t.co/L8w9V11PRL\",\n      \"id\": \"1691120132901240832\",\n      \"created_at\": \"2023-08-14T16:10:33.000Z\",\n      \"edit_history_tweet_ids\": [\"1691120132901240832\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"typescript\",\n            \"id\": \"809233214\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/1mRMwvjIpw\",\n            \"expanded_url\": \"https://effectivetypescript.com/2023/07/29/knip/\",\n            \"display_url\": \"effectivetypescript.com/2023/07/29/kni…\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1696204795353219085/ZjmFlTVW?format=jpg&name=orig\",\n                \"width\": 560,\n                \"height\": 735\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1696204795353219085/ZjmFlTVW?format=jpg&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"Effective TypeScript › Recommendation Update: ✂️ Use knip to detect dead code and types\",\n            \"description\": \"TL;DR: Use ts-prune is in maintenance mode. Use knip to find dead code instead. It's great!\",\n            \"unwound_url\": \"https://effectivetypescript.com/2023/07/29/knip/\"\n          }\n        ]\n      },\n      \"author_id\": \"21046936\",\n      \"text\": \"Recommendation update: use knip to find dead code, types and dependencies in your @typescript ✂️https://t.co/1mRMwvjIpw\",\n      \"id\": \"1685298103094554625\",\n      \"created_at\": \"2023-07-29T14:35:53.000Z\",\n      \"edit_history_tweet_ids\": [\"1685298103094554625\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9661,\n            \"type\": \"Other\",\n            \"normalized_text\": \"GitHub\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/vnxNbiJs1I\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n            \"display_url\": \"github.com/webpro-nl/knip\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig\",\n                \"width\": 1280,\n                \"height\": 640\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!\",\n            \"description\": \"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip\"\n          }\n        ]\n      },\n      \"author_id\": \"380616577\",\n      \"text\": \"This is worth checking out on GitHub. 👍 https://t.co/vnxNbiJs1I\",\n      \"id\": \"1581910299846012928\",\n      \"created_at\": \"2022-10-17T07:29:40.000Z\",\n      \"edit_history_tweet_ids\": [\"1581910299846012928\"]\n    },\n    {\n      \"note_tweet\": {\n        \"text\": \"Streamlining React projects with Knip:\\n\\nRecently, I employed Knip for a project, and it worked wonders! \\n\\nIt efficiently resolved issues with removing\\n✅ Unused files, \\n✅ Unused npm dependencies, \\n✅ Unneeded TypeScript exports.\\n\\n A real time-saver for maintaining a clean and efficient codebase. 🛠️ #ReactDevelopment \\n\\nhttps://t.co/IbJH2fIzsE\",\n        \"entities\": {\n          \"urls\": [\n            {\n              \"url\": \"https://t.co/IbJH2fIzsE\",\n              \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n              \"display_url\": \"github.com/webpro-nl/knip\"\n            }\n          ],\n          \"hashtags\": [{ \"tag\": \"ReactDevelopment\" }]\n        }\n      },\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.743,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          },\n          {\n            \"probability\": 0.7667,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/P39xg0qCrT\",\n            \"expanded_url\": \"https://twitter.com/i/web/status/1693502146128281657\",\n            \"display_url\": \"twitter.com/i/web/status/1…\"\n          }\n        ]\n      },\n      \"author_id\": \"827145937030148097\",\n      \"text\": \"Streamlining React projects with Knip:\\n\\nRecently, I employed Knip for a project, and it worked wonders! \\n\\nIt efficiently resolved issues with removing\\n✅ Unused files, \\n✅ Unused npm dependencies, \\n✅ Unneeded TypeScript exports.\\n\\n A real time-saver for maintaining a clean and… https://t.co/P39xg0qCrT\",\n      \"id\": \"1693502146128281657\",\n      \"created_at\": \"2023-08-21T05:55:50.000Z\",\n      \"edit_history_tweet_ids\": [\"1693502146128281657\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9331,\n            \"type\": \"Other\",\n            \"normalized_text\": \"JavaScript\"\n          },\n          {\n            \"probability\": 0.5907,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ]\n      },\n      \"author_id\": \"18191376\",\n      \"text\": \"Found a bunch of unused code, -dependencies, and unnecessary exports. Had just one false positive but overall pretty good. 10/10 would recommend.\\n\\nIf you’ve got a JavaScript package/project use Knip and remove unnecessary code. ✂️\",\n      \"id\": \"1692942539614028086\",\n      \"created_at\": \"2023-08-19T16:52:09.000Z\",\n      \"edit_history_tweet_ids\": [\"1692942539614028086\"]\n    }\n  ],\n  \"includes\": {\n    \"media\": [\n      {\n        \"media_key\": \"1\",\n        \"url\": \"https://pbs.twimg.com/media/GDrwdB3aYAAu4am?format=png&name=orig\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"2\",\n        \"url\": \"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:opw3iapscc55nlgrx6q2yjah/bafkreihzszb56agbe6dtuf6xfutl65mjg5ethnrvw264d5bljbm377jora@jpeg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"3_1730179997682552832\",\n        \"url\": \"https://pbs.twimg.com/media/GALVin9a0AAsn0-.jpg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"4\",\n        \"url\": \"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:4dsclu5hjmht3shxutxtge6h/bafkreid63o3hwvwpk6emgzj64vywusztofhz2yihuvwkywuuajn4eekvom@jpeg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"5\",\n        \"url\": \"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:2gkh62xvzokhlf6li4ol3b3d/bafkreiahk2jbsb2stw276lkrkxrkvialqs25zrpgo2n3cigzfb7qvgfsmq@jpeg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"6\",\n        \"url\": \"https://pbs.twimg.com/media/G9wBaMFWoAAkgv5.png\",\n        \"type\": \"photo\"\n      }\n    ],\n    \"users\": [\n      {\n        \"id\": \"22\",\n        \"username\": \"molliboyle.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:uwwm2qtpni4gvzzhujhh56ps/bafkreib5w76mmc6lxazhkymadd3oj5skped63b6ugvswiikrss7ljgcfi4@jpeg\",\n        \"name\": \"Molly Boyle\"\n      },\n      {\n        \"id\": \"20\",\n        \"username\": \"RozenMD\",\n        \"profile_image_url\": \"https://unavatar.io/x/RozenMD\",\n        \"name\": \"Max Rozen\"\n      },\n      {\n        \"id\": \"21\",\n        \"username\": \"06_Shreehari\",\n        \"profile_image_url\": \"https://unavatar.io/x/06_Shreehari\",\n        \"name\": \"Shreehari\"\n      },\n      {\n        \"id\": \"19\",\n        \"username\": \"janis.me\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:kmekwulhn26kgfwjzrry76d7/bafkreihtzvhhk7oz6cjbgnsbaravu46zhai3zwogkcg7hxv3dlhvecrqw4@jpeg\",\n        \"name\": \"Janis Jansen\"\n      },\n      {\n        \"id\": \"11\",\n        \"username\": \"julien.deniau.me\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:4dsclu5hjmht3shxutxtge6h/bafkreiht3iqxcmelwe7oysawrdpynzevf4dt2ndzeln4f5c2izf62zm57q@jpeg\",\n        \"name\": \"Julien Deniau\"\n      },\n      {\n        \"id\": \"12\",\n        \"username\": \"alexharfordseo.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:y3arowkhgiexpyvmmxvquavg/bafkreiazlcx5fdxylsqtsdng3beq3ayuoc7nzyqcddeequhi7uploqcjny@jpeg\",\n        \"name\": \"AlexHarford-TechSEO\"\n      },\n      {\n        \"id\": \"13\",\n        \"username\": \"fubits.dev\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:6aglx53tojyuwxwueap5og3h/bafkreiclnob3mnfvo74an6ugrnbdikrkxcskndjojrdtkwf5vwjuu77z5u@jpeg\",\n        \"name\": \"Ilja\"\n      },\n      {\n        \"id\": \"14\",\n        \"username\": \"alexanderkaran.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:3n4fccuhdomkkebojjdurnco/bafkreiggltcvdoh4igf5yxvrxggysmasv5efn6hffyav2o6swxslbc3lp4@jpeg\",\n        \"name\": \"Alexander Karan\"\n      },\n      {\n        \"id\": \"15\",\n        \"username\": \"patak.dev\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:2gkh62xvzokhlf6li4ol3b3d/bafkreibi7rw745tbcea7ljrpbkkkoragy2xa5a2lrxhdb3m23s7n3wkv3q@jpeg\",\n        \"name\": \"patak\"\n      },\n      {\n        \"id\": \"16\",\n        \"username\": \"psparwez\",\n        \"profile_image_url\": \"https://unavatar.io/x/psparwez\",\n        \"name\": \"PS\"\n      },\n      {\n        \"id\": \"17\",\n        \"username\": \"k_shehadeh\",\n        \"profile_image_url\": \"https://unavatar.io/x/k_shehadeh\",\n        \"name\": \"Karim Shehadeh\"\n      },\n      {\n        \"id\": \"18\",\n        \"username\": \"cramforce\",\n        \"profile_image_url\": \"https://unavatar.io/x/cramforce\",\n        \"name\": \"Malte Ubl\"\n      },\n      {\n        \"id\": \"1\",\n        \"username\": \"sqs\",\n        \"profile_image_url\": \"https://unavatar.io/x/sqs\",\n        \"name\": \"Quinn Slack\"\n      },\n      {\n        \"id\": \"2\",\n        \"username\": \"jokull\",\n        \"profile_image_url\": \"https://unavatar.io/x/jokull\",\n        \"name\": \"Jökull Solberg\"\n      },\n      {\n        \"id\": \"3\",\n        \"username\": \"Hicksyfern\",\n        \"profile_image_url\": \"https://unavatar.io/x/Hicksyfern\",\n        \"name\": \"Tom Hicks\"\n      },\n      {\n        \"id\": \"4\",\n        \"username\": \"daviduzumeri.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:6ykajndqngy2kxozo37mpsgc/bafkreif2xu6bini3tpv2hfauw53ng43zbefgqol36yt4baehcbdfxahihu@jpeg\",\n        \"name\": \"Old Man Uzi\"\n      },\n      {\n        \"id\": \"5\",\n        \"username\": \"gary__tyr\",\n        \"profile_image_url\": \"https://unavatar.io/x/gary__tyr\",\n        \"name\": \"Gary Tyr\"\n      },\n      {\n        \"id\": \"6\",\n        \"username\": \"KevinVanCott\",\n        \"profile_image_url\": \"https://unavatar.io/x/KevinVanCott\",\n        \"name\": \"Kevin Thomas Van Cott\"\n      },\n      {\n        \"id\": \"7\",\n        \"username\": \"joshuakgoldberg.com\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:hwtki3j7oghodc7h6gqnrtro/bafkreicvkrpjmc7yoviwf5vhkecgcgyn23x24ix4aqdwiikcl226c64k2q@jpeg\",\n        \"name\": \"Josh Goldberg 💖\"\n      },\n      {\n        \"id\": \"8\",\n        \"username\": \"beaussan.io\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:opw3iapscc55nlgrx6q2yjah/bafkreiaj72657msogojjdk4wr76fe3umimydon3pzzrquuj7opcftntrqa@jpeg\",\n        \"name\": \"Nicolas Beaussart\"\n      },\n      {\n        \"id\": \"9\",\n        \"username\": \"MidnightDesign\",\n        \"name\": \"Rudolph Gottesheim\",\n        \"profile_image_url\": \"https://avatars.githubusercontent.com/u/743172?v=4\"\n      },\n      {\n        \"id\": \"10\",\n        \"username\": \"stephaneledorze\",\n        \"name\": \"stephane le dorze\",\n        \"profile_image_url\": \"https://unavatar.io/x/stephaneledorze\"\n      },\n      {\n        \"id\": \"22918124\",\n        \"username\": \"gregberge_\",\n        \"profile_image_url\": \"https://unavatar.io/x/gregberge_\",\n        \"name\": \"Greg Bergé\"\n      },\n      {\n        \"id\": \"19268321\",\n        \"username\": \"housecor\",\n        \"profile_image_url\": \"https://unavatar.io/x/housecor\",\n        \"name\": \"Cory House\"\n      },\n      {\n        \"id\": \"3126044440\",\n        \"username\": \"pkgacek\",\n        \"profile_image_url\": \"https://unavatar.io/x/pkgacek\",\n        \"name\": \"Piotr Gacek 🐟\"\n      },\n      {\n        \"id\": \"95668959\",\n        \"username\": \"kuizinas\",\n        \"profile_image_url\": \"https://unavatar.io/x/kuizinas\",\n        \"name\": \"Gajus\"\n      },\n      {\n        \"id\": \"1632752318994153472\",\n        \"username\": \"imabhiprasad\",\n        \"profile_image_url\": \"https://unavatar.io/x/imabhiprasad\",\n        \"name\": \"Abhijeet Prasad\"\n      },\n      {\n        \"id\": \"1513218780167655427\",\n        \"username\": \"fernandoeeu_dev\",\n        \"profile_image_url\": \"https://unavatar.io/x/fernandoeeu_dev\",\n        \"name\": \"Fernando\"\n      },\n      {\n        \"id\": \"44217212\",\n        \"username\": \"TkDodo\",\n        \"profile_image_url\": \"https://unavatar.io/x/TkDodo\",\n        \"name\": \"Dominik 🔮\"\n      },\n      {\n        \"id\": \"481186762\",\n        \"username\": \"Mokkapps\",\n        \"profile_image_url\": \"https://unavatar.io/x/Mokkapps\",\n        \"name\": \"Michael Hoffmann\"\n      },\n      {\n        \"id\": \"416394303\",\n        \"username\": \"nicoespeon\",\n        \"profile_image_url\": \"https://unavatar.io/x/nicoespeon\",\n        \"name\": \"Nicolas Carlo\"\n      },\n      {\n        \"id\": \"15736190\",\n        \"username\": \"smashingmag\",\n        \"profile_image_url\": \"https://unavatar.io/x/smashingmag\",\n        \"name\": \"Smashing Magazine 🇺🇦 🏳️‍🌈\"\n      },\n      {\n        \"id\": \"21046936\",\n        \"username\": \"danvdk\",\n        \"profile_image_url\": \"https://unavatar.io/x/danvdk\",\n        \"name\": \"Dan Vanderkam\"\n      },\n      {\n        \"id\": \"380616577\",\n        \"username\": \"stefanjudis\",\n        \"profile_image_url\": \"https://unavatar.io/x/stefanjudis\",\n        \"name\": \"Stefan Judis\"\n      },\n      {\n        \"id\": \"827145937030148097\",\n        \"username\": \"BKailaash\",\n        \"profile_image_url\": \"https://unavatar.io/x/BKailaash\",\n        \"name\": \"Kailaash\"\n      },\n      {\n        \"id\": \"18191376\",\n        \"username\": \"waldekm\",\n        \"profile_image_url\": \"https://unavatar.io/x/waldekm\",\n        \"name\": \"Waldek Mastykarz\"\n      }\n    ]\n  }\n}\n","packages/docs/src/content/docs/explanations/comparison-and-migration.md":"---\ntitle: Comparison & Migration\ndescription: How Knip compares to depcheck, unimported, ts-prune, ts-unused-exports and tsr, and how to migrate from them.\n---\n\nFirst of all, Knip owes a lot to the projects on this page and they've all been\ninspirational in their own way. For best results, Knip has [a vision embracing\ncomprehensiveness][1] which is larger in scope than any of the alternatives. So\nif any of those tools has the right scope for your requirements, then by all\nmeans, use what suits you best. Note that most projects are no longer\nmaintained.\n\nAll tools have in common that they have less features and don't support the\nconcept of [monorepos/workspaces][2]. Feel free to send in projects that Knip\ndoes not handle better, Knip loves to be challenged!\n\n## Migration\n\nA migration consists of deleting the dependency and its configuration file and\n[getting started with Knip][3]. You should end up with less configuration.\n\n## Comparison\n\n### depcheck\n\n> [Depcheck][4] is a tool for analyzing the dependencies in a project to see:\n> how each dependency is used, which dependencies are useless, and which\n> dependencies are missing from package.json.\n\nThe project has plugins (specials), yet not as many as Knip has and they're not\nas advanced. It also supports compilers (parsers) for non-standard files.\n\nThe following commands are similar:\n\n```sh\ndepcheck\nknip --dependencies\n```\n\n**Project status**: The project is archived and recommends Knip.\n\n### unimported\n\n> Find and fix dangling files and unused dependencies in your JavaScript\n> projects.\n\n[unimported][5] is fast and works well. It works in what Knip calls \"production\nmode\" exclusively. If you're fine with a little bit of configuration and don't\nwant or need to deal with non-production items (such as `devDependencies` and\ntest files), then this might work well for you.\n\nThe following commands are similar:\n\n```sh\nunimported\nknip --production --dependencies --files\n```\n\n**Project status**: The project is archived and recommends Knip.\n\n### ts-prune\n\n> Find unused exports in a typescript project. 🛀\n\n[ts-prune][6] aims to find potentially unused exports in your TypeScript project\nwith zero configuration.\n\nThe following commands are similar:\n\n```sh\nts-prune\nknip --include exports,types,nsExports,nsTypes\n```\n\nUse `knip --exports` to also include enum and namespace members.\n\n**Project status**: The project is archived and recommends Knip.\n\n### ts-unused-exports\n\n> [ts-unused-exports][7] finds unused exported symbols in your Typescript\n> project\n\nThe following commands are similar:\n\n```sh\nts-unused-exports\nknip --include exports,types,nsExports,nsTypes\n```\n\nUse `knip --exports` to also include enum and namespace members.\n\n### tsr\n\n> Remove unused code from your TypeScript Project\n\n[tsr][8] (previously `ts-remove-unused`) removes unused exports, and works based\non a single `tsconfig.json` file (`includes` and `excludes`) and requires no\nconfiguration. It removes the `export` keyword or the whole export declaration.\n\n**Project status**: The project is archived and recommends Knip.\n\n## Related projects\n\nAdditional alternative and related projects include:\n\n- [deadfile][9]\n- [DepClean][10]\n- [dependency-check][11]\n- [find-unused-exports][12]\n- [next-unused][13]\n- [npm-check][14]\n- [renoma][15]\n\nIn general, the [e18e.dev][16] website and in particular the [Cleanup][17]\nsection is a great resource when dealing with technical debt.\n\n[1]: ./why-use-knip.md#comprehensive\n[2]: ../features/monorepos-and-workspaces.md\n[3]: ../overview/getting-started.mdx\n[4]: https://github.com/depcheck/depcheck\n[5]: https://github.com/smeijer/unimported\n[6]: https://github.com/nadeesha/ts-prune\n[7]: https://github.com/pzavolinsky/ts-unused-exports\n[8]: https://github.com/line/tsr\n[9]: https://github.com/M-Izadmehr/deadfile\n[10]: https://github.com/mysteryven/depclean\n[11]: https://github.com/dependency-check-team/dependency-check\n[12]: https://github.com/jaydenseric/find-unused-exports\n[13]: https://github.com/pacocoursey/next-unused\n[14]: https://github.com/dylang/npm-check\n[15]: https://github.com/bluwy/renoma\n[16]: https://e18e.dev\n[17]: https://e18e.dev/guide/cleanup.html\n","packages/docs/src/content/docs/explanations/entry-files.md":"---\ntitle: Entry Files\ndescription: What entry files are and how Knip and its plugins find them automatically from defaults, `package.json`, plugins and dynamic imports.\n---\n\nEntry files are the starting point for Knip to determine what files are used in\nthe codebase. More entry files lead to increased coverage of the codebase. This\nalso leads to more dependencies to be discovered. This page explains how Knip\nand its plugins try to find entry files so you don't need to configure them\nyourself.\n\n## Default entry file patterns\n\nFor brevity, the [default configuration][1] on the previous page mentions only\n`index.js` and `index.ts`, but the default set of file names and extensions is\nactually a bit larger:\n\n- `index`, `main` and `cli`\n- `js`, `mjs`, `cjs`, `jsx`, `ts`, `mts`, `cts` and `tsx`\n\nThis means files like `main.cjs` and `src/cli.ts` are automatically added as\nentry files. Here's the default configuration in full:\n\n```json\n{\n  \"entry\": [\n    \"{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\",\n    \"src/{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\"\n  ],\n  \"project\": [\"**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}!\"]\n}\n```\n\nNext to the default locations, Knip looks for `entry` files in other places. In\na monorepo, this is done for each workspace separately.\n\nThe values you set override the default values, they are not merged.\n\n## Plugins\n\nPlugins often add entry files. For instance, the Remix, Storybook and Vitest\nplugins add additional entry files. See [the next page about plugins][2] for\nmore details about this.\n\n## Scripts in package.json\n\nThe `package.json` is scanned for entry files. The `main`, `bin`, and `exports`\nfields may contain entry files. The `scripts` are also parsed to find entry\nfiles and dependencies. See [Script Parser][3] for more details.\n\n## Ignored files\n\nKnip respects `.gitignore` files. By default, ignored files are not added as\nentry files. This behavior can be disabled by using the [`--no-gitignore`][4]\nflag on the CLI.\n\n## Configuring project files\n\nSee [configuring project files][5] for guidance on tuning `entry` and `project`\nand when to use `ignore`.\n\n## Where Knip looks for entry files\n\nPutting it together, Knip discovers entry files from:\n\n- Default locations such as `index.js` and `src/index.ts`\n- The `main`, `bin` and `exports` fields in `package.json`\n- Entry and config files added by enabled plugins (the config files are entry\n  files too)\n- Dynamic imports: `require()` and `import()`\n- `require.resolve()` and `import.meta.resolve()`\n- `new URL('./file.js', import.meta.url)`\n- `new Worker(…)` and `child_process` `fork`/`spawn`/`execFile` when the target\n  is `path.join(__dirname, …)`\n- `module.register('./loader.js')` loader registration\n- Scripts the [script parser][3] extracts: `package.json` scripts, CI workflow\n  `run` commands, and source-code calls (tagged `$` templates,\n  `node:child_process`, `execa`, `nano-spawn`)\n\nEntry files are added to the module graph, and module resolution may pull in\nfurther entry files recursively until none remain.\n\n[1]: ../overview/configuration.md#defaults\n[2]: ./plugins.md\n[3]: ../features/script-parser.md\n[4]: ../reference/cli.md#--no-gitignore\n[5]: ../guides/configuring-project-files.md\n","packages/docs/src/content/docs/explanations/how-knip-works.md":"---\ntitle: How Knip works\ndescription: The mental model behind Knip. How entry files, the module graph and reachability decide what counts as unused, and why surprising results trace back to them.\n---\n\nKnip finds and removes unused code and dependencies. It starts at your entry\nfiles, follows every import to the files they reach, and builds a graph of\neverything connected. Anything left out is reported as unused: a file no entry\nreaches, an export no file imports, a dependency no file uses.\n\nThis page explains how Knip produces its results.\n\n## Build and analyze\n\nKnip runs in two phases.\n\nThe build phase starts from the entry files. Knip reads a file, parses it,\ncollects its imports and exports, resolves each import to another file, and\nrepeats for every newly reached file. The result is a graph of the project:\nevery reachable file, what it imports, and what imports it.\n\nResolution is broad by design. Knip follows custom path aliases and extensions,\nreads references out of config files and [shell scripts][1], and \"[compiles][2]\"\nnon-standard files like `.vue` and `.svelte` so their imports are in the graph\ntoo.\n\nThe analysis phase queries that graph. It never re-parses anything. It walks the\nedges already recorded:\n\n- a **file** is unused when no entry reaches it\n- an **export** is unused when no other file imports it\n- a **dependency** is unused when no file imports it (and _unlisted_ when a file\n  imports it but `package.json` doesn't list it)\n\nAnalysis happens by quering the graph. Your results are only as accurate as the\ngraph is complete. And the graph depends on your entry files.\n\n## Entry files decide what Knip can see\n\nThe graph contains only what's reachable from an entry file. Miss one entry, and\neverything reachable _only_ from it looks unused.\n\nIdeally you don't need to list entries by hand. Knip starts from sensible\n[defaults][3] like `src/index.ts`, and [plugins][4] automatically add the entry\npoints specific to your frameworks and libraries. The Vitest plugin adds your\ntest files, the Astro plugin adds your pages, and so on. This is why plugins are\nimportant: each one tells Knip about a whole class of files it might otherwise\nnever reach.\n\n## Findings come in chains\n\nUnused results cascade. They don't appear in isolation. Say a tool generates an\nentry file Knip doesn't know about:\n\n- that file looks unused, because nothing reaches it\n- every file it imports looks unused too, because nothing else reaches them\n- every export in those files looks unused\n- every dependency only those files used looks unused\n\nOne unreached entry can turn into dozens of findings. The chain also runs in\nreverse: add the entry, and the whole cascade collapses at once.\n\nSo read the output from the root down: **unused files first, then exports, then\ndependencies.** A single unused file usually explains a long list of results\nbelow it. Fix causes at the root and the rest disappears.\n\nSome chains only show up one run at a time. An export counts as used when\nanother file imports it, even if the importing code is unused. Remove that code,\nand the next run may report the export. Unused exports that import each other\nacross files are never reported.\n\n## A surprising result might be a gap, not a bug\n\nWhen Knip flags something you're sure is used, it's based on the graph: it\ncouldn't reach that code from an entry. The cause is usually one of:\n\n- a missing entry for a tool or convention Knip doesn't know yet\n- a dynamic import Knip can't follow statically, or a path it can't resolve\n- a transitive dependency of a package that resolves only because something else\n  installs it\n\nIn each case the fix is to teach Knip: add the entry, configure the plugin, list\nthe dependency. Don't hide the result. [Configuring project files][5] and\n[resolving reported issues][6] cover how, issue type by issue type.\n\n[1]: ../features/script-parser.md\n[2]: ../features/compilers.md\n[3]: ./entry-files.md\n[4]: ./plugins.md\n[5]: ../guides/configuring-project-files.md\n[6]: ../guides/handling-issues.mdx\n","packages/docs/src/content/docs/explanations/plugins.md":"---\ntitle: Plugins\ndescription: How Knip plugins work and the difference between `config` files (parsed for dependencies) and `entry` files (added to the module graph).\n---\n\nThis page describes why Knip uses plugins and the difference between `config`\nand `entry` files.\n\nKnip has an extensive and growing [list of built-in plugins][1]. Feel free to\n[write a plugin][2] so others can benefit too!\n\n## What does a plugin do?\n\nPlugins are enabled if the related package is listed in the list of dependencies\nin `package.json`. For instance, if `astro` is listed in `dependencies` or\n`devDependencies`, then the Astro plugin is enabled. And this means that this\nplugin will:\n\n- Handle [configuration files][3] like `astro.config.mjs`\n- Add [entry files][4] such as `src/pages/**/*.astro`\n- Define [command-line arguments][5]\n\n## Configuration files\n\nKnip uses [entry files][6] as starting points to scan your source code and\nresolve other internal files and external dependencies. The module graph can be\nstatically resolved through the `require` and `import` statements in those\nsource files. However, configuration files reference external dependencies in\nvarious ways. Knip uses a plugin for each tool to parse configuration files and\nfind those dependencies.\n\n### Example: ESLint\n\nIn the first example we look at [the ESLint plugin][7]. The default `config`\nfile patterns include `.eslintrc.json`. Here's a minimal example:\n\n```json title=\".eslintrc.json\"\n{\n  \"extends\": [\"airbnb\", \"prettier\"],\n  \"plugins\": [\"@typescript-eslint\"]\n}\n```\n\nConfiguration files like this don't `import` or `require` anything, but they do\nrequire the referenced dependencies to be installed.\n\nIn this case, the plugin will return three dependencies:\n\n- `eslint-config-airbnb`\n- `eslint-config-prettier`\n- `@typescript-eslint/eslint-plugin`\n\nKnip will then look for missing dependencies in `package.json` and report those\nas unlisted. And vice versa, if there are any ESLint plugins listed in\n`package.json`, but unused, those will be reported as well.\n\n### Example: Vitest\n\nThe second example uses [the Vitest plugin][8]. Here's a minimal example of a\nVitest configuration file:\n\n```ts title=\"vitest.config.ts\"\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    coverage: {\n      provider: 'istanbul',\n    },\n    environment: 'happy-dom',\n  },\n});\n```\n\nThe Vitest plugin reads this configuration and returns two dependencies:\n\n- `@vitest/coverage-istanbul`\n- `vitest-environment-happy-dom`\n\nKnip will look for missing and unused dependencies in `package.json` and report\naccordingly.\n\nSome tools allow configuration to be stored in `package.json`, that's why some\nplugins contain `package.json` in the list of `config` files.\n\n:::tip[Summary]\n\nPlugins load configuration files to find referenced dependencies, and determine\nunused and unlisted dependencies.\n\n:::\n\n## Entry files\n\nMany plugins have default `entry` files configured. When the plugin is enabled,\nKnip will add entry files as configured by the plugin to resolve used files and\ndependencies.\n\nFor example, if `next` is listed as a dependency in `package.json`, the Next.js\nplugin will automatically add multiple patterns as entry files, such as\n`pages/**/*.{js,jsx,ts,tsx}`. If `vitest` is listed, the Vitest plugin adds\n`**/*.{test,test-d,spec,spec-d}.ts` as entry file patterns. Most plugins have\nentry files configured, so you don't have to.\n\nIt's mostly plugins for meta frameworks and test runners that have `entry` files\nconfigured.\n\n:::tip[Plugins result in less configuration]\n\nPlugins use entry file patterns as defined in your configuration file of these\ntools. So you don't need to repeat this in your Knip configuration.\n\n:::\n\nFor example, let's say your Playwright configuration contains the following:\n\n```ts title=\"playwright.config.ts\"\nimport type { PlaywrightTestConfig } from '@playwright/test';\n\nconst config: PlaywrightTestConfig = {\n  testDir: 'integration',\n  testMatch: ['**/*-test.ts'],\n};\n\nexport default config;\n```\n\nThe Playwright plugin will read this configuration file and return those entry\npatterns (`integration/**/*-test.ts`). Knip will then not use the default entry\npatterns.\n\nYou can still override this behavior in your Knip configuration:\n\n```json title=\"knip.json\"\n{\n  \"playwright\": {\n    \"entry\": \"src/**/*.integration.ts\"\n  }\n}\n```\n\nThis should not be necessary though. Please consider opening a pull request or a\nbug report if any plugin is not behaving as expected.\n\n:::tip[Summary]\n\nPlugins try hard to automatically add the correct entry files.\n\n:::\n\n## Entry files from config files\n\nEntry files are part of plugin configuration (as described in the previous\nsection). Yet plugins can also return additional entry files after parsing\nconfiguration files. Below are some examples of configuration files parsed by\nplugins to return additional entry files. The goal of these examples is to give\nyou an idea about the various ways Knip and its plugins try to find entry files\nso you don't need to configure them yourself.\n\n### Angular\n\nThe Angular plugin parses the Angular configuration file. Here's a fragment:\n\n```json title=\"angular.json\"\n{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"projects\": {\n    \"knip-angular-example\": {\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit/build-angular:browser\",\n          \"options\": {\n            \"outputPath\": \"dist/knip-angular-example\",\n            \"main\": \"src/main.ts\",\n            \"tsConfig\": \"tsconfig.app.json\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nThis will result in `src/main.ts` being added as an entry file (and\n`@angular-devkit/build-angular` as a referenced dependency).\n\nAdditionally, the Angular plugin returns `tsconfig.app.json` as a configuration\nfile for the TypeScript plugin.\n\n### GitHub Actions\n\nThis plugin parses workflow YAML files. This fragment contains three `run`\nscripts:\n\n```yml title=\".github/workflows/deploy.yml\"\njobs:\n  integration:\n    runs-on: ubuntu-latest\n    steps:\n      - run: npm install\n      - run: node scripts/build.js\n      - run: node --loader tsx scripts/deploy.ts\n      - run: playwright test -c playwright.web.config.ts\n        working-directory: e2e\n```\n\nFrom these scripts, the `scripts/build.js` and `scripts/deploy.ts` files will be\nadded as entry files by the GitHub Actions plugin.\n\nAdditionally, the file `e2e/playwright.web.config.ts` is detected and will be\nhanded over as a Playwright configuration file.\n\nRead more about this in [command-line arguments][5].\n\n### webpack\n\nLet's take a look at this example webpack configuration file:\n\n```js title=\"webpack.config.js\"\nmodule.exports = env => {\n  return {\n    entry: {\n      main: './src/app.ts',\n      vendor: './src/vendor.ts',\n    },\n    module: {\n      rules: [\n        {\n          test: /\\.(woff|ttf|ico|woff2|jpg|jpeg|png|webp)$/i,\n          use: 'base64-inline-loader',\n        },\n      ],\n    },\n  };\n};\n```\n\nThe webpack plugin will parse this and add `./src/app.ts` and `./src/vendor.ts`\nas entry files. It will also add `base64-inline-loader` as a referenced\ndependency.\n\n:::tip[Summary]\n\nIn your config files, plugins can find additional entry files and also other\nconfig files recursively.\n\n:::\n\n## Bringing it all together\n\nSometimes a configuration file is a JavaScript or TypeScript file that imports\ndependencies, but also contains configuration that needs to be parsed by a\nplugin to find additional dependencies.\n\nLet's take a look at this example Vite configuration file:\n\n```ts title=\"vite.config.ts\"\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig(async ({ mode, command }) => {\n  return {\n    plugins: [react()],\n    test: {\n      setupFiles: ['./setup-tests.ts'],\n      environment: 'happy-dom',\n      coverage: {\n        provider: 'c8',\n      },\n    },\n  };\n});\n```\n\nThis file imports `vite` and `@vitejs/plugin-react` directly, but also\nindirectly references the `happy-dom` and `@vitest/coverage-c8` packages.\n\nThe Vite plugin of Knip will **dynamically** load this configuration file and\nparse the exported configuration. But it's not aware of the `vite` and\n`@vitejs/plugin-react` imports. This is why such `config` files are also\nautomatically added as `entry` files for Knip to **statically** resolve the\n`import` and `require` statements.\n\nAdditionally, `./setup-tests.ts` will be added as an `entry` file.\n\n:::note\n\nWhen plugins dynamically load configuration files, conditional dependencies may\nnot be detected if the condition evaluates differently during analysis. See\n[conditional or dynamic dependencies][9] for details and workarounds.\n\n:::\n\n## Command-Line Arguments\n\nPlugins may define the arguments where Knip should look for entry files,\nconfiguration files and dependencies. We've already seen some examples above:\n\n```sh\nnode --loader tsx scripts/deploy.ts\nplaywright test -c playwright.web.config.ts\n```\n\nPlease see [script parser][10] for more details.\n\n## Config File Location\n\nIf configuration files aren't in their default location and they are not\nreferenced through some script like `vite -c ./dir/vite.config.ts`, then make\nsure to tell Knip about it. Two examples:\n\n```json title=\"knip.jsonc\"\n{\n  \"playwright\": { \"config\": [\"e2e/playwright.config.ts\"] },\n  \"vite\": \"packages/*/vite.config.ts\" // shorthand without `config` and array notation\n}\n```\n\nThis is common in projects where a directory like `packages/lib` is not an\nactual workspace with a `package.json` file. Also see [integrated monorepos][11]\nfor similar cases.\n\n## Summary\n\n:::tip[Summary]\n\nPlugins are configured with two distinct types of files:\n\n- `config` files are dynamically loaded and parsed by the plugin\n- `entry` files are added to the module graph\n- Both can recursively lead to additional entry files, config files and\n  dependencies\n\n:::\n\n[1]: ../reference/plugins.md\n[2]: ../writing-a-plugin/index.md\n[3]: #configuration-files\n[4]: #entry-files\n[5]: #command-line-arguments\n[6]: ./entry-files.md\n[7]: ../reference/plugins/eslint.md\n[8]: ../reference/plugins/vitest.md\n[9]: ../guides/handling-issues.mdx#conditional-or-dynamic-dependencies\n[10]: ../features/script-parser.md\n[11]: ../features/integrated-monorepos.md\n","packages/docs/src/content/docs/explanations/why-use-knip.md":"---\ntitle: Why use Knip?\ndescription: Why remove unused files, exports and dependencies, and how Knip finds them comprehensively across greenfield and legacy (mono)repos.\n---\n\nThe value of removing clutter is clear, but finding it manually is tedious. Meet\nKnip: comprehensive and accurate results at any scale.\n\n:::tip[TL;DR]\n\nUnused files, exports and dependencies pile up as projects grow. Removing them\nimproves maintenance, performance, security and onboarding, and prevents\nregressions in CI. Knip automates finding (and fixing) all three,\ncomprehensively and at any scale.\n\n:::\n\n## Less is more\n\nThere are plenty of reasons to delete unused files, dependencies and \"dead\ncode\":\n\n- Easier maintenance: things are easier to manage when there's less of it.\n- Improved performance: startup time, build time and/or bundle size can be\n  negatively impacted when unused code, files and/or dependencies are included.\n  Relying on tree-shaking when bundling code helps, but it's not a silver\n  bullet.\n- Increased security: less code and dependencies means less room for weak spots.\n- Easier onboarding: there should be no doubts about whether files, dependencies\n  and exports are actually in use or not. Especially for people new to the\n  project and/or taking over responsibilities this is harder to grasp.\n- Prevent regressions: tools like TypeScript, ESLint and Prettier do all sorts\n  of checks and linting to report violations and prevent regressions. Knip does\n  the same for dependencies, exports and files that are obsolete.\n- Keeping dead code around has a negative value on readability, as it can be\n  misleading and distracting. Even if it serves no purpose it will need to be\n  maintained (source: [Safe dead code removal → YAGNI][1]).\n- Also see [Why are unused dependencies a problem?][2] and [Why are unused\n  exports a problem?][3].\n\n## Automation\n\nCode and dependency management is usually not the most exciting task for most of\nus. Knip's mission is to automate finding clutter. This is such a tedious job if\nyou were to do it manually, and where would you even start? Knip applies many\ntechniques and heuristics to report what you need and save a lot of time.\n\n:::tip\n\nKnip not only finds clutter, it can also [remove clutter][4]!\n\nUse Knip next to a linter like ESLint or Biome: after removing unused variables\ninside files, Knip might find even more unused code. Rinse and repeat!\n\n:::\n\n## Comprehensive\n\nYou can use alternative tools that do the same. However, the advantage of a\nstrategy that addresses all of dependencies, exports and files is in their\nsynergy:\n\n- Utilizing plugins to find their dependencies includes the capacity to find\n  additional entry and configuration files. This results in more resolved and\n  used files. Better coverage gives better insights into unused files and\n  exports.\n- Analyzing more files reveals more unused exports and dependency usage,\n  refining the list of both unused and unlisted dependencies.\n- This approach is amplified in a [monorepo setting][5]. In fact, files and\n  internal dependencies can recursively reference each other (across\n  workspaces).\n\nKnip reaches this coverage through [fine-grained entry points][6], [custom\nmodule resolution][7], [configuration-file parsers][8], an [advanced\nshell-script parser][9], and [built-in and custom compilers][10], then [fixes\nmost of it automatically][4].\n\n## Greenfield or Legacy\n\nInstalling Knip in greenfield projects ensures the project stays neat and tidy\nfrom the start. Add it to your CI workflow and prevent any regressions from\nentering the codebase.\n\n:::tip\n\nUse Knip in a CI environment to prevent future regressions.\n\n:::\n\nIn large and/or legacy projects, Knip may report false positives and require\nsome configuration. It aims to be a great assistant when cleaning up parts of\nthe project or doing large refactors. Even a list of results with a few false\npositives is many times better and faster than if you were to do it manually.\n\n## Unobtrusive\n\nKnip does not introduce new syntax for you to learn. This may sound obvious, but\nconsider comments like the following:\n\n```js\n// eslint-disable-next-line\n// prettier-ignore\n// @ts-expect-error\n```\n\nKnip doesn't have similar comments like `// knip-ignore` so you can get rid of\nfalse positives for a variety of reasons:\n\n1. A false positive may be a bug in Knip, and should be reported, not dismissed.\n2. Instead of proprietary comments, use [standardized annotations][11] that also\n   serve as documentation.\n3. In the event you want to remove Knip, just uninstall `knip` without having to\n   remove useless comments scattered throughout the codebase.\n\nTip: use `@lintignore` in JSDoc comments, so other linters can use the same.\n\n[1]: https://jfmengels.net/safe-dead-code-removal/#yagni-you-arent-gonna-need-it\n[2]: ../typescript/unused-dependencies.md#why-are-unused-dependencies-a-problem\n[3]: ../typescript/unused-exports.md#why-are-unused-exports-a-problem\n[4]: ../features/auto-fix.mdx\n[5]: ../features/monorepos-and-workspaces.md\n[6]: ./entry-files.md\n[7]: ../reference/faq.md#why-doesnt-knip-use-an-existing-module-resolver\n[8]: ./plugins.md#configuration-files\n[9]: ../features/script-parser.md\n[10]: ../features/compilers.md\n[11]: ../reference/jsdoc-tsdoc-tags.md\n","packages/docs/src/content/docs/features/catalogs.md":"---\ntitle: Catalogs\ndescription: How Knip finds unused pnpm, Yarn and Bun catalog entries referenced through the `catalog:` protocol, and removes them with auto-fix.\n---\n\nCatalogs let you define dependency version ranges once and reference them across\nworkspaces in a monorepo. Knip reports catalog entries that are defined but no\nlonger referenced, and references to entries that do not exist. It can remove\nunused entries with [auto-fix][1].\n\n## Supported catalogs\n\nKnip reads catalogs from the first applicable location:\n\n- `pnpm-workspace.yaml` — the `catalog` (default) and `catalogs` (named) keys\n- `.yarnrc.yml` — the `catalog` and `catalogs` keys\n- `package.json` — the `catalog` and `catalogs` keys\n- `package.json#workspaces` — the `catalog` and `catalogs` keys (Bun)\n\n## Unused catalog entries\n\nA catalog entry is reported as unused when no workspace references it through\nthe `catalog:` protocol in its `package.json`:\n\n```json title=\"packages/app/package.json\"\n{\n  \"dependencies\": {\n    \"react\": \"catalog:\",\n    \"zod\": \"catalog:validation\"\n  }\n}\n```\n\n`catalog:` references the `default` catalog, while `catalog:validation`\nreferences the named `validation` catalog. References are resolved from\n`dependencies`, `devDependencies`, `peerDependencies`, `optionalDependencies`,\n`resolutions`, `pnpm-workspace.yaml#overrides`, and `pnpm.overrides` in the root\n`package.json` (pnpm 10 and older).\n\nEntries defined in a catalog but not referenced anywhere are reported as [unused\ncatalog entries][2].\n\n## Unresolved catalog references\n\nA `catalog:` reference is reported when the selected catalog does not define\nthat package. These issues point to the consuming `package.json` or\n`pnpm-workspace.yaml`, where package managers would otherwise fail to resolve\nthe version.\n\n## Filter and fix\n\nThe `catalog` and `catalogReferences` issue types are included by the\n[`--dependencies`][3] shortcut. Focus on them (or exclude them) like any other\nissue type:\n\n```sh\nknip --include catalog,catalogReferences\nknip --exclude catalog,catalogReferences\n```\n\n[Auto-fix][1] removes unused catalog entries from the catalog file:\n\n```sh\nknip --fix --fix-type catalog\n```\n\n[1]: ./auto-fix.mdx#catalog-entries\n[2]: ../reference/issue-types.md\n[3]: ./rules-and-filters.md#shorthands\n","packages/docs/src/content/docs/features/compilers.md":"---\ntitle: Compilers\ndescription: Built-in and custom compilers let Knip analyze non-standard files like `.astro`, `.mdx`, `.svelte` and `.vue` for imports and exports.\n---\n\nProjects may have source files that are not JavaScript or TypeScript, and thus\nrequire compilation (or transpilation, or pre-processing, you name it). Files\nlike `.mdx`, `.astro`, `.vue` and `.svelte` may also import other source files\nand external dependencies. So ideally, these files are included when linting the\nproject. That's why Knip supports compilers.\n\n## Built-in compilers\n\nKnip has built-in \"compilers\" for the following file extensions:\n\n- `.astro`\n- `.css` (only enabled by `tailwindcss`)\n- `.mdx`\n- `.prisma`\n- `.sass` + `.scss`\n- `.less`\n- `.styl` + `.stylus`\n- `.svelte`\n- `.tsrx`\n- `.vue`\n\nKnip does not include real compilers for those files, but regular expressions to\ncollect `import` statements. This is fast, requires no dependencies, and enough\nfor Knip to build the module graph. The tradeoff is that unused exports inside\nthese files go unreported.\n\nReal compilers recover those exports, but bring their own challenges. The Svelte\ncompiler, for instance, keeps `exports` intact even when they represent\ncomponent properties, so Knip reports them as unused. When you need that\nfidelity, override any built-in with the framework's own compiler (see the\n[Svelte][1] and [Vue][2] examples below). For example, to report unused exports\nin [`.tsrx`][3] files.\n\nCompilers are enabled only when a related dependency is found. The `.tsrx`\ncompiler when a `@tsrx/*` package is installed, for example. If that detection\ndoesn't work for your project, set `true` to enable any compiler manually:\n\n```ts title=\"knip.ts\"\nexport default {\n  compilers: {\n    mdx: true,\n  },\n};\n```\n\n## Compiled files and `project` patterns\n\nThe default `project` patterns include compiler extensions automatically. When\nyou override `project`, list them explicitly:\n\n```ts title=\"knip.ts\"\nexport default {\n  project: ['src/**/*.{ts,tsx,css}'],\n};\n```\n\nFiles outside `project` are not analyzed, so their imports don't count. A\nnarrowed pattern like `['src/**/*.{ts,tsx}']` silently drops everything a\nstylesheet imports, which is a common source of false positives: `@import\n'tailwindcss'` in an excluded `.css` file gets `tailwindcss` reported as an\nunused dependency. Knip reports a configuration hint when a compiled extension\nis excluded this way.\n\n## Custom compilers\n\nBuilt-in compilers can be overridden, and additional compilers can be added.\nSince compilers are functions, the Knip configuration file must be a dynamic\n`.js` or `.ts` file.\n\n### Interface\n\nThe compiler function interface is straightforward. Text in, text out:\n\n```ts\n(source: string, filename: string) => string | PromiseLike<string>;\n```\n\nReturn a string or a Promise-like value that resolves to a string. Knip compiles\nfiles on demand and awaits asynchronous results; the `async` keyword is\noptional.\n\n### Examples\n\n- [CSS][4]\n- [MDX][5]\n- [Svelte][1]\n- [Vue][2]\n\n#### CSS\n\nHere's an example, minimal compiler for CSS files:\n\n```ts title=\"knip.ts\"\nexport default {\n  compilers: {\n    css: (text: string) => [...text.matchAll(/(?<=@)import[^;]+/g)].join('\\n'),\n  },\n};\n```\n\nYou may wonder why the CSS compiler is not included by default. It's currently\nnot clear if it should be included. And if so, what would be the best way to\ndetermine it should be enabled, and what syntax(es) it should support. Note that\nTailwind CSS, SASS/SCSS, Less and Stylus compilers are included.\n\n#### MDX\n\nAnother example, in case the built-in MDX compiler is not enough:\n\n```ts\nimport { compile } from '@mdx-js/mdx';\n\nexport default {\n  compilers: {\n    mdx: async text => (await compile(text)).toString(),\n  },\n};\n```\n\n#### Svelte\n\nIn a Svelte project, the compiler is automatically enabled. Override and use\nSvelte's compiler for better results if the built-in \"compiler\" is not enough:\n\n```ts\nimport type { KnipConfig } from 'knip';\nimport { compile } from 'svelte/compiler';\n\nexport default {\n  compilers: {\n    svelte: (source: string) => compile(source, {}).js.code,\n  },\n} satisfies KnipConfig;\n```\n\n#### Vue\n\nIn a Vue project, the compiler is automatically enabled. Override and use Vue's\nparser for better results if the built-in \"compiler\" is not enough:\n\n```ts\nimport type { KnipConfig } from 'knip';\nimport {\n  parse,\n  type SFCScriptBlock,\n  type SFCStyleBlock,\n} from 'vue/compiler-sfc';\n\nfunction getScriptBlockContent(block: SFCScriptBlock | null): string[] {\n  if (!block) return [];\n  if (block.src) return [`import '${block.src}'`];\n  return [block.content];\n}\n\nfunction getStyleBlockContent(block: SFCStyleBlock | null): string[] {\n  if (!block) return [];\n  if (block.src) return [`@import '${block.src}';`];\n  return [block.content];\n}\n\nfunction getStyleImports(content: string): string {\n  return [...content.matchAll(/(?<=@)import[^;]+/g)].join('\\n');\n}\n\nconst config = {\n  compilers: {\n    vue: (text: string, filename: string) => {\n      const { descriptor } = parse(text, { filename, sourceMap: false });\n      return [\n        ...getScriptBlockContent(descriptor.script),\n        ...getScriptBlockContent(descriptor.scriptSetup),\n        ...descriptor.styles.flatMap(getStyleBlockContent).map(getStyleImports),\n      ].join('\\n');\n    },\n  },\n} satisfies KnipConfig;\n\nexport default config;\n```\n\n## Tracking non-source files\n\nTo track any file extension that's not meant to compile to JavaScript, register\na no-op compiler:\n\n```ts title=\"knip.ts\"\nexport default {\n  compilers: { template: () => '' },\n};\n```\n\n[1]: #svelte\n[2]: #vue\n[3]: https://tsrx.dev\n[4]: #css\n[5]: #mdx\n","packages/docs/src/content/docs/features/custom-elements.md":"---\ntitle: Custom Elements\ndescription: How Knip credits custom element classes registered via `customElements.define()` or Lit, FAST, Stencil and Catalyst decorators.\n---\n\nCustom elements are registered under a tag name. When such a class isn't\nreferenced elsewhere, Knip would report the export as unused. Instead, Knip\nrecognizes the registration and considers the class used.\n\nNative registration needs no configuration. Framework registrations are credited\nthrough their plugin, which is enabled when the framework is a dependency.\n\n## Native registration\n\nThe web standard `customElements.define()` credits the registered class:\n\n```ts\nexport class MyCard extends HTMLElement {}\n\ncustomElements.define('my-card', MyCard);\n```\n\nThe registry can be the global `customElements` — directly, through a `window`,\n`globalThis` or `self` prefix, or a local alias — a `CustomElementRegistry`\ninstance, or a shadow root's scoped registry:\n\n```ts\nconst registry = new CustomElementRegistry();\nregistry.define('my-card', MyCard);\n```\n\nA class can also register itself from a `static` block using `this`:\n\n```ts\nexport class MyCard extends HTMLElement {\n  static {\n    customElements.define('my-card', this);\n  }\n}\n```\n\n## Framework registration\n\n| Framework     | Plugin        | Registration                    | Imported from                                            |\n| ------------- | ------------- | ------------------------------- | -------------------------------------------------------- |\n| [Lit][1]      | [lit][2]      | `@customElement('tag')`         | `lit/decorators`, `lit-element`, `@lit/reactive-element` |\n| [FAST][3]     | [fast][4]     | `@customElement` or `.define()` | `@microsoft/fast-element`                                |\n| [Stencil][5]  | [stencil][6]  | `@Component({ tag })`           | `@stencil/core`                                          |\n| [Catalyst][7] | [catalyst][8] | `@controller`                   | `@github/catalyst`                                       |\n\nThe decorator counts only when imported from the framework. A locally defined or\ndifferently-imported decorator is ignored.\n\n### Lit\n\nA `@customElement('tag')` decorator credits the class when the matching plugin\nis enabled:\n\n```ts\nimport { LitElement } from 'lit';\nimport { customElement } from 'lit/decorators.js';\n\n@customElement('my-card')\nexport class MyCard extends LitElement {}\n```\n\n### FAST\n\n[FAST][3] also registers elements through a static `define()` or `defineAsync()`\nmethod. A class extending `FASTElement`, directly or through a mixin, is\ncredited when registered this way:\n\n```ts\nimport { FASTElement } from '@microsoft/fast-element';\n\nexport class MyCard extends FASTElement {}\n\nMyCard.define('my-card');\n```\n\n### Stencil\n\nA `@Component` decorator credits the class:\n\n```ts\nimport { Component } from '@stencil/core';\n\n@Component({ tag: 'my-card' })\nexport class MyCard {}\n```\n\n### Catalyst\n\nThe bare `@controller` decorator registers the element under a tag derived from\nthe class name:\n\n```ts\nimport { controller } from '@github/catalyst';\n\n@controller\nexport class MyCardElement extends HTMLElement {}\n```\n\n[1]: https://lit.dev\n[2]: ../reference/plugins/lit.md\n[3]: https://fast.design\n[4]: ../reference/plugins/fast.md\n[5]: https://stenciljs.com\n[6]: ../reference/plugins/stencil.md\n[7]: https://catalyst.rocks\n[8]: ../reference/plugins/catalyst.md\n","packages/docs/src/content/docs/features/integrated-monorepos.md":"---\ntitle: Integrated Monorepos\ndescription: Configure Knip for repositories with a single `package.json` and many projects, like the Nx integrated monorepo style.\n---\n\nSome repositories have a single `package.json`, but consist of multiple projects\nwith configuration files across the repository. A good example is the [Nx\nintegrated monorepo style][1].\n\n:::tip\n\nAn integrated monorepo is a single workspace.\n\n:::\n\n## Entry Files\n\nThe default entrypoints files might not be enough. Here's an idea that might fit\nthis type of monorepo:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"{apps,libs}/**/src/index.{ts,tsx}\"],\n  \"project\": [\"{apps,libs}/**/src/**/*.{ts,tsx}\"]\n}\n```\n\n## Plugins\n\nLet's assume some of these projects are applications (\"apps\") which have their\nown ESLint configuration files and Cypress configuration and test files. This\nmay result in those files getting reported as unused, and consequently also the\ndependencies they import and refer to.\n\nIn that case, we could configure the ESLint and Cypress plugins like this:\n\n```json title=\"knip.json\"\n{\n  \"eslint\": {\n    \"config\": [\"{apps,libs}/**/.eslintrc.json\"]\n  },\n  \"cypress\": {\n    \"entry\": [\"apps/**/cypress.config.ts\", \"apps/**/cypress/e2e/*.spec.ts\"]\n  }\n}\n```\n\nAdapt the file patterns to your project, and the relevant `config` and `entry`\nfiles and dependencies should no longer be reported as unused.\n\n## Internal Workspace Dependencies\n\nA note about repositories with multiple `package.json` files and **internal**\nworkspace packages: it is recommended to list all dependencies in each consuming\n`package.json`, allowing Knip to do fine-grained reporting of both unused and\nunlisted dependencies.\n\nAn alternative is to `ignoreDependencies: [\"@internal/*\"]`.\n\n[1]: https://nx.dev/getting-started/tutorials/integrated-repo-tutorial\n","packages/docs/src/content/docs/features/monorepos-and-workspaces.md":"---\ntitle: Monorepos & Workspaces\ndescription: How Knip discovers and configures workspaces in package-based monorepos, with per-workspace options and the `--workspace` filter.\n---\n\nWorkspaces are handled out-of-the-box by Knip.\n\nWorkspaces are sometimes also referred to as package-based monorepos, or as\npackages in a monorepo. Knip uses the term workspace exclusively to indicate a\ndirectory that has a `package.json`.\n\n## Configuration\n\nHere's example configuration with custom `entry` and `project` patterns:\n\n```json title=\"knip.json\"\n{\n  \"workspaces\": {\n    \".\": {\n      \"entry\": \"scripts/*.js\",\n      \"project\": \"scripts/**/*.js\"\n    },\n    \"packages/*\": {\n      \"entry\": \"{index,cli}.ts\",\n      \"project\": \"**/*.ts\"\n    },\n    \"packages/cli\": {\n      \"entry\": \"bin/cli.js\"\n    }\n  }\n}\n```\n\n:::tip\n\nRun Knip without any configuration to see if and where custom `entry` and/or\n`project` files are necessary per workspace.\n\n:::\n\nEach workspace has the same [default configuration][1].\n\nThe root workspace is named `\".\"` under `workspaces` (like in the example\nabove).\n\n:::caution\n\nIn a project with workspaces, the `entry` and `project` options at the root\nlevel are ignored. Use the workspace named `\".\"` for those (like in the example\nabove).\n\n:::\n\n## Workspaces\n\nKnip reads workspaces from four possible locations:\n\n1. The `workspaces` array in `package.json` (npm, Bun, Yarn, Lerna)\n2. The `packages` array in `pnpm-workspace.yaml` (pnpm)\n3. The `workspaces.packages` array in `package.json` (legacy)\n4. The `workspaces` object in Knip configuration\n\nThe `workspaces` in Knip configuration (4) not already defined in the root\n`package.json` or `pnpm-workspace.yaml` (1, 2, 3) are added to the analysis.\n\n:::caution\n\nA workspace must have a `package.json` file.\n\n:::\n\nFor projects with only a root `package.json`, please see [integrated\nmonorepos][2].\n\n## Additional workspaces\n\nIf a workspace is not configured as such in `package.json#workspaces` (or\n`pnpm-workspace.yaml`) it can be added to the Knip configuration manually. Add\ntheir path to the `workspaces` configuration object the same way as\n`\"packages/cli\": {}` in the example above.\n\n## Source mapping\n\nSee [Source Mapping][3].\n\n## Additional options\n\nThe following options are available inside workspace configurations:\n\n- [ignore][4]\n- [ignoreBinaries][5]\n- [ignoreDependencies][6]\n- [ignoreIssues][7]\n- [ignoreMembers][8]\n- [ignoreUnresolved][9]\n- [includeEntryExports][10]\n\n[Plugins][11] can be configured separately per workspace.\n\nUse `--debug` for verbose output and see the workspaces Knip includes, their\nconfigurations, enabled plugins, glob options and resolved files.\n\n## Filter workspaces\n\nUse the `--workspace` (or `-W`) argument to select one or more workspaces:\n\n```sh\nknip --workspace packages/my-lib\n```\n\nThe filter supports multiple formats:\n\n```sh\nknip --workspace @myorg/my-lib     # Package name\nknip --workspace '@myorg/*'        # Package name glob\nknip --workspace packages/my-lib   # Directory path\nknip --workspace './apps/*'        # Directory glob\n```\n\nCombine selectors to include or exclude workspaces:\n\n```sh\nknip --workspace @myorg/* --workspace '!@myorg/legacy'\nknip --workspace './apps/*' --workspace '@shared/utils'\n```\n\nThis will include the target workspace(s), but also ancestor, dependency and\ndependent workspaces. For three reasons:\n\n- Ancestor workspaces may list dependencies in `package.json` the linted\n  workspace uses.\n- Dependency workspaces may provide configuration and source information used by\n  the linted workspace.\n- Dependent workspaces may reference exports from the linted workspace.\n\nTo lint the workspace in isolation, there are two options:\n\n- Combine the `workspace` argument with [strict production mode][12].\n- Run Knip from inside the workspace directory.\n\n[1]: ../overview/configuration.md#defaults\n[2]: ./integrated-monorepos.md\n[3]: ./source-mapping.md\n[4]: ../reference/configuration.md#ignore\n[5]: ../reference/configuration.md#ignorebinaries\n[6]: ../reference/configuration.md#ignoredependencies\n[7]: ../reference/configuration.md#ignoreissues\n[8]: ../reference/configuration.md#ignoremembers\n[9]: ../reference/configuration.md#ignoreunresolved\n[10]: ../reference/configuration.md#includeentryexports\n[11]: ../reference/configuration.md#plugins\n[12]: ./production-mode.md#strict-mode\n","packages/docs/src/content/docs/features/production-mode.md":"---\ntitle: Production Mode\ndescription: Use `--production` and `--strict` with `!` entry patterns to lint only shipped code, ignoring tests, stories and config files.\n---\n\nThe default mode for Knip is comprehensive and targets all project code,\nincluding configuration files, test files, Storybook stories, and so on. Test\nfiles usually import production files. This prevents production files or their\nexports from being reported as unused, while sometimes both of them can be\ndeleted. Knip features a \"production mode\" to focus only on the code that you\nship.\n\n## Configuration\n\nTo tell Knip what is production code, add an exclamation mark behind each\n`pattern!` that represents production code:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts!\", \"build/script.js\"],\n  \"project\": [\"src/**/*.ts!\", \"build/*.js\"]\n}\n```\n\nDepending on file structure and enabled plugins, you might not need to modify\nyour configuration at all.\n\nRun Knip with the `--production` flag:\n\n```sh\nknip --production\n```\n\nHere's what's included in production mode:\n\n- Only `entry` and `project` patterns suffixed with `!`\n- Only production `entry` file patterns exported by plugins (such as Next.js and\n  Remix)\n- Only the `start` script (of `package.json#scripts`)\n- Ignore exports with the [`@internal` tag][1]\n\n:::note\n\nThe production run does not replace the default run. Depending on your needs you\ncan run either of them or both separately. Usually both modes can share the same\nconfiguration.\n\n:::\n\nTo see the difference between default and production mode in great detail, use\nthe `--debug` flag and inspect what entry and project files are used, and the\nplugins that are enabled. For instance, in production mode this shows that files\nsuch as tests and Storybook files (stories) are excluded from the analysis.\n\nIn case files like mocks and test helpers are reported as unused files, use\nnegated patterns to exclude those files in production mode:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts!\"],\n  \"project\": [\"src/**/*.ts!\", \"!src/test-helpers/**!\"]\n}\n```\n\nAlso see [configuring project files][2] to align `entry` and `project` with\nproduction mode.\n\n## Strict Mode\n\nIn production mode, only `dependencies` (not `devDependencies`) are considered\nwhen finding unused or unlisted dependencies.\n\nAdditionally, the `--strict` flag can be added to:\n\n- Verify isolation: workspaces should use strictly their own `dependencies`\n- Include required `peerDependencies` when finding unused or unlisted\n  dependencies\n- [Distinguish development-only type imports from types exposed to package\n  consumers][3]\n\n```sh\nknip --production --strict\n```\n\nUsing `--strict` implies `--production`, so the latter can be omitted.\n\n## Types\n\nAdd `--exclude types` if you don't want to include types in the report:\n\n```sh\nknip --production --exclude types\n```\n\n[1]: ../reference/jsdoc-tsdoc-tags.md#internal\n[2]: ../guides/configuring-project-files.md\n[3]: ../guides/handling-issues.mdx#production-types\n","packages/docs/src/content/docs/features/reporters.md":"---\ntitle: Reporters & Preprocessors\ndescription: Knip's built-in reporters (including the shape of `knip --reporter json` for scripts, CI and coding agents), plus custom reporters and preprocessors.\n---\n\n## Built-in Reporters\n\nKnip provides the following built-in reporters:\n\n- [`codeclimate`][1]\n- [`codeowners`][2]\n- `compact`\n- [`cycles`][3]\n- [`disclosure`][4]\n- [`github-actions`][5]\n- [`json`][6]\n- [`markdown`][7]\n- [`sarif`][8]\n- `symbols` (default)\n\nExample usage:\n\n```sh\nknip --reporter compact\n```\n\n### CodeClimate\n\nThe built-in `codeclimate` reporter generates output in the Code Climate Report\nJSON format. Example usage:\n\n```text\n$ knip --reporter codeclimate\n\n[\n  {\n    \"type\": \"issue\",\n    \"check_name\": \"Unused exports\",\n    \"description\": \"isUnused\",\n    \"categories\": [\"Bug Risk\"],\n    \"location\": {\n      \"path\": \"path/to/file.ts\",\n      \"positions\": {\n        \"begin\": {\n          \"line\": 6,\n          \"column\": 1\n        }\n      }\n    },\n    \"severity\": \"major\",\n    \"fingerprint\": \"e9789995c1fe9f7d75eed6a0c0f89e84\"\n  }\n]\n```\n\n### CODEOWNERS\n\nWhen a `.github/CODEOWNERS` file exists, each entry gains an `owners` array.\nPoint the reporter at a different path through [`--reporter-options`][9]:\n\n```sh\nknip --reporter json --reporter-options '{\"codeowners\":\"docs/CODEOWNERS\"}'\n```\n\n### Cycles\n\nA verbose, multi-line tree view of [circular dependencies][10]. Each file path\nis suffixed with the location of the import that continues the cycle. Each edge\nshows the import kind and specifier, descends one file per level, and closes\n(`↩`) back to the file it started from.\n\nUse `--cycles` to report only circular dependencies and `--reporter cycles` to\ndisplay them as a tree:\n\n```text\n$ knip --cycles --reporter cycles\n\nCircular dependencies (1)\n\nsrc/i18n/index.ts:1:28\n└── import ./middleware → src/i18n/middleware.ts:3:15\n    └── re-export ../core/i18n/handler → src/core/i18n/handler.ts:5:10\n        └── import ../../i18n → src/i18n/index.ts:1:28 ↩\n```\n\nKnip reports representative cycle paths found while walking the module graph.\nThis is not an exhaustive list of every possible simple cycle in a cyclic\nsubgraph, because that can produce a noisy and very large report. If the same\nfile participates in multiple distinct reported paths, each path is shown\nseparately.\n\nUse [`cycles.allow`][11] to accept known cycle paths.\n\nDynamic imports are ignored by default because they are commonly used to avoid\nsynchronous circular loads. Set [`cycles.dynamicImports`][11] to include them.\nRepeated starting imports are grouped under one heading.\n\nFor one line per cycle path, use `knip --cycles` with the default reporter. To\nreport unused code as well, [combine the issue-type shorthands][12].\n\nCycles are warnings by default. Set `\"rules\": { \"cycles\": \"error\" }` to make\nreported cycles cause a non-zero exit code.\n\n### Disclosure\n\nThis reporter is useful for sharing large reports. Groups of issues are rendered\nin a closed state initially. The reporter renders this:\n\n````text\n$ knip --reporter disclosure\n\n<details>\n<summary>Unused files (2)</summary>\n\n```\nunused.ts\ndangling.js\n```\n\n</details>\n\n<details>\n<summary>Unused dependencies (2)</summary>\n\n```\nmy-package     package.json:17:5\nunused-dep     package.json:20:5\n```\n\n</details>\n````\n\nThe above can be copy-pasted where HTML and Markdown is supported, such as a\nGitHub issue or pull request, and renders like so:\n\n<details>\n  <summary>Unused files (2)</summary>\n\n```\nunused.ts\ndangling.js\n```\n\n</details>\n\n<details>\n  <summary>Unused dependencies (2)</summary>\n\n```\nmy-package     package.json:17:5\nunused-dep     package.json:20:5\n```\n\n</details>\n\n### GitHub Actions\n\nUse the GitHub Actions reporter in a workflow for annotations in pull requests.\nExample usage:\n\n```sh\nknip --reporter github-actions\n```\n\nChanged files in pull requests will now contain inline annotations for lint\nfindings.\n\n### JSON\n\nThe `json` reporter prints machine-readable results for scripts, CI, and tools\n(including coding agents) to consume:\n\n```sh\nknip --reporter json\n```\n\nOutput is one line of JSON. Formatted here for readability:\n\n```json\n{\n  \"issues\": [\n    {\n      \"file\": \"src/legacy.ts\",\n      \"files\": [{ \"name\": \"src/legacy.ts\" }]\n    },\n    {\n      \"file\": \"src/math.ts\",\n      \"exports\": [{ \"name\": \"factorial\", \"line\": 12, \"col\": 14, \"pos\": 256 }],\n      \"types\": [{ \"name\": \"Radians\", \"line\": 20, \"col\": 13, \"pos\": 410 }]\n    },\n    {\n      \"file\": \"package.json\",\n      \"dependencies\": [{ \"name\": \"lodash\" }],\n      \"unlisted\": [{ \"name\": \"rimraf\" }]\n    }\n  ]\n}\n```\n\nThe top level is an object with a single `issues` array. Each element groups\nevery issue found in one file:\n\n| Field        | Type         | Notes                                               |\n| :----------- | :----------- | :-------------------------------------------------- |\n| `file`       | `string`     | Path relative to the working directory              |\n| `owners`     | `{ name }[]` | Code owners, only when a `CODEOWNERS` file is found |\n| _issue type_ | array        | One key per enabled issue type (see below)          |\n\nEach entry carries a key for **every enabled [issue type][10]**, so the keys are\nthe same across entries. An array is empty when that file has no issues of that\ntype. Drop a type's key by disabling it with [filters or rules][12].\n\nIssue-type items are objects with position info:\n\n| Field       | Type      | Notes                                          |\n| :---------- | :-------- | :--------------------------------------------- |\n| `name`      | `string`  | The unused symbol, dependency, file, or import |\n| `namespace` | `string?` | Set for namespace members                      |\n| `line`      | `number?` | 1-based line                                   |\n| `col`       | `number?` | 1-based column                                 |\n| `pos`       | `number?` | Character offset                               |\n\nSee [Issue types][10] for the full set of issue-type keys.\n\nFor a typed object instead of JSON to parse, write a [custom reporter][13].\nCoding agents can also call Knip through the [MCP server][14], which returns\nstructured results and configuration hints directly.\n\n### SARIF\n\nThe `sarif` reporter emits [SARIF 2.1.0][15] for code-scanning integrations:\n\n```sh\nknip --reporter sarif > knip.sarif\n```\n\nFor example, upload the report to GitHub Code Scanning after installing project\ndependencies:\n\n```yaml\npermissions:\n  contents: read\n  security-events: write\n\nsteps:\n  - uses: actions/checkout@v4\n  - run: pnpm exec knip --reporter sarif > knip.sarif\n  - if: always()\n    uses: github/codeql-action/upload-sarif@v4\n    with:\n      sarif_file: knip.sarif\n```\n\nThe upload step runs even when Knip finds issues and exits non-zero. GitHub Code\nScanning availability for private repositories depends on the repository's\nGitHub Code Security plan.\n\n### Markdown\n\nThe built-in `markdown` reporter output is meant to be saved to a Markdown file.\nThis allows following the changes in issues over time. It reports issues in\nMarkdown tables separated by issue types as headings, for example:\n\n```md\n# Knip report\n\n## Unused files (1)\n\n- src/unused.ts\n\n## Unlisted dependencies (2)\n\n| Name            | Location          | Severity |\n| :-------------- | :---------------- | :------- |\n| unresolved      | src/index.ts:8:23 | error    |\n| @org/unresolved | src/index.ts:9:23 | error    |\n\n## Unresolved imports (1)\n\n| Name         | Location           | Severity |\n| :----------- | :----------------- | :------- |\n| ./unresolved | src/index.ts:10:12 | error    |\n```\n\n## Custom Reporters\n\nWhen the provided built-in reporters are not sufficient, a custom local reporter\ncan be implemented or an external reporter can be used. Multiple reporters can\nbe used at once by repeating the `--reporter` argument.\n\nThe results are passed to the function from its default export and can be used\nto write issues to `stdout`, a JSON or CSV file, or sent to a service. It\nsupports a local JavaScript or TypeScript file or an external dependency.\n\n### Local\n\nThe default export of the reporter should be a function with this interface:\n\n```ts\ntype Reporter = (options: ReporterOptions) => void;\n\ntype ReporterOptions = {\n  report: Report;\n  issues: Issues;\n  counters: Counters;\n  configurationHints: ConfigurationHints;\n  isDisableConfigHints: boolean;\n  isTreatConfigHintsAsErrors: boolean;\n  cwd: string;\n  isProduction: boolean;\n  isShowProgress: boolean;\n  options: string;\n};\n```\n\nThe data can then be used to write issues to `stdout`, a JSON or CSV file, or\nsent to a service.\n\nHere's a most minimal reporter example:\n\n```ts title=\"./my-reporter.ts\"\nimport type { Reporter } from 'knip';\n\nconst reporter: Reporter = function (options) {\n  console.log(options.issues);\n  console.log(options.counters);\n};\n\nexport default reporter;\n```\n\nExample usage:\n\n```sh\nknip --reporter ./my-reporter.ts\n```\n\n### External\n\nPass `--reporter [pkg-name]` to use an external reporter. The default exported\nfunction of the `main` script (default: `index.js`) will be invoked with the\n`ReporterOptions`, just like a local reporter.\n\n## Preprocessors\n\nA preprocessor is a function that runs after the analysis is finished. It\nreceives the results from the analysis and should return data in the same\nshape/structure (unless you pass it to only your own reporter).\n\nThe data goes through the preprocessors before the final data is passed to the\nreporters. There are no built-in preprocessors. Just like reporters, use e.g.\n`--preprocessor ./my-preprocessor` from the command line (can be repeated).\n\nThe default export of the preprocessor should be a function with this interface:\n\n```ts\ntype Preprocessor = (options: ReporterOptions) => ReporterOptions;\n```\n\nLike reporters, you can use local JavaScript or TypeScript files and external\nnpm packages as preprocessors.\n\nExample preprocessor:\n\n```ts title=\"./preprocess.ts\"\nimport type { Preprocessor } from 'knip';\n\nconst preprocess: Preprocessor = function (options) {\n  // modify options.issues and options.counters\n  return options;\n};\n\nexport default preprocess;\n```\n\nExample usage:\n\n```sh\nknip --preprocessor ./preprocess.ts\n```\n\nPreprocessors can also be configured in the Knip configuration file:\n\n```json title=\"knip.json\"\n{\n  \"preprocessor\": \"./preprocess.ts\"\n}\n```\n\n[1]: #codeclimate\n[2]: #codeowners\n[3]: #cycles\n[4]: #disclosure\n[5]: #github-actions\n[6]: #json\n[7]: #markdown\n[8]: #sarif\n[9]: ../reference/cli.md#--reporter-options-json\n[10]: ../reference/issue-types.md\n[11]: ../reference/configuration.md#cycles\n[12]: ./rules-and-filters.md\n[13]: #custom-reporters\n[14]: ../reference/integrations.md\n[15]: https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html\n","packages/docs/src/content/docs/features/rules-and-filters.md":"---\ntitle: Rules & Filters\ndescription: Customize Knip's output with `--include`/`--exclude` filters, shorthand flags and `rules` to set issue types to error, warn or off.\n---\n\nUse rules or filters to customize Knip's output. This has various use cases, a\nfew examples:\n\n- Temporarily focus on a specific issue type.\n- You don't want to see unused `type`, `interface` and `enum` exports reported.\n- Specific issue types should be printed, but not counted against the total\n  error count.\n\nIf you're looking to handle one-off exceptions, also see [JSDoc tags][1].\n\n## Filters\n\nYou can `--include` or `--exclude` any of the reported issue types to slice &\ndice the report to your needs. Alternatively, they can be added to the\nconfiguration (e.g. `\"exclude\": [\"dependencies\"]`).\n\nUse `--include` to report only specific issue types. The following example\ncommands do the same:\n\n```sh\nknip --include files --include dependencies\nknip --include files,dependencies\n```\n\nOr the other way around, use `--exclude` to ignore the types you're not\ninterested in:\n\n```sh\nknip --include files --exclude enumMembers,duplicates\n```\n\nThe `nsExports` and `nsTypes` types are [off by default][2]. Including only\nthose _adds_ them to the default report, rather than narrowing it to just those.\n\n`cycles` is also off by default. `--include cycles` (or `\"include\": [\"cycles\"]`\nin configuration) reports only circular dependencies. Use it with the [cycles\nreporter][3] for a detailed tree view.\n\nAlso see the [list of issue types][4].\n\n### Shorthands\n\nKnip has shortcuts to report only specific issue types.\n\n1. The `--dependencies` flag includes:\n   - `dependencies` (and `devDependencies` + `optionalPeerDependencies`)\n   - `unlisted`\n   - `binaries`\n   - `unresolved`\n   - `catalog`\n   - `catalogReferences`\n\n2. The `--exports` flag includes:\n   - `exports`\n   - `types`\n   - `enumMembers`\n   - `namespaceMembers`\n   - `duplicates`\n\n3. The `--files` flag is a shortcut to report only unused files.\n\n4. The `--cycles` flag is a shortcut to report only circular dependencies.\n\nCombine shorthands to report the default issue types plus circular dependencies:\n\n```sh\nknip --dependencies --exports --files --cycles\n```\n\n## Rules\n\nUse `rules` in the configuration to customize the issue types that count towards\nthe total error count, or to exclude them altogether.\n\n| Value     | Default | Printed | Counted | Description                       |\n| :-------- | :-----: | :-----: | :-----: | :-------------------------------- |\n| `\"error\"` |   ✓ ¹   |    ✓    |    ✓    | Similar to the `--include` filter |\n| `\"warn\"`  |    -    |    ✓    |    -    | Printed in faded/gray color       |\n| `\"off\"`   |    -    |    -    |    -    | Similar to the `--exclude` filter |\n\nExample:\n\n```json title=\"knip.json\"\n{\n  \"rules\": {\n    \"files\": \"warn\",\n    \"duplicates\": \"off\"\n  }\n}\n```\n\nNotes:\n\n- ¹ Exception: the `cycles` issue type is a warning by default.\n- If the `dependencies` issue type is included, the `devDependencies` and\n  `optionalPeerDependencies` types can still be set to `\"warn\"` separately.\n- The rules are modeled after the ESLint `rules` configuration, and could be\n  extended in the future.\n\nAlso see the [issue types overview][4].\n\n## Rules or filters?\n\nFilters are meant to be used as command-line flags, rules allow for more\nfine-grained configuration.\n\n- Rules are more fine-grained since they also have \"warn\".\n- Rules could be extended in the future.\n- Filters can be set in configuration and from CLI (rules only in\n  configuration).\n- Filters have shorthands (rules don't have this).\n\n[1]: ../reference/jsdoc-tsdoc-tags.md\n[2]: ../guides/namespace-imports.md\n[3]: ./reporters.md#cycles\n[4]: ../reference/issue-types.md\n","packages/docs/src/content/docs/features/script-parser.md":"---\ntitle: Script Parser\ndescription: How Knip statically parses shell scripts and CLI arguments in `package.json`, plugins and source code to find entry files and dependencies.\n---\n\nKnip parses shell commands and scripts to find additional dependencies, entry\nfiles and configuration files in various places:\n\n- In [`package.json`][1]\n- In [CLI arguments][2]\n- In [scripts][3]\n- In [source code][4]\n\nShell scripts are parsed and statically analyzed, but they're not executed.\n\n## package.json\n\nThe `main`, `bin`, `exports` and `scripts` fields may contain entry files. Let's\ntake a look at this example:\n\n```json title=\"package.json\"\n{\n  \"name\": \"my-package\",\n  \"main\": \"index.js\",\n  \"exports\": {\n    \"./lib\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./dist/index.cjs\"\n    }\n  },\n  \"bin\": {\n    \"program\": \"bin/cli.js\"\n  },\n  \"scripts\": {\n    \"build\": \"rollup src/entry.ts\",\n    \"start\": \"node --loader tsx server.ts\"\n  }\n}\n```\n\nFrom this example, Knip automatically adds the following files as entry files:\n\n- `index.js`\n- `./dist/index.mjs`\n- `./dist/index.cjs`\n- `bin/cli.js`\n- `src/entry.ts`\n- `server.ts`\n\n### Excluded files\n\nKnip would not add the `exports` if the `dist` folder is matching a pattern in a\nrelevant `.gitignore` file or `ignore` option.\n\nKnip does not add scripts without a standard extension. For instance, the\n`bin/tool` file might be a valid executable for Node.js, but wouldn't be added\nor parsed by Knip.\n\n### CLI Arguments\n\nWhen parsing the `scripts` of `package.json` and other files, Knip detects\nvarious types of inputs. Some examples:\n\n- The first positional argument is usually an entry file\n- Configuration files are often in the `-c` or `--config` argument\n- The `--require`, `--loader` or `--import` arguments are often dependencies\n\n```json\n{\n  \"name\": \"my-lib\",\n  \"scripts\": {\n    \"start\": \"node --import tsx/esm run.ts\",\n    \"bundle\": \"tsup -c tsup.lib.config.ts\",\n    \"type-check\": \"tsc -p tsconfig.app.json\"\n  }\n}\n```\n\nThe `\"start\"` script will have `tsx` marked as a referenced dependency, and adds\n`run.ts` as an entry file.\n\nAdditionally, the following files are detected as configuration files:\n\n- `tsup.lib.config.ts` - to be handled by the tsup plugin\n- `tsconfig.app.json` - to be handled by the TypeScript plugin\n\nSuch executables and their arguments are all defined in plugins separately for\nfine-grained results.\n\n## Scripts\n\nPlugins may also use the script parser to extract entry files and dependencies\nfrom commands. A few examples:\n\n- GitHub Actions: workflow files may contain `run` commands (e.g.\n  `.github/workflows/ci.yml`)\n- Husky & Lefthook: Git hooks such as `.git/hooks/pre-push` contain scripts;\n  also `lefthook.yml` has `run` commands\n- Lint Staged: configuration values are all commands\n- Nx: task executors and `nx:run-commands` executors in `project.json` contains\n  scripts\n- Release It: `hooks` contain commands\n\nPlugins can also return configuration files. Some examples:\n\n- The Angular plugin detects `options.tsConfig` as a TypeScript config file\n- The GitHub Actions plugin parses `run` commands which may contain\n  configuration file paths\n\n## Source Code\n\nWhen Knip is walking the abstract syntax trees (ASTs) of JavaScript and\nTypeScript source code files, it looks for imports and exports. But there's a\nfew more (rather obscure) things that Knip detects in the process. Below are\nexamples of additional scripts Knip parses to find entry files and dependencies.\n\n### bun\n\nIf the `bun` dependency is imported in source code, Knip considers the contents\nof `$` template tags to be scripts:\n\n```ts\nimport { $ } from 'bun';\nawait $`bun boxen I ❤ unicorns`;\nawait $`boxen I ❤ unicorns`;\n```\n\nParsing the script results in the `boxen` binary (the `boxen-cli` dependency) as\nreferenced (twice).\n\n### execa\n\nIf the `execa` dependency is imported in source code, Knip considers the\ncontents of `$` template tags to be scripts:\n\n```ts\nawait $({ stdio: 'inherit' })`c8 node hydrate.js`;\n```\n\nParsing the script results in `hydrate.js` added as an entry file and the `c8`\nbinary/dependency as referenced. The `execa()`, `execaSync()`, `execaCommand()`\nand `execaCommandSync()` call forms are parsed the same way.\n\n### zx\n\nIf the `zx` dependency is imported in source code, Knip considers the contents\nof `$` template tags to be scripts:\n\n```ts\nawait $`node scripts/parse.js`;\n```\n\nThis will add `scripts/parse.js` as an entry file.\n\n### child\\_process\n\nIf `node:child_process` is imported in source code, Knip parses the command in\n`exec`/`execSync` calls and the executable (with its arguments) in\n`spawn`/`spawnSync`/`execFile`/`execFileSync` calls:\n\n```ts\nimport { execSync, execFile } from 'node:child_process';\nexecSync('eslint --cache');\nexecFile('boxen', ['I ❤ unicorns']);\n```\n\nThis marks the `eslint` and `boxen` binaries as referenced. An inline\n`path.join(__dirname, …)` argument to `spawn`, `execFile` or `fork` is added as\nan entry file instead.\n\n### nano-spawn\n\nIf `nano-spawn` is imported in source code, Knip parses the executable and its\narguments:\n\n```ts\nimport spawn from 'nano-spawn';\nawait spawn('gsutil', ['cp', './file.txt', 'gs://bucket/']);\n```\n\nThis marks the `gsutil` binary as referenced.\n\n[1]: #packagejson\n[2]: #cli-arguments\n[3]: #scripts\n[4]: #source-code\n","packages/docs/src/content/docs/features/source-mapping.md":"---\ntitle: Source Mapping\ndescription: How Knip maps build artifacts in `dist`/`outDir` back to their original source files using `tsconfig.json` to avoid false positives.\n---\n\nKnip is mostly interested in source code. Analyzing build artifacts hurts\nperformance and often leads to false positives, as they potentially contain\nbundled code and unresolvable imports.\n\nThat's why Knip tries to map such build artifacts back to their original source\nfiles and analyze those instead. This is done based on `tsconfig.json` settings.\n\n## Example 1: package.json\n\nLet's look at an example case with `package.json` and `tsconfig.json` files, and\nsee how \"dist\" files are mapped to \"src\" files.\n\n```jsonc title=\"package.json\"\n{\n  \"name\": \"my-workspace\",\n  \"main\": \"index.js\",\n  \"exports\": {\n    \".\": \"./src/entry.js\",\n    \"./feat\": \"./lib/feat.js\",\n    \"./public\": \"./dist/app.js\",\n    \"./public/*\": \"./dist/*.js\",\n    \"./public/*.js\": \"./dist/*.js\",\n    \"./dist/internal/*\": null,\n  },\n}\n```\n\nWith this TypeScript configuration:\n\n```json title=\"tsconfig.json\"\n{\n  \"compilerOptions\": {\n    \"baseUrl\": \"src\",\n    \"outDir\": \"dist\"\n  }\n}\n```\n\n- `./src/entry.js` is not in an `outDir` folder, so it's added as an entry file\n- `./lib/feat.js` is not in an `outDir` folder, so it's added as an entry file\n- `./dist/app.js` is in a `dist` folder and mapped to `./src/app.{js,ts}` (¹)\n- `./dist/*.js` is in a `dist` folder and mapped to `./src/**/*.{js,ts}` (¹)\n- `./dist/internal/*` is translated to `./dist/internal/**` and files in this\n  directory and deeper are ignored when globbing entry files\n\n(¹) full extensions list is actually: `js`, `mjs`, `cjs`, `jsx`, `ts`, `tsx`,\n`mts`, `cts`\n\nIn `--debug` mode, look for \"Source mapping\" to see this in action.\n\n:::tip\n\nUsing `./dist/*.js` means that all files matching `./src/**/*.{js,ts}` are added\nas entry files. By default, unused exports of entry files are not reported. Use\n[includeEntryExports][1] to include them.\n\n:::\n\n## Example 2: monorepo\n\nLet's say we have this module in a monorepo that imports `helper` from another\nworkspace in the same monorepo:\n\n```ts title=\"index.js\"\nimport { helper } from '@org/shared';\n```\n\nThe target workspace `@org/shared` has this `package.json`:\n\n```json title=\"package.json\"\n{\n  \"name\": \"@org/shared\",\n  \"main\": \"dist/index.js\"\n}\n```\n\nThe module resolver will resolve `@org/shared` to `dist/index.js`. That file is\nusually compiled and git-ignored, while Knip wants the source file instead.\n\n:::tip\n\nYou may need to compile build artifacts to `outDir` first before Knip can\nsuccessfully apply source mapping for internal references in a monorepo.\n\n:::\n\nIf the target workspace has a `tsconfig.json` file with an `outDir` option, Knip\nwill try to map the \"dist\" file to the \"src\" file. Then if `src/index.ts`\nexists, Knip will use that file instead of `dist/index.js`.\n\nCurrently this only works based on `tsconfig.json`, in the future more source\nmappings may be added.\n\n## Example 3: source conditions\n\nSource-first monorepos may expose source files directly through a custom\ncondition in `package.json#exports` or `#imports` maps:\n\n```json title=\"package.json\"\n{\n  \"name\": \"@org/shared\",\n  \"exports\": {\n    \".\": {\n      \"@org/source\": \"./src/index.ts\",\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    }\n  }\n}\n```\n\nWhen module resolution fails because the targets aren't built, Knip falls back\nto the first conditional target of the workspace package that exists on disk,\nregardless of the condition's name. No build step or configuration required.\n\n[1]: ../reference/configuration.md#includeentryexports\n","packages/docs/src/content/docs/guides/adopt-gradually.md":"---\ntitle: Adopt Knip gradually\ndescription: Roll Knip out on a large or legacy codebase without trying to reach zero on day one. Baseline, focus one issue type at a time, then ratchet with rules.\n---\n\nOn a large or legacy codebase the first run can report a lot. Reaching zero in\none sitting is then the wrong goal. Get a trustworthy signal first, then ratchet\nthe codebase toward clean and keep it there.\n\n## Actionable baseline\n\nMost of the noise on a first run comes from gaps in what Knip can reach: a\ndependency that Knip does not have a plugin for yet, an entry point it can't\nresolve, a phantom dependency. Fix the gaps before you delete anything:\n\n- Address [configuration hints][1].\n- Tune [entry and project files][2] so Knip analyzes the right set of files.\n- Tune configuration for your tools' [plugins][3].\n\nRead the output from the top. One unused file hides its exports and\ndependencies, so files come first.\n\nOnce the report reflects real findings instead of gaps, you have an actionable\nbaseline.\n\n## Focus one issue type at a time\n\nDon't fix everything at once. Narrow the report with [filters][4]:\n\n```sh\nknip --files        # unused files only (the major cascade!)\nknip --dependencies # then dependencies\nknip --exports      # then exports and types\n```\n\nClear one type, commit, move to the next.\n\n## Stage by rules\n\n[Rules][5] set a severity per issue type. Start by setting all types to\n`\"warn\"`, and then the types you've cleaned to `\"error\"`. Warnings are printed\nin gray, and they don't fail the run. Example:\n\n```json title=\"knip.json\"\n{\n  \"rules\": {\n    \"files\": \"error\",\n    \"dependencies\": \"error\",\n    \"exports\": \"warn\",\n    \"duplicates\": \"off\"\n  }\n}\n```\n\nAs each `\"warn\"` type reaches zero, set it to `\"error\"`. Keep iterating and\nprune the codebase to perfection.\n\n## Gate CI without blocking the team\n\nAdd Knip to [CI][6] as soon as you have a baseline, so new clutter is caught in\nreview. A few ways to stage it:\n\n- Mark cleaned types `\"error\"` and the rest `\"warn\"`, so CI fails only on the\n  types you've finished.\n- Workspace by workspace: in a [monorepo][7], scope passes with `--workspace`\n  (accepts multiple workspaces and glob patterns).\n- Production first: [`--production`][8] limits analysis to shipped code, so you\n  can clean what matters most and defer tests and tooling.\n- Set a budget, so CI fails only when the count exceeds the number (e.g. `knip\n--max-issues 50`). This blocks regressions while you burn down the rest.\n- Run report-only with [`--no-exit-code`][9] while you're still triaging.\n\n## Suppress only what's justified\n\nWhen something is genuinely fine as-is, prefer a specific, documented signal\nover a blanket `ignore`, for example:\n\n- tag an export with e.g. [`@lintignore` or `@internal`][10]\n- use [`ignoreExportsUsedInFile`][11] for internal-only exports\n- list known exceptions in [`ignoreDependencies`][12]\n\n[Resolving reported issues][13] covers the right tool for each case.\n\n[1]: ../reference/configuration-hints.md\n[2]: ./configuring-project-files.md\n[3]: ../explanations/plugins.md\n[4]: ../features/rules-and-filters.md#filters\n[5]: ../features/rules-and-filters.md#rules\n[6]: ./using-knip-in-ci.md\n[7]: ../features/monorepos-and-workspaces.md\n[8]: ../features/production-mode.md\n[9]: ../reference/cli.md#--no-exit-code\n[10]: ../reference/jsdoc-tsdoc-tags.md\n[11]: ../reference/configuration.md#ignoreexportsusedinfile\n[12]: ../reference/configuration.md#ignoredependencies\n[13]: ./handling-issues.mdx\n","packages/docs/src/content/docs/guides/configuring-project-files.md":"---\ntitle: Configuring Project Files\ndescription: How to set Knip's `entry` and `project` file patterns, use negations and production mode, and when to reach for `ignore`.\n---\n\nThe `entry` and `project` file patterns are the first and most important\noptions. Getting those right is essential to help you delete more code and make\nKnip faster:\n\n- Start with defaults. Only add targeted `entry` overrides when needed.\n- Use `project` patterns (with negations) to define the scope for Knip.\n- Use production mode to exclude tests and other non-production files.\n- Use `ignore` only to suppress issues in specific files; it does not exclude\n  files from analysis.\n\nLet's dive in and expand on all of these.\n\n## Entry files\n\nAvoid adding too many files as `entry` files:\n\n1. Knip does not report [unused exports][1] in entry files by default.\n2. Proper `entry` and `project` patterns allow Knip to find unused files and\n   exports.\n\n## Unused files\n\nFiles are reported as unused if they are in the set of `project` files, but are\nnot resolved from the `entry` files:\n\n```\nunused files = project files - (entry files + resolved files)\n```\n\nSee [entry files][2] to see where Knip looks for entry files. Fine-tune `entry`\nand adjust `project` to fit your codebase.\n\n:::tip\n\nUse negated `project` patterns to precisely include/exclude files for unused\nfiles detection.\n\nUse `ignore*` to suppress specific issues in matching files; it does not exclude\nfiles from analysis.\n\n:::\n\n## Negated patterns\n\nWhen there are too many files in the analysis, start here.\n\nFor instance, routes are entry files except those prefixed with an underscore:\n\n```json\n{\n  \"entry\": [\"src/routes/*.ts\", \"!src/routes/_*.ts\"]\n}\n```\n\nSome files are not part of your source and are reported as unused (false\npositives)? Use negated `project` patterns:\n\n```json\n{\n  \"entry\": [\"src/index.ts\"],\n  \"project\": [\"src/**/*.ts\", \"!src/exclude/**\"]\n}\n```\n\n❌   Don't use `ignore` for generated artifacts:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts\", \"scripts/*.ts\"],\n  \"ignore\": [\"build/**\", \"dist/**\", \"src/generated.ts\"]\n}\n```\n\n✅   Do define your project boundaries:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts\", \"scripts/*.ts\"],\n  \"project\": [\"src/**\", \"scripts/**\"],\n  \"ignore\": [\"src/generated.ts\"]\n}\n```\n\nWhy this is better:\n\n- `project` defines what belongs to the codebase, so build outputs are excluded\n  from analysis and unused file detection\n- `ignore` is for the few files that should be analyzed but contain exceptions\n- Improves performance by analyzing fewer files\n\n## Ignore issues in specific files\n\nUse `ignore` when a specific analyzed file is not handled properly by Knip or\nintentionally contains unused exports (e.g. generated files exporting\n\"everything\"):\n\n```json\n{\n  \"entry\": [\"src/index.ts\"],\n  \"project\": [\"src/**/*.ts\"],\n  \"ignore\": [\"src/generated.ts\"]\n}\n```\n\nAlso see [ignoreExportsUsedInFile][3] for a more targeted approach.\n\n## Production Mode\n\nDefault mode includes tests and other non-production files in the analysis. To\nfocus on production code, use [production mode][4].\n\nDon't try to exclude tests via `ignore` or negated `project` patterns. That's\ninefficient and ineffective due to entries added by plugins. Use production mode\ninstead.\n\n❌   Don't do this:\n\n```json\n{\n  \"ignore\": [\"**/*.test.js\"]\n}\n```\n\nWhy not: `ignore` hides issues from the report; it does not exclude files from\nanalysis.\n\n❌   Also don't do this:\n\n```json\n{\n  \"entry\": [\"index.ts\", \"!**/*.test.js\"]\n}\n```\n\nWhy not: plugins add test files as `entry` files; you can't and shouldn't\noverride that globally.\n\n❌   Or this:\n\n```json\n{\n  \"project\": [\"**/*.ts\", \"!**/*.spec.ts\"]\n}\n```\n\nWhy not: `project` is for unused file detection; negating test files is\nineffective because they are `entry` files.\n\n✅   Do this instead:\n\n```shell\nknip --production\n```\n\nTo fine-tune the resulting production file set, for instance to exclude test\nhelper files that still show as unused, use the exclamation mark suffix on\nproduction patterns:\n\n```json\n{\n  \"entry\": [\"src/index.ts!\"],\n  \"project\": [\"src/**/*.ts!\", \"!src/test-helpers/**!\"]\n}\n```\n\nRemember to keep adding the exclamation mark `suffix!` for production file\npatterns.\n\n:::tip\n\nUse the exclamation mark (`!`) on both ends (`!`) to exclude files in production\nmode.\n\n:::\n\n## Defaults & Plugins\n\nTo reiterate, the default `entry` and `project` files for each workspace:\n\n```json\n{\n  \"entry\": [\n    \"{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\",\n    \"src/{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\"\n  ],\n  \"project\": [\"**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}!\"]\n}\n```\n\nNext to this, there are other places where [Knip looks for entry files][2].\n\nAdditionally, [plugins have plenty of entry files configured][5] that are\nautomatically added as well.\n\n[1]: ../typescript/unused-exports.md\n[2]: ../explanations/entry-files.md\n[3]: ../reference/configuration.md#ignoreexportsusedinfile\n[4]: ../features/production-mode.md\n[5]: ../explanations/plugins.md#entry-files\n","packages/docs/src/content/docs/guides/contributing.md":"---\ntitle: Contributing to Knip\ndescription: Ways to contribute to Knip, including filing reproductions, opening pull requests, and writing a plugin.\n---\n\nHere are some ways to contribute to Knip:\n\n- Spread the word!\n- [Star the project][1]\n- [File an issue with a reproduction][2]\n- [Pull requests are welcome][3]\n\n[Writing a plugin][4] is a great and fun way to get started.\n\nThe [CONTRIBUTING.md][3] and [DEVELOPMENT.md][5] guides should get you up and\nrunning quickly.\n\nThe main goal of Knip is to keep projects clean & tidy. Everything that\ncontributes to that goal is welcome!\n\n[1]: https://github.com/webpro-nl/knip\n[2]: ./issue-reproduction.md\n[3]: https://github.com/webpro-nl/knip/blob/main/.github/CONTRIBUTING.md\n[4]: ../writing-a-plugin/index.md\n[5]: https://github.com/webpro-nl/knip/blob/main/.github/DEVELOPMENT.md\n","packages/docs/src/content/docs/guides/issue-reproduction.md":"---\ntitle: Issue Reproduction\ndescription: How to create a minimal reproduction for a Knip bug or false positive using CodeSandbox, StackBlitz, a repo, or a test fixture.\n---\n\nIf you encounter an issue or false positives when using Knip, you can [open an\nissue on GitHub][1]. This will help you in your project, and will also improve\nKnip for everyone else!\n\nThink of Knip as a kitchen sink, it handles a large amount of projects and\nconfigurations, and your project is different from all others. Many factors may\ninfluence the issue at hand, such as:\n\n- Code syntax, import and export structure in source files\n- Dependencies, scripts and entry files in `package.json`\n- TypeScript configuration in `tsconfig.json`\n- Enabled plugins and related configuration files\n- Dependent or depending workspaces in a monorepo\n- Knip configuration in `knip.json`\n\n## Keep it minimal\n\nCreate the minimum of source code and configuration with a few files to\nreproduce and demonstrate the issue. Having this as a basis has many benefits:\n\n- Minimize barriers and unrelated contextual overhead\n- Optimize shared understanding of the situation\n- Serves as a \"contract\" to fix the actual issue\n- Files serve as a fixture to the project\n\nProviding this with an issue description will help us help you and improve the\nchances the issue can be looked into efficiently and in a timely manner.\n\nUseful **complements** to a minimal reproduction might include:\n\n- Screenshots, videos, code snippets or log output\n- Links to an existing project repository\n- Applications scaffolded by tools like Angular or Svelte CLI\n\n## Before opening an issue\n\nBefore opening an issue, please make sure you:\n\n- are using the latest version\n- have read the relevant documentation\n- have searched [existing issues][1]\n- have checked the list of [known issues][2]\n\nPlease file only a single issue at a time, so each of them can be labeled and\ntracked separately.\n\nThere is no need to open an issue if you're going to submit a pull request to\nclose it right away anyway. In that case it's preferred to keep things central\nin either an issue or pull request.\n\n## Templates\n\nA convenient way to create a minimal reproduction is by starting with one of\nthese templates in CodeSandbox or StackBlitz:\n\n| Template |                  |                 |\n| :------- | ---------------- | --------------- |\n| Basic    | [CodeSandbox][3] | [StackBlitz][4] |\n| Monorepo | [CodeSandbox][5] | [StackBlitz][6] |\n\nShoutout to [CodeSandbox][7] and [StackBlitz][8] for generously providing these\nfree dev containers!\n\n## Alternatives\n\nOther solutions to share a minimal and reproducible case may work well too,\nincluding:\n\n- A public repository on e.g. GitHub or GitLab.\n- A pull request with a new [test][9] and/or [fixture folder][10].\n\nThe goal is to have an easy and common understanding and reproduction. If you're\nunable to create a reproduction using one of the methods described then please\nclearly explain this in the issue or [contact me][11].\n\n## Pull Request\n\nThe optimal way is to add fixtures and failing tests to the Knip repository, and\nopen a pull request to discuss the issue! Also see [instructions for\ndevelopment][12].\n\n[1]: https://github.com/webpro-nl/knip/issues?q=is%3Aissue\n[2]: https://knip.dev/reference/known-issues\n[3]: https://codesandbox.io/p/devbox/github/webpro-nl/knip/main/templates/issue-reproduction/basic\n[4]: https://stackblitz.com/github/webpro-nl/knip/tree/main/templates/issue-reproduction/basic\n[5]: https://codesandbox.io/p/devbox/github/webpro-nl/knip/main/templates/issue-reproduction/monorepo\n[6]: https://stackblitz.com/github/webpro-nl/knip/tree/main/templates/issue-reproduction/monorepo\n[7]: https://codesandbox.io\n[8]: https://stackblitz.com\n[9]: https://github.com/webpro-nl/knip/blob/main/.github/DEVELOPMENT.md#tests\n[10]: https://github.com/webpro-nl/knip/tree/main/packages/knip/fixtures\n[11]: https://github.com/webpro\n[12]: https://github.com/webpro-nl/knip/blob/main/.github/DEVELOPMENT.md\n","packages/docs/src/content/docs/guides/namespace-imports.md":"---\ntitle: Namespace Imports\ndescription: How Knip handles exports used through `import * as NS` namespace imports, its usage heuristic, and the `nsExports` and `nsTypes` issue types.\n---\n\nThe intention of exports used through namespace imports may not always be clear\nto Knip. Here's a guide to better understand how Knip handles such exports.\n\n## Example\n\nWe start off by having two exports:\n\n```ts title=\"my-namespace.js\"\nexport const version = 'v5';\nexport const getRocket = () => '🚀';\n```\n\nThe next snippet shows how to import all the exports above on a namespace. All\nexports of the `my-namespace.js` module will be members on the `NS` object:\n\n```ts title=\"my-module.ts\"\nimport * as NS from './my-namespace.js';\nimport send from 'stats';\nsend(NS);\n```\n\nThe intention of export usage is not always clear. In the example above is\n`version` or `getRocket` used? We're not sure, but we _probably_ don't want them\nto be reported as unused. The same goes for the next example:\n\n```ts title=\"my-module.ts\"\nimport * as NS from './my-namespace.js';\n\nexport { NS };\n```\n\nIf this is all usage of the `NS` namespace object, we also don't know whether\nindividual exports like `version` or `getRocket` will be used. However, if at\nleast one reference to a property such as `NS.version` is found, then the\nindividual exports are considered separately again and `getRocket` will be\nmarked as unused:\n\n```ts title=\"index.ts\"\nimport { NS } from './my-module.js';\n\nconst version = NS.version;\n```\n\n## The default heuristic\n\nKnip uses the following heuristic to determine which of the individual exports\nare used:\n\n- If there's one or more references to the import namespace object, but without\n  any property access, all exports on that namespace are considered used.\n- Otherwise, exports are considered separately.\n\nBelow are a few more examples, and a way to disable this default behavior.\n\n## Examples\n\nLet's take a look at more examples:\n\n```ts title=\"my-namespace.ts\"\nexport const start = 1;\n\nexport const end = 1;\n```\n\nIn the following cases all exports of `my-namespace.ts` are considered used:\n\n```ts title=\"index.ts\"\nimport * as NS from './my-namespace.js';\nimport send from 'stats';\n\nsend(NS);\n\nconst spread = { ...NS };\n\nconst shorthand = { NS };\n\nconst assignment = NS;\n\nconst item = [NS];\n\ntype TypeOf = typeof NS;\n\nObject.values(NS);\n\nfor (const fruit in NS) {\n  //\n}\n\nexport { NS };\n\nexport { NS as AliasedNS };\n\nexport = NS;\n```\n\nHowever, this is no longer the case when one of the properties is accessed:\n\n```ts title=\"index.js\"\nimport * as NS from './namespace.js';\n\nconst begin = NS.start;\n\nsend(NS);\n```\n\nIn this case, the `end` export will be reported as unused, even though the `NS`\nobject itself is referenced on its own as well.\n\n## Include `nsExports` and `nsTypes`\n\nTo disable the heuristic as explained above, and enforce Knip to consider each\nexport on a namespace individually, include the `nsExports` issue type:\n\n```json\n{\n  \"include\": [\"nsExports\"]\n}\n```\n\nOr use the `--include nsExports` argument from the CLI. The `nsTypes` can be\nadded as well to do the same for exported types.\n\nIncluding these _adds_ them to the report; all other issue types are still\nreported.\n","packages/docs/src/content/docs/guides/performance.md":"---\ntitle: Performance\ndescription: How to profile and speed up Knip using the `--cache`, `--performance`, and `--debug` flags, file patterns, and per-workspace linting.\n---\n\nThis page describes a few topics around Knip's performance, and how you might\nimprove it.\n\nKnip does not want to tell you how to structure files or how to write your code,\nbut it might still be good to understand inefficient patterns for Knip.\n\nUse the `--debug` and `--performance` flags to find potential bottlenecks.\n\n## Cache\n\nUse `--cache` to speed up consecutive runs.\n\n## Ignoring files\n\nFiles matching the `ignore` patterns are not excluded from the analysis. They're\njust not printed in the report. Use negated `entry` and `project` patterns to\nexclude files from the analysis.\n\nRead [configuring project files][1] for details and examples. Improving\nconfiguration may have a significant impact on performance.\n\n## Metrics\n\nUse [the `--performance` flag][2] to see how many times potentially expensive\nfunctions (e.g. `findReferences`) are invoked and how much time is spent in\nthose functions. Example usage:\n\n```sh\nknip --performance\n```\n\n## ignoreExportsUsedInFile\n\nThe [ignoreExportsUsedInFile][3] option slows down the process slightly.\nTypically, anywhere between 0.25% and 10% of total running time. To find out:\n\n```sh\nknip --performance-fn hasRefsInFile\n```\n\n## A last resort\n\nIn case Knip is unbearably slow (or even crashes), you could resort to [lint\nindividual workspaces][4].\n\n[1]: ./configuring-project-files.md\n[2]: ../reference/cli.md#--performance\n[3]: ../reference/configuration.md#ignoreexportsusedinfile\n[4]: ../features/monorepos-and-workspaces.md#filter-workspaces\n","packages/docs/src/content/docs/guides/troubleshooting.md":"---\ntitle: Troubleshooting\ndescription: Troubleshoot Knip lint issues and exceptions using exit codes, `--debug`, and `--trace` to see where exports and dependencies are used.\n---\n\nWe can distinguish two types of issues:\n\n- [Lint issues reported by Knip][1]\n- [Exceptions thrown by Knip][2]\n\nAlso see the [debug][3] and [trace][4] options below that can help to\ntroubleshoot issues.\n\n:::note[Rationale]\n\nThe JavaScript/TypeScript ecosystem has a vast amount of frameworks and tools.\nAdditionally, file locations, configuration semantics, command-line arguments\nand so on vary wildly. Files and dependencies are referenced in many ways. Knip\ntries harder than you think to cover it all.\n\nKnip is intentionally strict to maximize its potential. It may initially report\nmany unused files. However, getting this right will result in great reports and\ntidy codebases.\n\nIf it doesn't work out at first, a small change can go a long way.\n\n:::\n\n## Lint issues reported by Knip\n\nKnip reports lint issues in your codebase. See [handling issues][5] to deal with\nthe reported issues.\n\nIf you're considering filing an issue, please read [issue reproduction][6]\nfirst.\n\nExit code 1 indicates a successful run, but lint issues were found.\n\n## Exceptions thrown by Knip\n\nKnip may throw an exception, resulting in an unsuccessful run.\n\nSee [known issues][7] as it may be listed there and a workaround may be\navailable. If it isn't clear what's throwing the exception, try another run with\n`--debug` to locate the cause of the issue with more details.\n\nIf you're considering filing an issue, please read [issue reproduction][6]\nfirst.\n\nExit code 2 indicates an exception was thrown by Knip.\n\n## Debug\n\nTo better understand why Knip reports what it does, run it in debug mode by\nadding `--debug` to the command:\n\n```sh\nknip --debug\n```\n\nThis will give a lengthy output, including:\n\n- Included workspaces\n- Used configuration per workspace\n- Enabled plugins per workspace\n- Glob patterns and options followed by matching file paths\n- Plugin config file paths and found dependencies per plugin\n- Compiled non-standard source files\n\n## Trace\n\nUse `--trace` to see where exports or dependencies are used:\n\n- Use `--trace-file [path]` to output this only for the given file.\n- Use `--trace-export [name]` to output this only for the given export name.\n- Use `--trace-dependency [name]` to find where a dependency is imported\n- Use both to trace a specific named or default export of a certain file.\n\nThis works across re-exports, barrel files and workspaces. Here's an example\nscreenshot:\n\n<img src=\"/screenshots/trace-export.png\" alt=\"trace export\" class=\"mw500\" />\n\nIt's like a reversed module graph. Instead of traversing imports it goes in the\nopposite direction and shows where exports are imported.\n\nThe `--trace-dependency` accepts strings for exact matches, but if it looks like\na regex that works too:\n\n<img src=\"/screenshots/trace-dependency.png\" alt=\"trace dependency\" class=\"mw500\" />\n\nUse [--workspace \\[filter\\]][8] to filter accordingly.\n\n#### Legend\n\n| Marker | Description                         |\n| ------ | :---------------------------------- |\n| `✓`    | Referenced (not reported as unused) |\n| `✗`    | Reported as unused                  |\n| `⎆`    | Entry file                          |\n\nEach child node is prefixed with how the export is consumed: `import`,\n`importAs` (shown as `original → alias`), `importNS`, or a re-export\n(`reExport`, `reExportAs`, `reExportNS`, `reExportStar`). A `refs:` line lists\nthe references found in that file; a `members:` line shows per-member status for\nnamespaces and enums. An `[ambiguous]` line lists the competing definitions when\na name reaches the file through more than one `export *`. A name that reaches\nthe file only through `export *` is traced from its definition.\n\n## Opening an issue\n\nIf you want to open an issue, please see [issue reproduction][6].\n\n## Understanding Knip\n\nLooking to better understand how Knip works? The [entry files][9] and\n[plugins][10] explanations cover two core concepts. After this you might want to\ncheck out features like [production mode][11] and [monorepos & workspaces][12].\n\nIn a more general sense, [Why use Knip?][13] explains what Knip can do for you.\n\n## Asking for help\n\nIf you can't find your answer in any of the aforementioned resources, feel free\nto [open an issue on GitHub][14].\n\n[1]: #lint-issues-reported-by-knip\n[2]: #exceptions-thrown-by-knip\n[3]: #debug\n[4]: #trace\n[5]: ../guides/handling-issues.mdx\n[6]: ./issue-reproduction.md\n[7]: ../reference/known-issues.md\n[8]: ../reference/cli.md#--workspace-filter\n[9]: ../explanations/entry-files.md\n[10]: ../explanations/plugins.md\n[11]: ../features/production-mode.md\n[12]: ../features/monorepos-and-workspaces.md\n[13]: ../explanations/why-use-knip.md\n[14]: https://github.com/webpro-nl/knip/issues\n","packages/docs/src/content/docs/guides/using-knip-in-ci.md":"---\ntitle: Using Knip in CI\ndescription: Run Knip in continuous integration to catch regressions, with a GitHub Actions workflow example, exit codes, caching, and reporters.\n---\n\nKnip is your companion during local development. But it is even more valuable in\na continuous integration (CI) environment to prevent regressions over time. Knip\nwill notify you of unused dependencies, exports and files if you forgot to\nremove them.\n\nKnip will exit the process with code `1` if there are one or more issues.\n\n## GitHub Actions\n\nHere's an example workflow configuration for GitHub Actions:\n\n```yaml\nname: Lint project\n\non: push\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    name: Ubuntu/Node v24\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions/setup-node@v6\n        with:\n          node-version: 24\n      - name: Install dependencies\n        run: npm install --ignore-scripts\n      - name: Run knip\n        run: npm run knip\n```\n\n## Notes\n\n- Use [--cache][1] to speed up consecutive runs (default location:\n  `./node_modules/.cache/knip`).\n- See [Reporters][2] including the GitHub Actions reporter.\n- Consider running Knip twice: a default run and a [production mode][3] run.\n- See [CLI arguments → Output][4] for some relevant options such as\n  `--treat-config-hints-as-errors` and `--no-exit-code`.\n- In CI environments, the [--no-progress][5] flag is set automatically.\n\n[1]: ../reference/cli.md#--cache\n[2]: ../features/reporters.md\n[3]: ../features/production-mode.md\n[4]: ../reference/cli.md#output\n[5]: ../reference/cli.md#--no-progress\n","packages/docs/src/content/docs/guides/working-with-commonjs.md":"---\ntitle: Working with CommonJS\ndescription: Conventions for `module.exports` and `require()` so Knip detects CommonJS named and default exports correctly and avoids false positives.\n---\n\nCommonJS is the JavaScript module system using `require()` and `module.exports`\nstatements.\n\nKnip works well with CommonJS. You don't need to use ES Modules or a\n`tsconfig.json` to use Knip.\n\nThe dynamic nature of CommonJS leaves room for ambiguity: it's sometimes unclear\nwhether an export is a default or a named export (and thus how it should be\nimported). So we'll have to agree on a few conventions to prevent false\npositives. Those conventions are designed to minimize impact on existing\ncodebases, improve consistency, and ease migration to ES Modules or TypeScript.\n\nFor **named exports**, the recommendation is to assign keys to `module.exports`:\n\n```js\nconst B = function () {};\n\nmodule.exports.A = { option: true };\nmodule.exports.B = B;\n```\n\nAlternatively, assign an object with ONLY shorthand property assignments to\n`module.exports`:\n\n```js\nconst A = function () {};\nconst B = { option: true };\n\nmodule.exports = { A, B };\n```\n\nAnything else assigned to `module.exports` is considered a default export, and\nshould be imported as such.\n\nThe following **default import** of the **named exports** above will result in\nall those exports reported as unused, even when referenced like below:\n\n```js\nconst DefaultImport = require('./common.js');\nconst runtime = [DefaultImport.A, DefaultImport.B];\n```\n\nInstead, do this:\n\n```js\nconst { A, B } = require('./common.js');\nconst runtime = [A, B];\n```\n\nNot recommended per se, but the following import syntax also results in the\nnamed export `A` being used:\n\n```js\nconst runtime = [require('./common.js').A];\n```\n\nAdd a non-shorthand property to turn the named object notation into a single\n**default export**:\n\n```js\nconst A = function () {};\nconst B = { option: true };\n\nmodule.exports = { __esModule: true, A, B };\n```\n\nThe `__esModule` key could be named differently (but makes sense given it's an\ninformal \"CJS/ESM interop\" standard amongst compilers and bundlers).\n","packages/docs/src/content/docs/overview/configuration.md":"---\ntitle: Configuration\ndescription: config\n---\n\n## Defaults\n\nKnip has good defaults and aims for \"zero config\". Here's a simplified version\nof the default `entry` and `project` values:\n\n```json\n{\n  \"entry\": [\"index.{js,ts}\", \"src/index.{js,ts}\"],\n  \"project\": [\"**/*.{js,ts}\"]\n}\n```\n\nEntry files are the starting point for Knip to find more source files and\nexternal dependencies.\n\n## Location\n\nBy default, Knip will look for a configuration file with the following names:\n\n- `knip.json`\n- `knip.jsonc`\n- `.knip.json`\n- `.knip.jsonc`\n- `knip.ts`\n- `knip.js`\n- `knip.config.ts`\n- `knip.config.js`\n- `package.json` (in the `\"knip\"` property)\n\nIf you want to use a custom file name or path, use the `--config` flag:\n\n```sh\nknip --config path/to/knip.json\n```\n\n## Customize\n\nYour project structure may not match the default `entry` and `project` files.\nHere's an example custom configuration to include `.js` files in the `scripts`\nfolder:\n\n```json title=\"knip.json\"\n{\n  \"$schema\": \"https://unpkg.com/knip@6/schema.json\",\n  \"entry\": [\"src/index.ts\", \"scripts/{build,create}.js\"],\n  \"project\": [\"src/**/*.ts\", \"scripts/**/*.js\"]\n}\n```\n\nThe set of `project` files determines the analysis scope. Use negated `project`\npatterns to exclude files from the analysis. See [configuring project files][1]\nfor details.\n\nThe values you set override the default values, they are not merged.\n\n:::tip\n\nBe specific with `entry` files. Minimize the number of entry files and wildcards\nfor better results.\n\nPlugins are enabled automatically, and their entry files are added\nautomatically. Such as for Next.js, Astro, Remix, Vitest, Playwright and many\nmore.\n\n:::\n\nKnip looks for entry files in many places. Learn more in the next page about\n[entry files][2].\n\n## Configuration Options\n\nSee [configuration file options][3].\n\nUse JavaScript or TypeScript in a [dynamic configuration file][4].\n\n## What's next?\n\nThe best way to understand Knip and what it can do for you is to read the pages\nin the \"Understanding Knip\" sections, starting with [entry files][2].\n\nWant to learn more about some of the main features?\n\n- Working with [monorepos & workspaces][5].\n- Learn more about [production mode][6].\n\nHaving trouble configuring Knip?\n\n- [Configuring project files][1]\n- [Troubleshooting][7]\n\nSearch this website using the bar at the top (`Ctrl+K` or `⌘+K`).\n\n[1]: ../guides/configuring-project-files.md\n[2]: ../explanations/entry-files.md\n[3]: ../reference/configuration.md\n[4]: ../reference/dynamic-configuration.mdx\n[5]: ../features/monorepos-and-workspaces.md\n[6]: ../features/production-mode.md\n[7]: ../guides/troubleshooting.md\n","packages/docs/src/content/docs/overview/features.md":"---\ntitle: Features\ndescription: Table of Knip capabilities including auto-fix, cache, compilers, monorepos, plugins, reporters, production mode, trace and watch mode.\n---\n\nOverview of capabilities in support of the core feature: find many [types of\nissues][1].\n\nAlso see [related tooling][2].\n\n## Overview\n\n| Name                         | Description or example                                                |\n| :--------------------------- | :-------------------------------------------------------------------- |\n| [Auto-fix][3]                | Use `--fix` to auto-fix issues                                        |\n| [Cache][4]                   | Use `--cache` to speed up consecutive runs                            |\n| [Catalog][5]                 | Report & fix unused catalog entries                                   |\n| [CommonJS][6]                | CommonJS is still widely used & supported, but conditions apply       |\n| [Compilers][7]               | Support for Astro, MDX, Svelte, Vue and custom compilers              |\n| Configuration hints          | Display configuration hints to keep `knip.json` tidy                  |\n| [Debug][8]                   | Use `--debug` for troubleshooting                                     |\n| [Filters][9]                 | Exclude or focus on specific issue types                              |\n| [Format][10]                 | Use `--format` with `--fix` to auto-format modified files             |\n| [JSDoc tags][11]             | Tag and exclude specific exports from the report                      |\n| [Memory usage][12]           | Use `--memory` for detailed memory usage insights                     |\n| [Monorepos][13]              | Workspaces are first-class citizen                                    |\n| [Performance][14]            | Use `--performance` for detailed timing insights                      |\n| [Plugins][15]                | Over 100 plugins with custom entry paths and config parsing           |\n| [Plugins: inputs][16]        | Inputs are an affective mechanism to add entries, dependencies & more |\n| [Plugins: CLI arguments][17] | Tool-specific CLI argument parsing make plugins go the extra mile     |\n| [Preprocessors][18]          | Preprocess issues before being reported                               |\n| [Production mode][19]        | Use `--production` to lint only production code                       |\n| [Reporters][20]              | Choose from many built-in reporters or use your own                   |\n| [Rules][21]                  | Exclude or focus on specific issue types                              |\n| [Script parser][22]          | Shell scripts and `package.json` contain entry paths and dependencies |\n| [Source mapping][23]         | Map `dist` files back to `src` files                                  |\n| [Strict mode][24]            | Use `--strict` to tighten and lint only production `dependencies`     |\n| [Trace][25]                  | Trace exports to find where they are used                             |\n| [Watch mode][26]             | Use `--watch` for live updates of unused files and exports            |\n| [Workspace][27]              | Use `--workspace` to filter workspaces in a monorepo                  |\n\n[1]: ../reference/issue-types.md\n[2]: ../reference/related-tooling.md\n[3]: ../features/auto-fix.mdx\n[4]: ../reference/cli.md#--cache\n[5]: ../features/catalogs.md\n[6]: ../guides/working-with-commonjs.md\n[7]: ../features/compilers.md\n[8]: ../guides/troubleshooting.md#debug\n[9]: ../features/rules-and-filters.md#filters\n[10]: ../features/auto-fix.mdx#format\n[11]: ../reference/jsdoc-tsdoc-tags.md\n[12]: ../reference/cli.md#--memory\n[13]: ../features/monorepos-and-workspaces.md\n[14]: ../reference/cli.md#--performance\n[15]: ../explanations/plugins.md\n[16]: ../writing-a-plugin/inputs.md\n[17]: ../writing-a-plugin/argument-parsing.md\n[18]: ../features/reporters.md#preprocessors\n[19]: ../features/production-mode.md\n[20]: ../features/reporters.md\n[21]: ../features/rules-and-filters.md#rules\n[22]: ../features/script-parser.md\n[23]: ../features/source-mapping.md\n[24]: ../features/production-mode.md#strict-mode\n[25]: ../guides/troubleshooting.md#trace\n[26]: ../reference/cli.md#--watch\n[27]: ../features/monorepos-and-workspaces.md#filter-workspaces\n","packages/docs/src/content/docs/overview/screenshots-videos.md":"---\ntitle: Screenshots & videos\ndescription: Screenshots and videos showing Knip watch mode, auto-fix, export and file trace, and performance output in action.\n---\n\n## Watch & auto-fix\n\nThis video demonstrates using the `--watch` and `--fix` options inside Visual\nStudio Code:\n\n<video controls width=\"500\">\n  <source src=\"/screenshots/watch-fix.mp4\" type=\"video/mp4\" />\n\n  <source src=\"/screenshots/watch-fix.webm\" type=\"video/webm\" />\n</video>\n\nThis works in any terminal. See [--watch][1] and [auto-fix][2] for more details.\n\n## Trace\n\nHere's an example screenshot that traces the `mapIterator` export in the\nTypeScript codebase:\n\n<img src=\"/screenshots/trace-export.png\" alt=\"trace export\" class=\"mw500\" />\n\nInspect complicated import and re-export chains at a glance:\n\n<img src=\"/screenshots/trace-file.png\" alt=\"trace file\" class=\"mw500\" />\n\nSee [Trace][3] for more details.\n\n## Performance\n\nAn example screenshot showing `--performance` output for the Knip codebase:\n\n<img src=\"/screenshots/performance.png\" alt=\"performance\" class=\"mw500\" />\n\nAlso see [--performance][4].\n\n[1]: ../reference/cli.md#--watch\n[2]: ../features/auto-fix.mdx\n[3]: ../guides/troubleshooting.md#trace\n[4]: ../reference/cli.md#--performance\n","packages/docs/src/content/docs/reference/cli.md":"---\ntitle: CLI Arguments\ndescription: Every Knip command-line flag, grouped by mode, scope, fix, output and troubleshooting, with shortcuts and exit codes.\n---\n\n## General\n\n### `--help`\n\nShortcut: `-h`\n\nPrints a summary of this page.\n\n### `--version`\n\nShortcut: `-V`\n\nPrint the version number.\n\n### `--no-progress`\n\nShortcut: `-n`\n\nDon't show dynamic progress updates. Progress is automatically disabled in CI\nenvironments.\n\n### `--config [file]`\n\nUse an alternative path for the configuration file. Default locations:\n\n- `knip.json`\n- `knip.jsonc`\n- `.knip.json`\n- `.knip.jsonc`\n- `knip.ts`\n- `knip.js`\n- `knip.config.ts`\n- `knip.config.js`\n- `package.json#knip`\n\nShortcut: `-c`\n\n### `--use-tsconfig-files`\n\nPer workspace, take project files from `tsconfig.json` (`files` + `include`,\nminus `exclude`, `node_modules` and `outDir`) and from the tsconfig files in its\n`references` instead of the `project` patterns. Workspaces without a\n`tsconfig.json` fall back to their `project` patterns.\n\nImplicitly enabled in the [editor extension, MCP server and language server][1]\nwhen there is no Knip configuration file.\n\n### `--tsConfig [file]`\n\nShortcut: `-t`\n\nUse an alternative path for the TypeScript configuration file.\n\nUsing `-t jsconfig.json` is also supported.\n\nDefault location: `tsconfig.json`\n\n### `knip-bun`\n\nRun Knip using the Bun runtime (instead of Node.js + jiti).\n\n```shell\nknip-bun\n```\n\nThis is equal to `bunx --bun knip`\n\nRequires [Bun][2] to be installed. Also see [known issues][3] for the type of\nissues this might help with.\n\n### NO\\_COLOR\n\nThe built-in reporters use the [NO\\_COLOR][4] friendly [picocolors][5]:\n\n```sh\nNO_COLOR=1 knip\n```\n\n### KNIP\\_DISABLE\\_RAW\\_TRANSFER\n\nSet `KNIP_DISABLE_RAW_TRANSFER=1` to disable oxc-parser raw transfer and use the\nnormal parser path.\n\n## Mode\n\n### `--cache`\n\nEnable caching.\n\nConsecutive runs are 10-40% faster as the results of file analysis (AST\ntraversal) are cached. Conservative. Cache strategy based on file meta data\n(modification time + file size).\n\nSee [stale cache results][6] for limitations and workarounds.\n\n### `--cache-location`\n\nProvide alternative cache location.\n\nDefault location: `./node_modules/.cache/knip`\n\n### `--include-entry-exports`\n\nWhen a repository is self-contained or private, you may want to include entry\nfiles when reporting unused exports:\n\n```sh\nknip --include-entry-exports\n```\n\nAlso see [includeEntryExports][7].\n\n### `--no-gitignore`\n\nIgnore `.gitignore` files.\n\n### `--production`\n\nShortcut: `-p`\n\nLint only production source files. This excludes:\n\n- entry files defined by plugins:\n  - test files\n  - configuration files\n  - Storybook stories\n- `devDependencies` from `package.json`\n\nRead more at [Production Mode][8].\n\n### `--strict`\n\nShortcut: `-s`\n\nIsolate workspaces and consider only direct dependencies. Implies [production\nmode][9].\n\nRead more at [Production Mode][8].\n\n### `--watch`\n\nShortcut: `-w`\n\nWatch current directory, and update reported issues when a file is modified,\nadded or deleted.\n\nWatch mode focuses on imports and exports in source files. During watch mode,\nchanges in `package.json` or `node_modules` may not cause an updated report.\n\n## Scope\n\n### `--workspace [filter]`\n\nSelect one or multiple workspaces (including its ancestor, dependency and\ndependent workspaces). The default behavior is to lint all configured\nworkspaces.\n\nShortcut: `-W`\n\nSee [filter workspaces][10] for more details and examples.\n\n### `--directory [dir]`\n\nShortcut: `-D`\n\nDefault: `cwd` (current directory)\n\nRun the process from a different directory.\n\n### `--exclude`\n\nExclude provided issue types from report. Can be comma-separated or repeated.\n\nExample:\n\n```sh\nknip --exclude enumMembers\n```\n\n### `--include`\n\nReport only provided issue types. Can be comma-separated or repeated.\n\nExample:\n\n```sh\nknip --include files,dependencies\nknip --include files --include dependencies\n```\n\n`nsExports` and `nsTypes` are [off by default][11]; including only those _adds_\nthem to the default report instead of narrowing it.\n\nAvailable [issue types][12] when filtering output using `--include` or\n`--exclude`:\n\n- `files`\n- `dependencies`\n- `unlisted`\n- `binaries`\n- `unresolved`\n- `exports`\n- `nsExports`\n- `types`\n- `nsTypes`\n- `enumMembers`\n- `namespaceMembers`\n- `duplicates`\n- `catalog`\n- `catalogReferences`\n\n### `--dependencies`\n\nShortcut to report only all types of dependency issues:\n\n```sh\n--include dependencies,unlisted,binaries,unresolved,catalog,catalogReferences\n```\n\n### `--exports`\n\nShortcut to report only all types of export issues:\n\n```sh\n--include exports,nsExports,types,nsTypes,enumMembers,namespaceMembers,duplicates\n```\n\n### `--files`\n\nShortcut to report only file issues:\n\n```sh\n--include files\n```\n\n### `--cycles`\n\nShortcut to report only circular dependencies:\n\n```sh\n--include cycles\n```\n\nAlso see the [cycles reporter][13].\n\n### `--tags`\n\nExports can be tagged with known or arbitrary JSDoc/TSDoc tags:\n\n```ts\n/**\n * Description of my exported value\n *\n * @type number\n * @internal Important matters\n * @lintignore\n */\nexport const myExport = 1;\n```\n\nAnd then include (`+`) or exclude (`-`) these tagged exports from the report\nlike so:\n\n```shell\nknip --tags=-lintignore,-internal\nknip --tags=+custom\n```\n\nThis way, you can either focus on or ignore specific tagged exports with tags\nyou define yourself. This also works for individual enum and namespace members.\n\nThe default directive is `+` (include) and the `@` prefix is ignored, so the\nnotation below is valid and will report only exports tagged `@lintignore` or\n`@internal`:\n\n```shell\nknip --tags @lintignore --tags @internal\n```\n\n## Fix\n\n### `--fix`\n\nShortcut: `-f`\n\nRead more at [auto-fix][14].\n\n### `--fix-type`\n\nFix only issues of type, can be comma-separated or repeated.\n\nMore info about fixable types at [issue types][12]\n\n### `--allow-remove-files`\n\nAllow Knip to remove files (with `--fix`).\n\n### `--format`\n\nShortcut: `-F`\n\nFormat modified files after `--fix` using the local formatter.\n\n## Output\n\n### `--preprocessor [preprocessor]`\n\nPreprocess the results before providing it to the [reporter(s)][15].\n\nCan be repeated. Examples:\n\n```sh\nknip --preprocessor ./my-preprocessor.ts\n```\n\n```sh\nknip --preprocessor preprocessor-package\n```\n\nPreprocessors can also be configured in the Knip configuration file.\n\nAlso see [Reporters & Preprocessors][16].\n\n### `--preprocessor-options [json]`\n\nPass extra options to the preprocessor as JSON string.\n\n```sh\nknip --preprocessor ./preproc.ts --preprocessor-options '{\"key\":\"value\"}'\n```\n\n### `--reporter [reporter]`\n\nAvailable reporters:\n\n- `symbols` (default)\n- `compact`\n- `codeowners`\n- `json`\n- `codeclimate`\n- `markdown`\n- `disclosure`\n- `github-actions`\n- `sarif`\n\nCan be repeated. Example:\n\n```sh\nknip --reporter compact\n```\n\nAlso see [Reporters & Preprocessors][16].\n\n### `--reporter-options [json]`\n\nPass extra options to the reporter (as JSON string):\n\nExample:\n\n```sh\nknip --reporter codeowners --reporter-options '{\"path\":\".github/CODEOWNERS\"}'\n```\n\n### `--no-config-hints`\n\nSuppress configuration hints.\n\n### `--no-tag-hints`\n\nSuppress tag hints.\n\n### `--treat-config-hints-as-errors`\n\nExit with non-zero exit code (`1`) if there are any configuration hints.\n\n### `--treat-tag-hints-as-errors`\n\nExit with non-zero exit code (`1`) if there are any tag hints.\n\n### `--max-issues`\n\nMaximum number of issues before non-zero exit code. Default: `0`\n\n### `--max-show-issues`\n\nMaximum number of issues per type to display (does not affect exit code).\n\n### `--no-exit-code`\n\nExit with code zero (`0`) even when there are lint issues. Config load failures\nand internal errors still exit with code `2`.\n\nThe default exit codes:\n\n| Code | Description                                                                                     |\n| :--: | :---------------------------------------------------------------------------------------------- |\n| `0`  | Knip ran successfully, no lint issues                                                           |\n| `1`  | Knip ran successfully, but there is at least one lint issue                                     |\n| `2`  | Knip did not run successfully due to bad input, a plugin config load error or an internal error |\n\n## Troubleshooting\n\n### `--debug`\n\nShortcut: `-d`\n\nShow [debug output][17].\n\n### `--memory`\n\n```txt frame=terminal\nknip --memory\n\n(results)\n\n # heapUsed  heapTotal  freemem\n-- --------  ---------  -------\n 0    42.09      70.91  2251.00\n 1   927.04    1042.58  1166.47\n 2   973.29    1047.33  1160.92\n 3   971.54    1079.83  1121.66\n 4   997.80    1080.33  1120.34\n 5  1001.88    1098.08  1100.72\n 6  1038.69    1116.58  1100.72\n 7  1082.12    1166.33  1100.72\n 8  1145.46    1224.50  1100.72\n 9  1115.82    1240.25  1100.72\n10  1182.35    1249.75   973.05\n11   637.32    1029.17   943.63\n12   674.30    1029.33   943.39\n13   682.24    1029.33   941.63\n14   707.70    1029.33   937.48\n\nTotal running time: 4.3s\n```\n\n### `--memory-realtime`\n\nUse this if Knip crashes to still see memory usage info over time:\n\n```txt frame=terminal\nknip --memory-realtime\n\n#  heapUsed  heapTotal  freemem\n-  --------  ---------  -------\n0     42.09      70.91  2251.00\n1    927.04    1042.58  1166.47\n...mem info keeps being logged...\n\n(results)\n```\n\n### `--performance`\n\nUse this flag to get the count and execution time of potentially expensive\nfunctions in a table. Example:\n\n```txt frame=terminal\n$ knip --performance\n\n(results)\n\nName                           size  min       max       median    sum\n-----------------------------  ----  --------  --------  --------  --------\nfindReferences                  648     84.98   7698.61     96.41  70941.70\ncreateProgram                     2   6295.84   7064.68   6680.26  13360.52\nglob                              6      0.05    995.78    513.82   3150.87\nfindESLintDependencies            2      0.01     74.41     37.21     74.41\nfindGithubActionsDependencies     6      0.16     12.71      0.65     23.45\nfindBabelDependencies             2      0.00     38.75     19.37     38.75\n...\n\nTotal running time: 5s\n```\n\n- `name`: the internal Knip function name\n- `size`: number of function invocations\n- `min`: the fastest invocation\n- `max`: the slowest invocation\n- `median`: the median invocation\n- `sum` the accumulated time of all invocations\n\nThis is not yet available in Bun, since it does not support\n`performance.timerify` ([GitHub issue][18]).\n\n### `--duration`\n\nShortcut: `-u`\n\nPrint total running time. Zero overhead — no `timerify` instrumentation, unlike\n`--performance`.\n\n### `--performance-fn`\n\nLimit the output of `--performance` to a single function to minimize the\noverhead of the `timerify` Node.js built-in and focus on that function alone:\n\n```txt frame=terminal\n$ knip --performance-fn resolveSync\n\n(results)\n\nName         size   min   max   median   sum\n-----------  -----  ----  ----  ------  ------\nresolveSync  66176  0.00  5.69    0.00  204.85\n\nTotal running time: 12.9s\n```\n\n### `--trace`\n\nTrace exports to see where they are imported.\n\nAlso see [Trace][19].\n\n### `--trace-dependency [name]`\n\nTrace package or binary name to see where it's referenced. Implies\n[--trace][20].\n\n### `--trace-export [name]`\n\nTrace export name to see where it's imported. Implies [--trace][20].\n\n### `--trace-file [path]`\n\nTrace file to see where its exports are imported. Implies [--trace][20].\n\n[1]: ./integrations.md\n[2]: https://bun.sh\n[3]: ../reference/known-issues.md\n[4]: https://no-color.org/\n[5]: https://www.npmx.dev/package/picocolors\n[6]: ./known-issues.md#stale-cache-results\n[7]: ./configuration.md#includeentryexports\n[8]: ../features/production-mode.md\n[9]: #--production\n[10]: ../features/monorepos-and-workspaces.md#filter-workspaces\n[11]: ../guides/namespace-imports.md\n[12]: ./issue-types.md\n[13]: ../features/reporters.md#cycles\n[14]: ../features/auto-fix.mdx\n[15]: #--reporter-reporter\n[16]: ../features/reporters.md\n[17]: ../guides/troubleshooting.md#debug\n[18]: https://github.com/oven-sh/bun/issues/9271\n[19]: ../guides/troubleshooting.md#trace\n[20]: #--trace\n","packages/docs/src/content/docs/reference/configuration-hints.md":"---\ntitle: Configuration Hints\ndescription: The configuration hints Knip emits to keep your config tidy, what each one means, and how to resolve it.\n---\n\nKnip emits configuration hints to help keep your configuration file tidy and\nreduce drift.\n\nThey're warnings by default, not lint findings. But addressing the hints might\nimprove results significantly. The hints on this page are sorted by\nimpact/importance (most impactful first).\n\nUse [`--treat-config-hints-as-errors`][1] or [`treatConfigHintsAsErrors`][2] to\nmake any configuration hint an error and result in a non-zero exit code to fail\nCI.\n\n## Unconfigured projects\n\nToo many unused files in a single workspace-codebase, caused by a missing\nconfiguration file or incomplete configuration:\n\n```\nCreate knip.json configuration file, and add entry and/or refine project files (42 unused files)\n```\n\nOr if you have a config file:\n\n```\nAdd entry and/or refine project files (42 unused files)\n```\n\n**Solution**: Add and refine `entry` and/or `project` patterns.\n\nRelated resources:\n\n- [Configuration][3]\n- [Monorepos & Workspaces][4]\n\n## Unconfigured workspaces\n\nToo many unused files in a monorepo, caused by a missing configuration file or\nincomplete configuration:\n\n```\nCreate knip.json configuration file with workspaces[\"packages/app\"] object (42 unused files)\n```\n\nOr if you have a config file:\n\n```\nAdd entry and/or refine project files in workspaces[\"packages/app\"] (42 unused files)\n```\n\n**Solution**: add a `workspaces` object to configuration. Add and refine `entry`\nand/or `project` patterns. For instance, the example message translates to\nconfiguration like this:\n\n```json\n{\n  \"workspaces\": {\n    \"packages/app\": {\n      \"entry\": [\"src/App.tsx\"],\n      \"project\": [\"src/**/*.ts\"]\n    }\n  }\n}\n```\n\nRelated resources:\n\n- [Configuring Project Files][5]\n- [Monorepos & Workspaces][4]\n\n## Top-level entry/project\n\nIn monorepos, Knip uses only `entry` and `project` under `workspaces`. The\ntop-level keys with the same name are ignored.\n\n```\nRemove, or move unused top-level entry to one of \"workspaces\"\nRemove, or move unused top-level project to one of \"workspaces\"\n```\n\n**Solution**: Remove top-level `entry` and `project` keys, use these options in\n`workspaces` instead.\n\n```jsonc\n{\n  \"entry\": [\"src/App.tsx\"], // move entry/project from here... ↴\n  \"project\": [\"src/**/*.ts\"],\n  \"workspaces\": {\n    \".\": {\n      \"entry\": [\"src/App.tsx\"], // ...to the correct workspace(s) ↲\n      \"project\": [\"src/**/*.ts\"],\n    },\n  },\n}\n```\n\n## Stale workspace configuration\n\nA key in the `workspaces` configuration matches no workspace in the project, for\ninstance after the workspace was removed or renamed.\n\n```\nRemove from workspaces\n```\n\n**Solution**: Remove the stale key from `workspaces`, or correct its path.\n\n## Unused entry in ignore group\n\nAn entry of an ignore list is no longer needed, remove it.\n\n```\nRemove from ignoreWorkspaces\nRemove from ignoreDependencies\nRemove from ignoreBinaries\nRemove from ignoreUnresolved\n```\n\n**Solution**: Remove the entry from the array.\n\n## Useless patterns\n\nA glob pattern in `entry` or `project` does not match any files.\n\n```\nRefine entry pattern (no matches)\nRefine project pattern (no matches)\n```\n\n**Solution**: Refine or remove the `entry` or `project` entry.\n\n## Redundant patterns\n\nA glob/pattern is redundant, because it's already covered by defaults or added\nby an enabled plugin.\n\n```\nRemove redundant entry pattern\nRemove redundant project pattern\n```\n\n**Solution**: Remove the `entry` or `project` entry.\n\n## Missing package entry file\n\n```\nPackage entry file not found\n```\n\n**Solution**: Refine or remove the entry in `package.json`.\n\n[1]: ./cli.md#--treat-config-hints-as-errors\n[2]: ./configuration.md#treatconfighintsaserrors\n[3]: ../overview/configuration.md\n[4]: ../features/monorepos-and-workspaces.md\n[5]: ../guides/configuring-project-files.md\n","packages/docs/src/content/docs/reference/configuration.md":"---\ntitle: Configuration\ndescription: Every knip.json option, including entry, project, paths, workspaces, plugins, rules, tags, ignores and compilers.\n---\n\nThis page lists all configuration file options.\n\n## File Types\n\n### JSON Schema\n\nA `$schema` field is a URL that you put at the top of your JSON file. This\nallows you to get red squiggly lines inside of your IDE when you make a typo or\nprovide an otherwise invalid configuration option.\n\nIn JSON, use the provided JSON schema:\n\n```json title=\"knip.json\"\n{\n  \"$schema\": \"https://unpkg.com/knip@6/schema.json\"\n}\n```\n\n### JSONC\n\nIn JSONC, use the provided JSONC schema:\n\n```json title=\"knip.jsonc\"\n{\n  \"$schema\": \"https://unpkg.com/knip@6/schema-jsonc.json\"\n}\n```\n\nUse JSONC if you want to use comments and/or trailing commas.\n\n### TypeScript\n\nSee [dynamic configuration][1] about dynamic and typed configuration files.\n\n## Project\n\n### `entry`\n\nArray of glob patterns to find entry files. Prefix with `!` for negation.\nExample:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts\", \"scripts/*.ts\", \"!scripts/except-this-one.ts\"]\n}\n```\n\nAlso see [configuration][2] and [entry files][3].\n\n### `project`\n\nArray of glob patterns to find project files. Example:\n\n```json title=\"knip.json\"\n{\n  \"project\": [\"src/**/*.ts\", \"scripts/**/*.ts\"]\n}\n```\n\nAlso see [configuration][2] and [entry files][3].\n\n### `paths`\n\nTools like TypeScript, webpack and Babel support import aliases in various ways.\nKnip automatically includes `compilerOptions.paths` from the TypeScript\nconfiguration, but does not automatically use other types of import aliases.\nThey can be configured manually:\n\n```json title=\"knip.json\"\n{\n  \"paths\": {\n    \"@lib\": [\"./lib/index.ts\"],\n    \"@lib/*\": [\"./lib/*\"]\n  }\n}\n```\n\nEach workspace can have its own `paths` configured. Knip `paths` follow the\nTypeScript semantics:\n\n- Path values are an array of relative paths.\n- Paths without an `*` are exact matches.\n\n## Workspaces\n\n### `workspaces`\n\nConfigure `entry`, `project`, plugins and most other options per workspace. Keys\nare workspace directories (globs allowed); the root workspace is `\".\"`.\n\n```json title=\"knip.json\"\n{\n  \"workspaces\": {\n    \".\": {\n      \"entry\": [\"scripts/*.ts\"],\n      \"project\": [\"scripts/**/*.ts\"]\n    },\n    \"packages/*\": {\n      \"entry\": [\"src/index.ts\"],\n      \"project\": [\"src/**/*.ts\"]\n    }\n  }\n}\n```\n\nWorkspaces configured here that aren't already defined in the root\n`package.json` (or `pnpm-workspace.yaml`) are added to the analysis. Also see\n[Monorepos & Workspaces][4].\n\nIndividual workspace configurations may contain all other options listed on this\npage, except for the following root-only options:\n\n- `exclude` / `include`\n- `ignoreWorkspaces`\n- `workspaces`\n\nWorkspaces can't be nested in a Knip configuration, but they can be nested in a\nmonorepo folder structure.\n\nAlso see [Monorepos and workspaces][4].\n\n## Plugins\n\nThere are a few options to modify the behavior of a plugin:\n\n- Override a plugin's `config` or `entry` location\n- Force-enable a plugin by setting its value to `true`\n- Disable a plugin by setting its value to `false`\n\n```json title=\"knip.json\"\n{\n  \"mocha\": {\n    \"config\": \"config/mocha.config.js\",\n    \"entry\": [\"**/*.spec.js\"]\n  },\n  \"playwright\": true,\n  \"webpack\": false\n}\n```\n\nIt should be rarely necessary to override the `entry` patterns, since plugins\nalso read custom entry file patterns from the tooling configuration (see\n[Plugins → entry files][5]).\n\nPlugin configuration can be set on root and on a per-workspace level. If enabled\non root level, it can be disabled on workspace level by setting it to `false`\nthere, and vice versa.\n\nAlso see [Plugins][6].\n\n## Rules & Filters\n\n### `rules`\n\nSee [Rules & Filters][7].\n\n### `include`\n\nSee [Rules & Filters][7].\n\n### `exclude`\n\nSee [Rules & Filters][7].\n\n### `tags`\n\nExports can be tagged with known or arbitrary JSDoc/TSDoc tags:\n\n```ts\n/**\n * Description of my exported value\n *\n * @type number\n * @internal Important matters\n * @lintignore\n */\nexport const myExport = 1;\n```\n\nAnd then include (`+`) or exclude (`-`) these tagged exports from the report\nlike so:\n\n```json\n{\n  \"tags\": [\"-lintignore\"]\n}\n```\n\nThis way, you can either focus on or ignore specific tagged exports with tags\nyou define yourself. This also works for individual enum and namespace members.\n\nThe default directive is `+` (include) and the `@` prefix is ignored, so the\nnotation below is valid and will report only exports tagged `@lintignore` or\n`@internal`:\n\n```json\n{\n  \"tags\": [\"@lintignore\", \"@internal\"]\n}\n```\n\n:::caution\n\nTags must not contain hyphens or plus symbols, so it is recommended to stick to\nletters and avoid snake-case.\n\n:::\n\nAlso see [JSDoc & TSDoc Tags][8].\n\n### `preprocessor`\n\nPreprocess the results before providing them to the reporter(s). Can be a single\npreprocessor or an array of preprocessors. Each value is a path to a local file\nor an npm package name.\n\n```json title=\"knip.json\"\n{\n  \"preprocessor\": [\"./first.ts\", \"./second.ts\"]\n}\n```\n\nAlso see [Preprocessors][9].\n\n### `preprocessorOptions`\n\nExtra options to pass to the preprocessor.\n\n```json title=\"knip.json\"\n{\n  \"preprocessor\": \"./my-preprocessor.ts\",\n  \"preprocessorOptions\": { \"key\": \"value\" }\n}\n```\n\n### `treatConfigHintsAsErrors`\n\nExit with non-zero code (1) if there are any configuration hints.\n\n```json title=\"knip.json\"\n{\n  \"treatConfigHintsAsErrors\": true\n}\n```\n\n### `treatTagHintsAsErrors`\n\nExit with non-zero code (1) if there are any tag hints.\n\n```json title=\"knip.json\"\n{\n  \"treatTagHintsAsErrors\": true\n}\n```\n\n## Ignore Issues\n\n### `ignore`\n\n:::tip\n\nPlease read [configuring project files][10] before using the `ignore` option.\n\n:::\n\nAvoid `ignore` patterns. There is almost always a better solution:\n\n- Follow up on configuration hints (if there are any).\n- Fine-tune `entry` and `project` patterns.\n- Use [production mode][11].\n- Other `ignore*` options.\n\n**NOTE**: An exception to the rule: to _temporarily_ report only issues in files\nthat match the negated `ignore` pattern:\n\n```json title=\"knip.json\"\n{\n  \"ignore\": [\"!src/dir/**\"]\n}\n```\n\n### `ignoreFiles`\n\nArray of glob patterns of files to exclude from the \"Unused files\" section only.\n\nUnlike `ignore`, which suppresses all issue types for matching files,\n`ignoreFiles` only affects the `files` issue type. Use this when a file should\nremain analyzed for other issues (exports, dependencies, unresolved) but should\nnot be considered for unused file detection.\n\n```json title=\"knip.json\"\n{\n  \"ignoreFiles\": [\"src/generated/**\", \"fixtures/**\"]\n}\n```\n\nSuffix an item with `!` to enable it only in production mode.\n\n### `ignoreBinaries`\n\nExclude binaries that are used but not provided by any dependency from the\nreport. Value is an array of binary names or regular expressions. Example:\n\n```json title=\"knip.json\"\n{\n  \"ignoreBinaries\": [\"zip\", \"docker-compose\", \"pm2-.+\"]\n}\n```\n\nActual regular expressions can be used in dynamic configurations:\n\n```ts title=\"knip.ts\"\nexport default {\n  ignoreBinaries: [/^pm2-.+/],\n};\n```\n\nSuffix an item with `!` to enable it only in production mode.\n\n### `ignoreGlobalBinaries`\n\nDefaults to `true`, suppressing missing-binary reports for common global commands such as `git` and `docker`. Set it to `false` to report these commands where a project dependency is expected:\n\n```json title=\"knip.json\"\n{\n  \"ignoreGlobalBinaries\": false,\n  \"ignoreBinaries\": [\"git\"]\n}\n```\n\nDependencies that provide a referenced binary still count as used, and `ignoreBinaries` still applies. Optional commands, including bare CI/hook commands and commands installed on demand, produce no missing-binary reports. Workspaces inherit the top-level value unless they override it.\n\n### `ignoreDependencies`\n\nArray of package names to exclude from the report. Regular expressions allowed.\nExample:\n\n```json title=\"knip.json\"\n{\n  \"ignoreDependencies\": [\"hidden-package\", \"@org/.+\"]\n}\n```\n\nActual regular expressions can be used in dynamic configurations:\n\n```ts title=\"knip.ts\"\nexport default {\n  ignoreDependencies: [/@org\\/.*/, /^lib-.+/],\n};\n```\n\nSuffix an item with `!` to enable it only in production mode.\n\nAlso see [Unused dependencies][12].\n\n### `ignoreMembers`\n\nArray of enum and namespace members to exclude from the report. Regular\nexpressions allowed. Example:\n\n```json title=\"knip.json\"\n{\n  \"ignoreMembers\": [\"render\", \"on.+\"]\n}\n```\n\nActual regular expressions can be used in dynamic configurations.\n\n### `ignoreUnresolved`\n\nArray of specifiers to exclude from the report. Regular expressions allowed.\nExample:\n\n```json title=\"knip.json\"\n{\n  \"ignoreUnresolved\": [\"ignore-unresolved-import\", \"#virtual/.+\"]\n}\n```\n\nActual regular expressions can be used in dynamic configurations:\n\n```ts title=\"knip.ts\"\nexport default {\n  ignoreUnresolved: [/^#virtual\\/.+/],\n};\n```\n\n### `ignoreWorkspaces`\n\nArray of workspaces to ignore, globs allowed. Example:\n\n```json title=\"knip.json\"\n{\n  \"ignoreWorkspaces\": [\n    \"packages/go-server\",\n    \"packages/flat/*\",\n    \"packages/deep/**\"\n  ]\n}\n```\n\nSuffix an item with `!` to enable it only in production mode.\n\nPrefix an item with `!` to override an earlier wildcard.\n\n### `ignoreIssues`\n\nIgnore specific issue types for specific file patterns. Keys are glob patterns\nand values are arrays of issue types to ignore for matching files. This allows\nignoring specific issues (like unused exports) in generated files while still\nreporting other issues in those same files.\n\n```json title=\"knip.json\"\n{\n  \"ignoreIssues\": {\n    \"src/generated/**\": [\"exports\", \"types\"],\n    \"**/*.generated.ts\": [\"exports\", \"enumMembers\", \"namespaceMembers\"]\n  }\n}\n```\n\n### `cycles`\n\nConfigure circular dependency (`cycles`) detection.\n\nSet `dynamicImports` to include dynamic `import()` edges, which are excluded by\ndefault (a dynamic import defers evaluation, so it does not cause the\ninitialization hazard cycles are meant to catch).\n\nUse `allow` to accept specific cycles by exact path while keeping other `cycles`\nissues enabled. Path entries are relative to the project root and omit the\nclosing repeat of the first file.\n\n```json title=\"knip.json\"\n{\n  \"cycles\": {\n    \"dynamicImports\": true,\n    \"allow\": [[\"src/i18n/index.ts\", \"src/i18n/middleware.ts\"]]\n  }\n}\n```\n\n## Exports\n\n### `ignoreExportsUsedInFile`\n\nIn files with multiple exports, some of them might be used only internally. If\nthese exports should not be reported, there is a `ignoreExportsUsedInFile`\noption available. With this option enabled, when something is also no longer\nused internally, it will be reported as unused.\n\n```json title=\"knip.json\"\n{\n  \"ignoreExportsUsedInFile\": true\n}\n```\n\nIn a more fine-grained manner, to ignore only specific issue types:\n\n```json title=\"knip.json\"\n{\n  \"ignoreExportsUsedInFile\": {\n    \"interface\": true,\n    \"type\": true\n  }\n}\n```\n\nValid keys are the symbol types Knip distinguishes: `class`, `enum`, `function`,\n`interface`, `member`, `namespace`, `type` and `variable`.\n\nSet this option at root level to enable this globally, or within workspace\nconfigurations individually.\n\n### `includeEntryExports`\n\nBy default, Knip does not report unused exports in entry files. When a\nrepository (or workspace) is self-contained or private, you may want to include\nentry files when reporting unused exports:\n\n```json title=\"knip.json\"\n{\n  \"includeEntryExports\": true\n}\n```\n\nIf enabled, Knip will report unused exports in entry source files. But not in\nentry and configuration files as configured by plugins, such as `next.config.js`\nor `src/routes/+page.svelte`. Entry files discovered only through `package.json`\nscripts are also excluded; add them to `entry` to include their exports.\n\nThis will also enable reporting unused members of exported enums and namespaces.\n\nSet this option at root level to enable this globally, or within workspace\nconfigurations individually.\n\n## Compilers\n\nKnip supports custom compilers to transform files before analysis.\n\n:::note\n\nSince compilers are functions, they can only be used in dynamic configuration\nfiles (`.js` or `.ts`), not in JSON configuration files.\n\n:::\n\n### `compilers`\n\nOverride built-in compilers or add custom compilers for additional file types.\n\nAlso see [Compilers][13].\n\n[1]: ../reference/dynamic-configuration.mdx\n[2]: ../overview/configuration.md\n[3]: ../explanations/entry-files.md\n[4]: ../features/monorepos-and-workspaces.md\n[5]: ../explanations/plugins.md#entry-files\n[6]: ../explanations/plugins.md\n[7]: ../features/rules-and-filters.md#filters\n[8]: ./jsdoc-tsdoc-tags.md\n[9]: ../features/reporters.md#preprocessors\n[10]: ../guides/configuring-project-files.md\n[11]: ../features/production-mode.md\n[12]: ../guides/handling-issues.mdx#unused-dependencies\n[13]: ../features/compilers.md\n","packages/docs/src/content/docs/reference/faq.md":"---\ntitle: FAQ\ndescription: Design decisions behind Knip, common pitfalls, how it compares to ESLint and tree-shaking, and how the module graph works.\ndate: 2024-08-20\n---\n\n## Introduction\n\nKnip finds and fixes unused dependencies, exports and files. As a \"kitchen sink\"\nin the npm ecosystem, it creates a comprehensive module graph of your project.\n\n:::note[Rationale]\n\nThe JavaScript/TypeScript ecosystem has a vast amount of frameworks and tools.\nAdditionally, file locations, configuration semantics, command-line arguments\nand so on vary wildly. Files and dependencies are referenced in many ways. Knip\ntries harder than you think to cover it all.\n\n:::\n\nThis FAQ explains a few design decisions and why certain things work the way\nthey do, here and there in more depth than the rest of the docs.\n\n:::tip\n\nTry the [Knip MCP Server][1] or the [Knip Editor Extension][2]. Let your coding\nagent use the built-in MCP Server and create a custom `knip.json` for you, so\nyou don't have to.\n\n:::\n\n## Common Pitfalls\n\n### Why shouldn't I ignore or disable configuration hints?\n\nConfiguration hints are critical for building a healthy and accurate module\ngraph. They usually indicate that Knip cannot resolve a dependency, plugin, or\nentry file. If you ignore or disable these hints, Knip's understanding of your\nproject will be incomplete, which inevitably leads to false positives (reporting\nused code as unused). Always address configuration hints first before looking at\nother reported issues.\n\n### Why is it a bad idea to use `ignore` patterns like I do in ESLint?\n\nKnip is not a regular file-based linter like ESLint. It works by analyzing the\nentire interconnected module graph of your project. Using `ignore` patterns does\nnot exclude files from the analysis, it only suppresses the reporting of issues\nin those files. This hides real issues and creates blind spots. Instead of\nignoring files, ensure your entry points and plugins are configured correctly,\nand use `project` patterns to define the boundaries of your codebase. Read more:\n[Configuring Project Files][3].\n\nIf you have specific exports (such as types) that are only used within the file\nthey are defined, use the [ignoreExportsUsedInFile][4] configuration option\nrather than ignoring the file entirely.\n\n### How should I exclude tests and development tools from the analysis?\n\nA common mistake is trying to exclude test files, storybooks, or development\ntools using `project` or `ignore` patterns. The correct approach is to use\n[production mode][5]. This mode is specifically designed to strictly analyze\nonly your production source code and `dependencies`, automatically excluding\ntests and `devDependencies` without requiring complex ignore rules.\n\n### Why shouldn't I run `knip --fix` immediately?\n\nRunning `knip --fix` before your configuration is fully settled is dangerous. If\nyour configuration is missing entry points or has unresolved hints, Knip might\nthink perfectly valid, actively used code is unused. Auto-fixing in this state\ncan lead to deleting code that your application relies on. Always verify the\nreported issues manually and ensure your configuration is solid before using the\n`--fix` flag.\n\n## Comparison\n\n### Why isn't Knip an ESLint plugin?\n\nLinters like ESLint analyze files separately, while Knip lints projects as a\nwhole.\n\nKnip requires a full module and dependency graph to find clutter across the\nproject. Building the graph is substantial work, especially in monorepos.\n\nFile-oriented linters like ESLint are complementary to Knip.\n\n### Isn't tree-shaking enough?\n\nNo. They share a goal: improving UX by removing unused code. But tree-shaking\nand Knip are different, complementary tools.\n\nTree-shaking is a build-time optimization to reduce production bundle size. It\noperates on bundled production code, which might include external code, and runs\nautomatically (out of your hands).\n\nOn the other hand, Knip is a project linter for the development and QA phase. It\nreports and fixes only your own source code, and leaves the changes for you to\nreview. It focuses on inter-file dependencies, so dead code within a single file\nmay slip through.\n\nBesides those differences, Knip has a broader scope:\n\n- Improve DX (see [less is more][6]).\n- Unless using [production mode][5], also lint all source code like tests,\n  scripts and Storybook stories.\n- Handle more [types of issues][7] (such as unlisted dependencies).\n\nFor how Knip compares to other unused-code tools and how to migrate from them,\nsee [Comparison & Migration][8].\n\n## Synergy\n\n### Why does Knip have plugins?\n\nPlugins are an essential part of Knip. They save you a lot of configuration out\nof the box, by adding entry files as accurately as possible and only for the\ntools actually installed. More powerful still are their custom parsers for\nconfiguration files and command-line argument definitions.\n\nFor instance, Vitest has the `environment` configuration option. The Vitest\nplugin knows `\"node\"` is the default value for `environment` which does not\nrequire an extra package, but will translate `\"edge-runtime\"` to the\n`@edge-runtime/vm` package. This allows Knip to report it if this package is not\nlisted in `package.json`, or when it is no longer used after changes in the\nVitest configuration.\n\nConfiguration files may also contain references to entry files. For instance,\nJest has `setupFilesAfterEnv: \"<rootDir>/jest.setup.js\"` or a reference may\npoint to a file in another workspace in the same monorepo, e.g. `setupFiles:\n['@org/shared/jest-setup.ts']`. Those entry files may also contain imports of\ninternal modules or external dependencies, and so on.\n\n### Why is Knip so heavily engineered?\n\nEven though a modular approach has its merits, for Knip it makes sense to have\nall the pieces in a single tool.\n\nBuilding up the module and dependency graph takes more than standard module\nresolution. It needs dynamic analysis, not just static: plugin parsers actually\nload and execute dynamic tooling configuration files to read their exported\nvalue. On top of that, [exports consumed by external libraries][9] require type\ninformation. And shell script parsing is needed to find the right entry files,\nconfiguration files and dependencies accurately.\n\nThe rippling effect of plugins recursively pulling in more entry files and\ndependencies is exactly what [\"comprehensive\"][10] refers to.\n\n## Design decisions\n\n### Why isn't production mode the default?\n\nThe default mode of Knip includes all source files, tests, dependencies, dev\ndependencies and tooling configuration.\n\nOn the other hand, production mode considers only source files and production\ndependencies. Plugins add only production entry files.\n\nWhich mode should've been the default? They both have their merits:\n\n- Production mode catches dead production code and dependencies. This mode has\n  the most impact on UX, since less code tends to be faster and safer.\n- Default mode potentially catches more issues, e.g. lots of unused plugins of\n  tooling, including most issues found in production mode. This mode has the\n  most impact on DX, for the same reason.\n\nAlso see [production mode][5].\n\n### Why doesn't Knip just read the lockfile?\n\nKnip reads the `package.json` file of each dependency. Most of the information\nrequired is in the lockfile as well, which would be more efficient. However,\nlockfiles lack some data, including:\n\n- It requires lockfile parsing for each lockfile format and version of each\n  package manager.\n- The lockfile doesn't contain whether the package [has types included][11].\n- The lockfile doesn't contain entry point fields (`main`, `module`, `exports`)\n  needed to resolve what a dependency actually exposes.\n- The lockfile doesn't contain `bin` entries to determine installed binaries.\n\n### Why doesn't Knip use an existing module resolver?\n\nIt does: Knip uses [oxc-resolver][12]. A runtime or bundler resolver can't be\nused as-is, because Knip resolves imports to your source across every workspace\nin a (mono)repo. It has to:\n\n- Resolve to source (`src/module.ts`), not type definitions (`module.d.ts`) or\n  the build artifact a `package.json#main` like `dist/module.js` points to\n- Resolve non-standard extensions like `.svelte`, `.astro` and `.css` so those\n  files enter the module graph\n\noxc-resolver is configurable enough for this. Combined with a thin layer for\nKnip-configured `paths` and plugin aliases. This covers resolution across all\nworkspaces and[script parsing][13] and references to files in other workspaces.\n\n### Why doesn't Knip match my TypeScript project structure?\n\nRepositories and workspaces in a monorepo aren't necessarily structured like\nTypeScript projects. Put simply, the location of `package.json` files isn't\nalways adjacent to `tsconfig.json` files. Knip follows the structure of\nworkspaces in a monorepo.\n\nAn additional layering of TypeScript projects would complicate things. The\ndownside is that a `tsconfig.json` file not used by Knip may have conflicting\nmodule resolution settings, potentially resulting in missed files.\n\nIn practice, this is rarely an issue. Knip sticks to the workspaces structure\nand installs a single \"kitchen sink\" module resolver function per workspace.\nDifferent strategies might add more complexity and performance penalties, while\nthe current strategy is simple, fast and good enough.\n\nNote that any directory with a `package.json` not listed in the root\n`package.json#workspaces` can be added to the Knip configuration manually to\nhave it handled as a separate workspace.\n\nIf you do want Knip to take its project files from `tsconfig.json` rather than\nits own `project` patterns, see [`--use-tsconfig-files`][14].\n\n### Why doesn't Knip just use `ts.findReferences`?\n\nTypeScript has a very good \"Find references\" feature, that you might be using in\nyour IDE as well. There are a few reasons Knip doesn't use it:\n\n- It requires the full TypeScript language service, which is heavy to\n  initialize.\n- It must be called per symbol. A project with thousands of exports would need\n  thousands of calls, each scanning potentially all files. Knip parses each file\n  once and resolves all export usages from the resulting graph.\n- It operates within a single TypeScript program. Monorepos with multiple\n  `tsconfig.json` files would need separate language service instances.\n- It cannot see into non-standard files like `.vue`, `.svelte` and `.astro`.\n\nKnip's module graph is also serializable and cacheable, and usable for other\ntools to build upon.\n\n### Why doesn't Knip have...?\n\nExamples of features that have been requested include:\n\n- Expose programmatic API\n- Add local/custom plugins\n- Expose the module and dependency graph\n- Custom AST visitors, e.g. to find and return:\n  - Unused interface/type members\n  - Unused object members (and e.g. React component props)\n  - Unused object props in function return values\n- Analyze workspaces in parallel\n- Support Deno\n\nThese are all interesting ideas, but most increase the API surface area, and all\nrequire more development efforts and maintenance. Time is limited and\n[sponsorships][15] currently don't cover - this can change though!\n\n## Under the hood\n\n### Where does Knip look for entry files?\n\nKnip discovers them from defaults, `package.json`, enabled plugins, source-code\nimports and resolution calls (`require.resolve`, `import.meta.resolve`, `new\nURL`, `new Worker`, `module.register`), and parsed scripts. See [Entry\nFiles][16] for the complete list. Entry files are added to the module graph, and\n[module resolution][17] may result in more entry files recursively until none\nremain.\n\n### What does Knip look for in source files?\n\nKnip uses oxc-parser to parse source files, it's powerful and fault-tolerant.\nKnip visits all nodes of the generated AST to find:\n\n- Imports and dynamic imports of internal modules and external dependencies\n- Exports\n- Accessed properties on namespace imports and re-exports to track individual\n  export usage\n- Entry files from `require.resolve`, `import.meta.resolve`, `new URL(specifier,\nimport.meta.url)`, `new Worker(…)`, `child_process` `fork`/`spawn`/`execFile`,\n  and `module.register()`\n- Scripts passed to the [script parser][13]: tagged `$` templates (`bun`,\n  `execa`, `zx`) and `node:child_process`, `execa` and `nano-spawn` calls\n\n### What's in the graph?\n\nOnce built, the graph holds everything needed to produce the report: every\n[issue type][7], from unused files and dependencies to unused exports, types and\nenum members.\n\nThe graph also surfaces more interesting details, such as:\n\n- Circular references\n- Usage numbers per export\n- Export usage across workspaces in a monorepo\n- List of all binaries used\n- List of all used (OS) binaries not installed in `node_modules`\n\n### How does Knip handle non-standard import syntax?\n\nKnip tries to be resilient against import syntax like what's used by e.g.\nwebpack loaders or Vite asset imports. Knip strips off the prefixes and suffixes\nin import specifiers like this:\n\n```ts title=\"component.ts\"\nimport Icon from './icon.svg?raw';\nimport Styles from '-!style-loader!css-loader?modules!./styles.css';\n```\n\nIn this example, the `style-loader` and `css-loader` dependencies should be\ndependencies found in webpack configuration, handled by Knip's webpack plugin.\n\n## TypeScript\n\n### What's the difference between workspaces, projects and programs?\n\nA workspace is a directory with a `package.json` file. They're configured in\n`package.json#workspaces` (or `pnpm-workspaces.yml`). In case a directory has a\n`package.json` file, but is not a workspace (from a package manager\nperspective), it can be added as a workspace to the Knip configuration.\n\nProjects - in the context of TypeScript - are directories with a `tsconfig.json`\nfile. They're not a concept in Knip.\n\nKnip analyzes all workspaces using a single module graph with a shared module\nresolver.\n\n### What's up with that configurable `tsconfig.json` location?\n\nTwo settings point Knip at a `tsconfig.json`, and they do different things:\n\n- [`--tsConfig [file]`][18] (CLI, root only) sets an alternative location for\n  the root `tsconfig.json`. Knip reads its `compilerOptions`, notably `paths`\n  and `moduleResolution`.\n- [`typescript.config`][19] (plugin, per workspace) sets the location the\n  TypeScript plugin reads to extract referenced dependencies from `extends`,\n  `compilerOptions.types` and JSX settings:\n\n```json title=\"tsconfig.json\"\n{\n  \"extends\": \"@tsconfig/node20/tsconfig.json\",\n  \"compilerOptions\": {\n    \"jsxImportSource\": \"hastscript/svg\"\n  }\n}\n```\n\nFrom this example, Knip can tell whether `@tsconfig/node20` and `hastscript` are\nlisted in `package.json`.\n\nNote that the TypeScript plugin doesn't add TypeScript support to Knip (that's\nbuilt-in); like other plugins, it extracts dependencies from `tsconfig.json`. If\npath aliases from `compilerOptions.paths` aren't picked up, either point\n`--tsConfig` at the right `tsconfig.json` or add [paths][20] to the Knip config\n(per workspace).\n\n### What does `--use-tsconfig-files` do?\n\nBy default Knip discovers project files with its own `project` patterns. The\n[`--use-tsconfig-files`][14] flag instead takes them from `tsconfig.json` per\nworkspace. Those become TypeScript program files, so Knip analyzes their exports\nand dependencies but does not report them as unused files: delegating project\ndefinition to `tsconfig.json` declares them intentional, including empty files.\nThis is by design: use the default `project` patterns (discovery mode) to flag\ndangling files. Implicitly enabled in the [editor extension, MCP server and\nlanguage server][21] without a Knip configuration file.\n\n## Compilers\n\n### How does Knip handle Svelte or Astro files?\n\nTo further increase the coverage of the module graph, non-standard files other\nthan JavaScript and TypeScript modules should be included as well. For instance,\n`.mdx` and `.astro` files can import each other, internal modules and external\ndependencies.\n\nKnip includes basic \"compilers\" for a few common file types (Astro, MDX, Svelte,\nVue). These are lightweight regex-based extractors, not actual compilers. You\ncan override the built-in compilers with your project's actual compiler, and add\nadditional ones for other file types.\n\n### Why are the exports of my `.vue` files not used?\n\nThe built-in compilers extract `import` statements only, so the exports declared\nin a `.vue` or `.svelte` file aren't analyzed and may be reported as unused.\nOverride the built-in with a real compiler. See [Compilers][22].\n\n[1]: ../reference/integrations.md#mcp-server\n[2]: ../reference/integrations.md#vs-code-extension\n[3]: ../guides/configuring-project-files.md\n[4]: ../reference/configuration.md#ignoreexportsusedinfile\n[5]: ../features/production-mode.md\n[6]: ../explanations/why-use-knip.md#less-is-more\n[7]: ./issue-types.md\n[8]: ../explanations/comparison-and-migration.md\n[9]: ../guides/handling-issues.mdx#external-libraries\n[10]: ../explanations/why-use-knip.md#comprehensive\n[11]: ../guides/handling-issues.mdx#type-definition-packages\n[12]: https://oxc.rs/docs/guide/usage/resolver.html\n[13]: ../features/script-parser.md\n[14]: ../reference/cli.md#--use-tsconfig-files\n[15]: /sponsors\n[16]: ../explanations/entry-files.md#where-knip-looks-for-entry-files\n[17]: #why-doesnt-knip-use-an-existing-module-resolver\n[18]: ../reference/cli.md#--tsconfig-file\n[19]: ../explanations/plugins.md#configuration-files\n[20]: ../reference/configuration.md#paths\n[21]: ../reference/integrations.md\n[22]: ../features/compilers.md\n","packages/docs/src/content/docs/reference/integrations.md":"---\ntitle: Integrations\ndescription: Knip's VS Code extension, JetBrains plugin, MCP server and language server for editor diagnostics and coding agents.\n---\n\n- [VS Code/VSX Extension][1]\n- [JetBrains Plugin][2]\n- [MCP Server][3]\n- [Language Server][4]\n\n## VS Code Extension\n\nThe official VS Code extension provides a rich integration with the [Knip\nLanguage Server][4]:\n\n- **Diagnostics**: Inline warnings for unused dependencies, exports and files\n- **Hover Information**: Hover over exports to see import and usage locations\n- **Imports Tree View**: Direct links to implementations\n- **Exports Tree View**: Direct links to import and usage locations\n- **Contention Detection**: Warnings for circular dependencies, ambiguous,\n  shadowed and diamond-shaped import chains\n- **Built-in MCP Server**: Automated configuration support for coding agents\n\nFind [Knip on the VS Code Marketplace][5] and find [Knip in the Open VSX\nRegistry][6].\n\nSee below for [screenshots][7].\n\n## JetBrains Plugin\n\nA community plugin is available for JetBrains IDEs including WebStorm, IntelliJ\nIDEA, and others. The plugin is powered by the [Knip Language Server][4] and\nprovides diagnostics. Find [Knip on the JetBrains Marketplace][8].\n\n## MCP Server\n\nThe standalone MCP Server enables coding agents to configure Knip automatically.\nTell your agent to \"configure knip\" and it will use the available tools to\ncreate, analyze and optimize your `knip.json` configuration.\n\nThe [Knip MCP Server][9] is available separately and built into the [Knip VS\nCode Extension][1].\n\nStart:\n\n```sh\nnpx @knip/mcp\n```\n\nNote: The VS Code extension has this MCP Server built-in.\n\n## Language Server\n\nThe IDE integrations are powered by the Knip Language Server. It builds the full\nmodule graph of your project and provides a session with a graph explorer. See\nthe [Knip Language Server documentation][10] for more details and information on\nintegrating Knip.\n\n## VS Code Extension Screenshots\n\n### Lint Findings\n\n![Lint Findings][11]\n\n### Imports & Exports\n\n![Hover over imports and exports][12]\n\n### Contention\n\nThe extension shows circular dependencies and three kinds of export contention:\nambiguous, shadowed, and converged.\n\n#### Circular Dependencies\n\n![Circular Dependencies][13]\n\n#### Ambiguous\n\nDifferent bindings compete for the same name, with no winner. Knip lists the\ncompeting bindings:\n\n![Ambiguous][14]\n\n#### Shadowed\n\nAn explicit export hides bindings from `export *`. Knip labels the site as\n\"shadowing\" and lists the winning and hidden bindings:\n\n![Shadowed][15]\n\n#### Converged\n\nThe same binding arrives through multiple re-export paths. Knip shows where\nthose paths meet and the binding they share.\n\n![Converged][16]\n\n### Settings\n\n![VS Code Extension Settings][17]\n\n[1]: #vs-code-extension\n[2]: #jetbrains-plugin\n[3]: #mcp-server\n[4]: #language-server\n[5]: https://marketplace.visualstudio.com/items?itemName=webpro.vscode-knip\n[6]: https://open-vsx.org/extension/webpro/vscode-knip\n[7]: #vs-code-extension-screenshots\n[8]: https://plugins.jetbrains.com/plugin/29765-knip\n[9]: https://www.npmx.dev/package/@knip/mcp\n[10]: https://github.com/webpro-nl/knip/blob/main/packages/language-server/README.md\n[11]: /screenshots/editors-and-agents/diagnostics.webp\n[12]: /screenshots/editors-and-agents/imports-exports.webp\n[13]: /screenshots/editors-and-agents/circular-dependency.webp\n[14]: /screenshots/editors-and-agents/ambiguous.webp\n[15]: /screenshots/editors-and-agents/shadow.webp\n[16]: /screenshots/editors-and-agents/branch.webp\n[17]: /screenshots/editors-and-agents/vscode-extension-settings.webp\n","packages/docs/src/content/docs/reference/issue-types.md":"---\ntitle: Issue Types\ndescription: Every issue type Knip reports, from unused files and dependencies to unused exports, enum and namespace members, with their filter keys.\ntableOfContents: false\n---\n\nKnip reports the following types of issues:\n\n| Title                                | Description                                                |       | Key                 |\n| :----------------------------------- | :--------------------------------------------------------- | ----- | :------------------ |\n| Unused files                         | Unable to find a reference to this file                    | 🔧    | `files`             |\n| Unused dependencies                  | Unable to find a reference to this dependency              | 🔧    | `dependencies`      |\n| Unused devDependencies               | Unable to find a reference to this devDependency           | 🔧    | `dependencies`²     |\n| Referenced optional peerDependencies | Optional peer dependency is referenced                     |       | `dependencies`²     |\n| Unlisted dependencies                | Used dependencies not listed in package.json               |       | `unlisted`          |\n| Unlisted binaries                    | Binaries from dependencies not listed in package.json      |       | `binaries`          |\n| Unused catalog entries               | Unable to find a reference to this catalog entry           | 🔧    | `catalog`           |\n| Unresolved catalog references        | Catalog does not contain the referenced package            |       | `catalogReferences` |\n| Unresolved imports                   | Unable to resolve this (import) specifier                  |       | `unresolved`        |\n| Unused exports                       | Unable to find a reference to this export                  | 🔧    | `exports`           |\n| Unused exported types                | Unable to find a reference to this exported type           | 🔧    | `types`             |\n| Exports in used namespace            | Namespace with export is referenced, but not export itself | 🔧 🟠 | `nsExports`         |\n| Exported types in used namespace     | Namespace with type is referenced, but not type itself     | 🔧 🟠 | `nsTypes`           |\n| Unused exported enum members         | Unable to find a reference to this enum member             | 🔧    | `enumMembers`       |\n| Unused exported namespace members    | Unable to find a reference to this namespace member        | 🔧    | `namespaceMembers`  |\n| Duplicate exports                    | This is exported more than once                            |       | `duplicates`        |\n| Circular dependencies                | These files (in)directly import each other at runtime      | 🟠    | `cycles`            |\n\n## Legend\n\n|     | Description                                         |\n| --- | :-------------------------------------------------- |\n| 🔧  | [Auto-fixable][1] issue types                       |\n| 🟠  | Not included by default (include with [filters][2]) |\n\n## Notes\n\n1. When an issue type has zero issues, it is not shown.\n2. Including or excluding `dependencies` (via CLI or configuration)\n   automatically includes or excludes `devDependencies` and\n   `optionalPeerDependencies`. In [rules][3], each key can be set individually.\n3. In [strict production mode][4], `devDependencies` are not included.\n4. The `types` issue type includes `enum`, `interface` and `type` exports.\n5. `cycles` defaults to the `warn` [rule][3] (reported, but not counted as an\n   error). Set `rules.cycles` to `error` to fail on circular dependencies.\n\n[1]: ../features/auto-fix.mdx\n[2]: ../features/rules-and-filters.md#filters\n[3]: ../features/rules-and-filters.md#rules\n[4]: ../features/production-mode.md#strict-mode\n","packages/docs/src/content/docs/reference/jsdoc-tsdoc-tags.md":"---\ntitle: JSDoc & TSDoc Tags\ndescription: Use JSDoc and TSDoc tags like `@public`, `@internal`, `@alias` and custom tags to include or exclude exports from Knip's report.\n---\n\nJSDoc or TSDoc tags can be used to make exceptions for unused or duplicate\nexports.\n\nKnip tries to minimize configuration and introduces no new syntax. That's why it\nhooks into JSDoc and TSDoc tags.\n\n:::caution\n\nAdding tags or excluding a certain type of issues from the report is usually not\nrecommended. It hides issues, which is often a sign of code smell or ambiguity\nand ends up harder to maintain. It's usually better to refactor the code (or\nreport an issue with Knip for false positives).\n\n:::\n\nTags also work in regular block comments (`/* ... */`) and standalone line\ncomments (`// ...`) before a declaration. These comments keep suppression tags\nout of JSDoc hover information.\n\nTags in consecutive comments are combined. Trailing `//` comments are ignored.\n\n## Tags\n\nUse arbitrary [tags][1] to exclude or include tagged exports from the report.\nExample:\n\n```ts\n/** @lintignore */\nexport const myUnusedExport = 1;\n\n// @lintignore\nimport Unresolved from './generated/lib.js';\n```\n\nAnd then include (`+`) or exclude (`-`) these tagged exports from the report\nlike so:\n\n```shell\nknip --tags=-lintignore,-internal\n```\n\nTags can also be [configured in `knip.json`][2].\n\nWhen an excluded tag is no longer necessary because the export is actually used,\nKnip reports a **tag hint**:\n\n```sh\nTag hints (1)\nignored  unimported.ts  Unused tag in unimported.ts: ignored → @custom\n```\n\nThis helps you clean up tags that were added to suppress issues that have since\nbeen resolved.\n\n## `@public`\n\nBy default, Knip reports unused exports in non-entry files.\n\nTag the export as `@public` and Knip will not report it.\n\nExample:\n\n```ts\n/**\n * @public\n */\nexport const unusedFunction = () => {};\n```\n\nThis tag can also be used to make exceptions in entry files when using\n[--include-entry-exports][3].\n\n[JSDoc: @public][4] and [TSDoc: @public][5]\n\n## `@internal`\n\nInternal exports are not meant for public consumption, but only for internal\nusage such as tests. This means they would be reported in [production mode][6].\n\nMark the export with `@internal` and Knip will not report the export in\nproduction mode.\n\nExample:\n\n```ts\n/** @internal */\nexport const internalTestedFunction = () => {};\n```\n\nIn general it's not recommended to expose and test implementation details, but\nexceptions are possible. Those should not be reported as false positives, so\nwhen using production mode you'll need to help Knip out by tagging them as\n`@internal`.\n\n[TSDoc: @internal][7]\n\n## `@alias`\n\nKnip reports duplicate exports. To prevent this, tag one of the exports as\n`@alias`.\n\nExample:\n\n```ts\nexport const Component = () => {};\n\n/** @alias */\nexport default Component;\n```\n\nAn alternative solution is to use `--exclude duplicates` and exclude all\nduplicates from being reported.\n\n[JSDoc: @alias][8]\n\n## `@beta`\n\nWorks identical to [`@public`][9]. Knip ignores other tags like `@alpha` and\n`@experimental`.\n\n[TSDoc: @beta][10]\n\n[1]: ../reference/cli.md#--tags\n[2]: ./configuration.md#tags\n[3]: ./cli.md#--include-entry-exports\n[4]: https://jsdoc.app/tags-public.html\n[5]: https://tsdoc.org/pages/tags/public/\n[6]: ../features/production-mode.md\n[7]: https://tsdoc.org/pages/tags/internal/\n[8]: https://jsdoc.app/tags-alias.html\n[9]: #public\n[10]: https://tsdoc.org/pages/tags/beta/\n","packages/docs/src/content/docs/reference/known-issues.md":"---\ntitle: Known Issues\ndescription: Known limitations and workarounds for caching, config file errors, path aliases in config files, and the Nx daemon.\n---\n\nKnown limitations and workarounds for errors during a Knip run.\n\nSee [handling issues][1] to learn more about dealing with lint issues.\n\n## Exceptions from config files\n\nKnip plugins may fail to load a JavaScript or TypeScript configuration file such\nas `webpack.config.js` or `vite.config.ts`:\n\n```sh\n$ knip\nERROR: Error loading vite.config.ts\n```\n\nKnip exits with code `2` when a plugin config file fails to load.\n`--no-exit-code` does not suppress this error.\n\nKnip may load such files differently, in a different environment, with missing\nenvironment variables, missing path aliases, etcetera. Use `--debug` to locate\nthe cause of the issue with more details.\n\nPotential workarounds:\n\n- For \"Cannot find module\" and \"ENOENT: no such file/dir, open './file'\" errors:\n  - Install dependencies\n  - Use absolute paths, e.g. with `path.join()` or `path.resolve()`\n  - [Set path aliases][2]\n- Set missing environment variable(s), potential solutions:\n  - Use a helper package like [dotenvx][3]\n  - `KEY=VAL knip`\n  - `node --env-file .env $(which knip)`\n- Run the build script to generate required files.\n- Disable loading the file by overriding the default `config` for that plugin.\n  - Example: `vite: { config: [] }`\n  - In a monorepo, be more specific like so: `workspaces: { \"packages/lib\": {\nvite: { config: [] } } }`\n  - If this helps, add the file as an `entry` file for static analysis.\n- Disable the related plugin.\n  - Example: `eslint: false`\n  - In a monorepo, be more specific like so: `workspaces: { \"packages/lib\": {\neslint: false } }`\n  - If this helps, add the file as an `entry` file for static analysis.\n- As a last resort, ignore the workspace: `ignoreWorkspaces: [\"packages/lib\"]`.\n\n## Path aliases in config files\n\nLoading the configuration file (e.g. `cypress.config.ts`) for one of Knip's\nplugins may give an error:\n\n```sh\n$ knip\nAnalyzing workspace ....\nError loading .../cypress.config.ts\nReason: Cannot find module '@alias/name'\nRequire stack:\n- .../cypress.config.ts\n```\n\nSome tools (such as Cypress and Jest) support using TypeScript path aliases in\nthe configuration file.\n\nPotential workarounds:\n\n- Rewrite the import in the configuration file to a relative import.\n- Inject support with a module like `tsx`: `NODE_OPTIONS=\"--import tsx\" knip`\n- Or `tsconfig-paths`: `NODE_OPTIONS=\"--import tsconfig-paths/register.js\" knip`\n- Use Bun with [knip-bun][4].\n- See [exceptions from config files][5] for more potential workarounds.\n\n## Nx Daemon\n\nIn Nx projects you might encounter this error:\n\n```sh\nNX   Daemon process terminated and closed the connection\n```\n\nThe solution is to [disable the Nx Daemon][6]:\n\n```sh\nNX_DAEMON=false knip\n```\n\n## Raw transfer memory errors\n\nOn machines with low RAM or Windows with Node.js >=22, oxc-parser raw transfer\nmay fail under memory pressure:\n\n```sh\nRangeError: Array buffer allocation failed\n```\n\nDisable raw transfer to use the normal parser path:\n\n```sh\nKNIP_DISABLE_RAW_TRANSFER=1 knip\n```\n\n## Stale cache results\n\nWith `--cache`, configuration or path alias changes may leave results stale. An\nimport may still be reported as unresolved after the missing file is added.\nNewly added `.gitignore` files are also not detected automatically.\n\nRun without `--cache` for fresh results, or delete the cache directory\n(`node_modules/.cache/knip` by default, configurable with `--cache-location`)\nbefore running with `--cache` again.\n\n[1]: ../guides/handling-issues.mdx\n[2]: #path-aliases-in-config-files\n[3]: https://dotenvx.com/\n[4]: ./cli.md#knip-bun\n[5]: #exceptions-from-config-files\n[6]: https://nx.dev/concepts/nx-daemon#turning-it-off\n","packages/docs/src/content/docs/reference/plugins.md":"---\ntitle: Plugins (177)\ndescription: 'The full list of Knip plugins for frameworks, build tools, test runners and linters, each linking to its reference page.'\ntableOfContents: false\n---\n\n:::section{.columns.min200}\n\n- [Angular][1]\n- [Astro][2]\n- [Astro DB][3]\n- [Astro Markdoc][4]\n- [astro-og-canvas][5]\n- [Ava][6]\n- [Babel][7]\n- [Biome][8]\n- [bumpp][9]\n- [Bun][10]\n- [c8][11]\n- [Capacitor][12]\n- [Catalyst][13]\n- [Changelogen][14]\n- [Changelogithub][15]\n- [Changesets][16]\n- [Commitizen][17]\n- [commitlint][18]\n- [Convex][19]\n- [create-typescript-app][20]\n- [CSpell][21]\n- [Cucumber][22]\n- [Cypress][23]\n- [Danger][24]\n- [dependency-cruiser][25]\n- [Docusaurus][26]\n- [dotenv][27]\n- [Drizzle][28]\n- [electron-vite][29]\n- [Eleventy][30]\n- [esbuild][31]\n- [ESLint][32]\n- [eve][33]\n- [execa][34]\n- [Expo][35]\n- [Expressive Code][36]\n- [FAST][37]\n- [Fumadocs][38]\n- [Gatsby][39]\n- [GitHub Action][40]\n- [GitHub Actions][41]\n- [glob][42]\n- [GraphQL Codegen][43]\n- [Hardhat][44]\n- [husky][45]\n- [i18next Parser][46]\n- [Jest][47]\n- [Karma][48]\n- [Knex][49]\n- [Ladle][50]\n- [laravel-vite-plugin][51]\n- [Lefthook][52]\n- [lint-staged][53]\n- [LintHTML][54]\n- [Lit][55]\n- [lockfile-lint][56]\n- [Lost Pixel][57]\n- [Lunaria][58]\n- [markdownlint][59]\n- [MDX][60]\n- [mdxlint][61]\n- [Metro][62]\n- [Mocha][63]\n- [moonrepo][64]\n- [Mock Service Worker][65]\n- [nano-spawn][66]\n- [Nano Staged][67]\n- [Nest][68]\n- [Netlify][69]\n- [Next.js][70]\n- [next-intl][71]\n- [Next.js MDX][72]\n- [Nitro][73]\n- [Node.js][74]\n- [node-modules-inspector][75]\n- [nodemon][76]\n- [npm-package-json-lint][77]\n- [Nuxt][78]\n- [@nuxtjs/i18n][79]\n- [Nx][80]\n- [nyc][81]\n- [oclif][82]\n- [openapi-ts][83]\n- [orval][84]\n- [Oxfmt][85]\n- [Oxlint][86]\n- [Panda CSS][87]\n- [Parcel][88]\n- [Payload CMS][89]\n- [pino][90]\n- [Playwright][91]\n- [Playwright for components][92]\n- [playwright-test][93]\n- [Plop][94]\n- [pm2][95]\n- [pnpm][96]\n- [PostCSS][97]\n- [Preconstruct][98]\n- [Prettier][99]\n- [Prisma][100]\n- [Quasar][101]\n- [Qwik][102]\n- [Raycast][103]\n- [React Cosmos][104]\n- [React Email][105]\n- [React Native][106]\n- [React Router][107]\n- [Relay][108]\n- [Release It!][109]\n- [Remark][110]\n- [Remix][111]\n- [Rolldown][112]\n- [Rollup][113]\n- [Rsbuild][114]\n- [Rslib][115]\n- [Rspack][116]\n- [Rstest][117]\n- [Sanity][118]\n- [Semantic Release][119]\n- [Sentry][120]\n- [Serverless Framework][121]\n- [simple-git-hooks][122]\n- [size-limit][123]\n- [SST][124]\n- [Starlight][125]\n- [Stencil][126]\n- [Storybook][127]\n- [Stryker][128]\n- [Stylelint][129]\n- [Svelte][130]\n- [@sveltejs/package][131]\n- [SvelteKit][132]\n- [SVGO][133]\n- [SVGR][134]\n- [SWC][135]\n- [Syncpack][136]\n- [Tailwind][137]\n- [TanStack Router][138]\n- [Taskfile][139]\n- [Tauri][140]\n- [Temporal.io][141]\n- [Travis CI][142]\n- [ts-node][143]\n- [tsdown][144]\n- [tsup][145]\n- [tsx][146]\n- [TypeDoc][147]\n- [TypeScript][148]\n- [unbuild][149]\n- [UnoCSS][150]\n- [unplugin-auto-import][151]\n- [unplugin-icons][152]\n- [unplugin-vue-components][153]\n- [@intlify/unplugin-vue-i18n][154]\n- [unplugin-vue-markdown][155]\n- [unplugin-vue-router][156]\n- [Vercel][157]\n- [Vercel OG][158]\n- [Vike][159]\n- [Vite][160]\n- [vite-plugin-pages][161]\n- [vite-plugin-pwa][162]\n- [vite-plugin-vue-layouts-next][163]\n- [vite-plus][164]\n- [@vite-pwa/assets-generator][165]\n- [VitePress][166]\n- [Vitest][167]\n- [Vue][168]\n- [WebdriverIO][169]\n- [webpack][170]\n- [Wireit][171]\n- [Wrangler][172]\n- [WXT][173]\n- [xo][174]\n- [Yarn][175]\n- [yorkie][176]\n- [zx][177]\n\n:::\n\n[1]: /reference/plugins/angular\n[2]: /reference/plugins/astro\n[3]: /reference/plugins/astro-db\n[4]: /reference/plugins/astro-markdoc\n[5]: /reference/plugins/astro-og-canvas\n[6]: /reference/plugins/ava\n[7]: /reference/plugins/babel\n[8]: /reference/plugins/biome\n[9]: /reference/plugins/bumpp\n[10]: /reference/plugins/bun\n[11]: /reference/plugins/c8\n[12]: /reference/plugins/capacitor\n[13]: /reference/plugins/catalyst\n[14]: /reference/plugins/changelogen\n[15]: /reference/plugins/changelogithub\n[16]: /reference/plugins/changesets\n[17]: /reference/plugins/commitizen\n[18]: /reference/plugins/commitlint\n[19]: /reference/plugins/convex\n[20]: /reference/plugins/create-typescript-app\n[21]: /reference/plugins/cspell\n[22]: /reference/plugins/cucumber\n[23]: /reference/plugins/cypress\n[24]: /reference/plugins/danger\n[25]: /reference/plugins/dependency-cruiser\n[26]: /reference/plugins/docusaurus\n[27]: /reference/plugins/dotenv\n[28]: /reference/plugins/drizzle\n[29]: /reference/plugins/electron-vite\n[30]: /reference/plugins/eleventy\n[31]: /reference/plugins/esbuild\n[32]: /reference/plugins/eslint\n[33]: /reference/plugins/eve\n[34]: /reference/plugins/execa\n[35]: /reference/plugins/expo\n[36]: /reference/plugins/expressive-code\n[37]: /reference/plugins/fast\n[38]: /reference/plugins/fumadocs\n[39]: /reference/plugins/gatsby\n[40]: /reference/plugins/github-action\n[41]: /reference/plugins/github-actions\n[42]: /reference/plugins/glob\n[43]: /reference/plugins/graphql-codegen\n[44]: /reference/plugins/hardhat\n[45]: /reference/plugins/husky\n[46]: /reference/plugins/i18next-parser\n[47]: /reference/plugins/jest\n[48]: /reference/plugins/karma\n[49]: /reference/plugins/knex\n[50]: /reference/plugins/ladle\n[51]: /reference/plugins/laravel-vite-plugin\n[52]: /reference/plugins/lefthook\n[53]: /reference/plugins/lint-staged\n[54]: /reference/plugins/linthtml\n[55]: /reference/plugins/lit\n[56]: /reference/plugins/lockfile-lint\n[57]: /reference/plugins/lost-pixel\n[58]: /reference/plugins/lunaria\n[59]: /reference/plugins/markdownlint\n[60]: /reference/plugins/mdx\n[61]: /reference/plugins/mdxlint\n[62]: /reference/plugins/metro\n[63]: /reference/plugins/mocha\n[64]: /reference/plugins/moonrepo\n[65]: /reference/plugins/msw\n[66]: /reference/plugins/nano-spawn\n[67]: /reference/plugins/nano-staged\n[68]: /reference/plugins/nest\n[69]: /reference/plugins/netlify\n[70]: /reference/plugins/next\n[71]: /reference/plugins/next-intl\n[72]: /reference/plugins/next-mdx\n[73]: /reference/plugins/nitro\n[74]: /reference/plugins/node\n[75]: /reference/plugins/node-modules-inspector\n[76]: /reference/plugins/nodemon\n[77]: /reference/plugins/npm-package-json-lint\n[78]: /reference/plugins/nuxt\n[79]: /reference/plugins/nuxtjs-i18n\n[80]: /reference/plugins/nx\n[81]: /reference/plugins/nyc\n[82]: /reference/plugins/oclif\n[83]: /reference/plugins/openapi-ts\n[84]: /reference/plugins/orval\n[85]: /reference/plugins/oxfmt\n[86]: /reference/plugins/oxlint\n[87]: /reference/plugins/panda-css\n[88]: /reference/plugins/parcel\n[89]: /reference/plugins/payload\n[90]: /reference/plugins/pino\n[91]: /reference/plugins/playwright\n[92]: /reference/plugins/playwright-ct\n[93]: /reference/plugins/playwright-test\n[94]: /reference/plugins/plop\n[95]: /reference/plugins/pm2\n[96]: /reference/plugins/pnpm\n[97]: /reference/plugins/postcss\n[98]: /reference/plugins/preconstruct\n[99]: /reference/plugins/prettier\n[100]: /reference/plugins/prisma\n[101]: /reference/plugins/quasar\n[102]: /reference/plugins/qwik\n[103]: /reference/plugins/raycast\n[104]: /reference/plugins/react-cosmos\n[105]: /reference/plugins/react-email\n[106]: /reference/plugins/react-native\n[107]: /reference/plugins/react-router\n[108]: /reference/plugins/relay\n[109]: /reference/plugins/release-it\n[110]: /reference/plugins/remark\n[111]: /reference/plugins/remix\n[112]: /reference/plugins/rolldown\n[113]: /reference/plugins/rollup\n[114]: /reference/plugins/rsbuild\n[115]: /reference/plugins/rslib\n[116]: /reference/plugins/rspack\n[117]: /reference/plugins/rstest\n[118]: /reference/plugins/sanity\n[119]: /reference/plugins/semantic-release\n[120]: /reference/plugins/sentry\n[121]: /reference/plugins/serverless-framework\n[122]: /reference/plugins/simple-git-hooks\n[123]: /reference/plugins/size-limit\n[124]: /reference/plugins/sst\n[125]: /reference/plugins/starlight\n[126]: /reference/plugins/stencil\n[127]: /reference/plugins/storybook\n[128]: /reference/plugins/stryker\n[129]: /reference/plugins/stylelint\n[130]: /reference/plugins/svelte\n[131]: /reference/plugins/sveltejs-package\n[132]: /reference/plugins/sveltekit\n[133]: /reference/plugins/svgo\n[134]: /reference/plugins/svgr\n[135]: /reference/plugins/swc\n[136]: /reference/plugins/syncpack\n[137]: /reference/plugins/tailwind\n[138]: /reference/plugins/tanstack-router\n[139]: /reference/plugins/taskfile\n[140]: /reference/plugins/tauri\n[141]: /reference/plugins/temporal\n[142]: /reference/plugins/travis\n[143]: /reference/plugins/ts-node\n[144]: /reference/plugins/tsdown\n[145]: /reference/plugins/tsup\n[146]: /reference/plugins/tsx\n[147]: /reference/plugins/typedoc\n[148]: /reference/plugins/typescript\n[149]: /reference/plugins/unbuild\n[150]: /reference/plugins/unocss\n[151]: /reference/plugins/unplugin-auto-import\n[152]: /reference/plugins/unplugin-icons\n[153]: /reference/plugins/unplugin-vue-components\n[154]: /reference/plugins/unplugin-vue-i18n\n[155]: /reference/plugins/unplugin-vue-markdown\n[156]: /reference/plugins/unplugin-vue-router\n[157]: /reference/plugins/vercel\n[158]: /reference/plugins/vercel-og\n[159]: /reference/plugins/vike\n[160]: /reference/plugins/vite\n[161]: /reference/plugins/vite-plugin-pages\n[162]: /reference/plugins/vite-plugin-pwa\n[163]: /reference/plugins/vite-plugin-vue-layouts-next\n[164]: /reference/plugins/vite-plus\n[165]: /reference/plugins/vite-pwa-assets-generator\n[166]: /reference/plugins/vitepress\n[167]: /reference/plugins/vitest\n[168]: /reference/plugins/vue\n[169]: /reference/plugins/webdriver-io\n[170]: /reference/plugins/webpack\n[171]: /reference/plugins/wireit\n[172]: /reference/plugins/wrangler\n[173]: /reference/plugins/wxt\n[174]: /reference/plugins/xo\n[175]: /reference/plugins/yarn\n[176]: /reference/plugins/yorkie\n[177]: /reference/plugins/zx\n","packages/docs/src/content/docs/reference/related-tooling.md":"---\ntitle: Related Tooling\ndescription: Tools that complement Knip for things it does not cover, like unused imports and variables, and unused properties of objects and types.\n---\n\nThis is an overview of related tooling for features Knip does not support.\n\n## Unused imports & variables\n\nKnip doesn't look for unused imports and variables within a file. The focus is\non exported values and types across files.\n\nUse [ESLint][1], [Biome][2] or [oxlint][3] to find unused variables within\nfiles.\n\nUse [remove-unused-vars][4] to remove unused code within files, but in a more\nvaliant way. Using input from any of the above linters, it actually removes a\nlot more unused code. This pairs great with Knip.\n\n## Unused properties\n\nKnip does not yet support finding unused members of types, interfaces and\nobjects. This includes returned objects from exported functions and objects\npassed as React component props.\n\nKnip does support finding unused members of enums and classes, and exported\nvalues and types on imported namespaces.\n\n## Circular dependencies\n\nKnip reports circular dependencies as an opt-in [`cycles`][5] issue type. The\n[editor integrations][6] show cyclic paths directly in IDE.\n\nOther dedicated tools include [DPDM][7], [Madge][8] and [skott][9]. Linters such\nas ESLint have similar plugins and rules, e.g. the `eslint-plugin-import-x`\nplugin has the [import-x/no-cycle][10] and oxlint has the [import/no-cycle][11]\nrule.\n\n## Cleanup\n\nThe [e18e.dev][12] website and in particular the [Cleanup][13] section is a\ngreat resource when dealing with technical debt.\n\n[1]: https://eslint.org\n[2]: https://biomejs.dev/linter/\n[3]: https://oxc.rs/docs/guide/usage/linter.html\n[4]: https://github.com/webpro-nl/remove-unused-vars\n[5]: ./issue-types.md\n[6]: ./integrations.md#circular-dependencies\n[7]: https://github.com/acrazing/dpdm\n[8]: https://github.com/pahen/madge\n[9]: https://github.com/antoine-coulon/skott\n[10]: https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-cycle.md\n[11]: https://oxc.rs/docs/guide/usage/linter/rules/import/no-cycle.html\n[12]: https://e18e.dev\n[13]: https://e18e.dev/guide/cleanup.html\n","packages/docs/src/content/docs/typescript/unused-dependencies.md":"---\ntitle: Unused dependencies\ndescription: Find and remove unused dependencies with Knip\nprev: false\nnext: false\n---\n\nOne of Knip's core features is finding unused dependencies in your JavaScript\nand TypeScript projects. And it comes with many more features to remove clutter\nand keep your projects in great shape.\n\n## Why are unused dependencies a problem?\n\nHaving unused dependencies in your `package.json` is an issue for various\nreasons:\n\n- They might end up in the final production bundle, increasing size and load\n  times for end users.\n- They waste space in `node_modules` and add to the installation time of the\n  project.\n- They slow down tooling such as linters and bundlers that analyze dependencies.\n- They are confusing and noisy in `package.json`.\n- They cause unnecessary extra work when managing and upgrading dependencies.\n- They can cause version conflicts with other dependencies in use.\n- They can cause false security alerts.\n- They might have restrictive licenses and make your project subject to theirs.\n- They usually come with transitive dependencies that have the same issues.\n\n## How do I find unused dependencies?\n\nUse Knip to find and remove unused dependencies. It also finds dependencies that\nare missing in `package.json` and has a lot more features to keep your\nJavaScript and TypeScript projects tidy.\n\nIt's easy to [get started][1] and make package management easier and more fun!\n\n<div style=\"display: flex; justify-content: center; margin: 4rem auto;\">\n  <img src=\"/logo.svg\" alt=\"Logo of Knip, to find unused dependencies, exports and files\" class=\"logo-border\" />\n</div>\n\n## How does Knip identify unused dependencies?\n\nKnip works by analyzing `package.json` files, source code and configuration\nfiles for other tooling in the project to find unused and missing dependencies.\nKnip has many heuristics, [plugins][2] and [compilers][3] to fully automate the\nprocess.\n\n## Can Knip remove unused dependencies?\n\nYes, Knip can automatically remove unused dependencies installed by a package\nmanager like npm or pnpm for you. Add the `--fix` argument to [auto-fix][4] and\nremove unused dependencies from `package.json`.\n\n## Can Knip detect missing dependencies?\n\nYes, Knip detects missing dependencies. It analyzes `package.json` files, and\nreports packages that are missing. They should be added to `package.json` to\navoid relying on transitive dependencies that can cause version mismatches and\nbreakage.\n\n## Does Knip work with monorepos?\n\nYes, Knip has first-class support for [monorepos and workspaces][5]. It analyzes\nall workspaces in the project and understands their relationship.\n\nFor instance, if a dependency is listed in the root `package.json` it does not\nneed to be listed in other workspaces. Except if you enable `--strict` checking.\n\n## Does Knip separate dependencies and devDependencies?\n\nYes, Knip understands the difference between dependencies and devDependencies.\nIt has a [production mode][6] to focus on production code only and find dead\ncode and dependencies that would otherwise only be referenced by tests and other\ntooling. This allows you to remove both unused exported code and their tests.\n\n## Does Knip work with my package manager?\n\nYes, Knip works with any package manager: npm, pnpm, Bun and Yarn are all\nsupported. It's easy to [get started][1] with any package manager.\n\n[1]: ../overview/getting-started.mdx\n[2]: ../reference/plugins.md\n[3]: ../features/compilers.md\n[4]: ../features/auto-fix.mdx\n[5]: ../features/monorepos-and-workspaces.md\n[6]: ../features/production-mode.md\n","packages/docs/src/content/docs/typescript/unused-exports.md":"---\ntitle: Unused exports\ndescription: Find and remove unused exports with Knip\nprev: false\nnext: false\n---\n\nFinding unused exports in your JavaScript and TypeScript projects is one of\nKnip's core features. And it comes with even more features to identify and\nremove clutter to keep your projects in great shape.\n\n## Why are unused exports a problem?\n\nHaving unused exports in your codebase is problematic for several reasons:\n\n- They increase bundle sizes if not properly eliminated by tree-shaking.\n- They clutter the codebase and make it harder to navigate and understand.\n- They mislead developers into thinking certain code is used when it's not.\n- They make refactoring and maintaining the codebase more difficult.\n- They slow down tooling that analyze the codebase, such as bundlers, linters\n  and type checkers.\n- They may represent dead code that is no longer needed but hasn't been cleaned\n  up.\n\n## How do I find unused exports?\n\nKnip is a powerful tool that can help you find and remove unused exports in your\nJavaScript and TypeScript projects. It analyzes the codebase, identifies exports\nthat are not imported anywhere, and reports them.\n\n[Get started and install Knip][1] to run it on your project. Knip will scan your\nfiles and provide a detailed report of unused exports, and much more.\n\n<div style=\"display: flex; justify-content: center; margin: 4rem auto;\">\n  <img src=\"/logo.svg\" alt=\"Logo of Knip, to find unused dependencies, exports and files\" class=\"logo-border\" />\n</div>\n\n## How does Knip identify unused exports?\n\nKnip performs both static and dynamic analysis to determine which exports are\nactually being used in your codebase. It looks at import statements, export\nusage, and [a lot more code patterns][2] to identify unused exports.\n\nKnip supports JavaScript and TypeScript projects, and handles both [CommonJS][3]\nand ES Modules syntax.\n\n## Can Knip remove unused exports?\n\nYes, Knip not only finds unused exports but can also remove them for you. Run\nKnip with the `--fix` flag to enable [the auto-fix feature][4], and it will\nmodify your source code and remove the unused exports.\n\nIt's always recommended to review the changes made by Knip before committing\nthem to ensure no unintended modifications were made.\n\n## Can Knip handle large codebases?\n\nAbsolutely. Knip supports [monorepos with workspaces][5] to efficiently analyze\nlarge monorepos. This makes it easier and more fun to manage and optimize large\nmulti-package projects.\n\n## Does Knip work with my favorite editor or IDE?\n\nKnip is a command-line tool that runs independently of your editor or IDE.\nHowever, if you run Knip inside an integrated IDE terminal, the report contains\nfile names and positions in a format IDEs like VS Code and WebStorm understand\nto easily navigate around.\n\n## How is Knip different from ESLint for finding unused exports?\n\nWhile linters like ESLint can find unused imports and variables within\nindividual files, Knip analyzes the entire project to determine which exports\nare actually unused. By building [a comprehensive module graph][6], Knip\nidentifies exports that are not imported or used anywhere in the codebase. This\nallows Knip to catch unused exports and dead code that ESLint and other linters\nwould miss.\n\nAlso see [Why isn't Knip an ESLint plugin?][7]\n\n[1]: ../overview/getting-started.mdx\n[2]: ../reference/faq.md#what-does-knip-look-for-in-source-files\n[3]: ../guides/working-with-commonjs.md\n[4]: ../features/auto-fix.mdx\n[5]: ../features/monorepos-and-workspaces.md\n[6]: ../reference/faq.md#whats-in-the-graph\n[7]: ../reference/faq.md#why-isnt-knip-an-eslint-plugin\n","packages/docs/src/content/docs/writing-a-plugin/argument-parsing.md":"---\ntitle: Argument Parsing\ndescription: Reference for a Knip plugin `arg` object to parse a tool's command-line arguments and find dependencies and entry files in scripts.\n---\n\nSome plugins have an `arg` object in their implementation. It's a way for\nplugins to customize how command-line arguments are parsed for their tool's\nexecutables. Argument parsing in plugins help Knip identify dependencies and\nentry files from scripts.\n\nKnip parses these arguments with a built-in parser. The options below customize\nhow a tool's scripts are parsed. Here's an example:\n\n```ts\nconst args = {\n  args: (args) => args  // modify/filter the array of raw args\n  config: true,         // shorthand to add `--config [config file]` (and shortcut `-c`) as a `config` file\n  fromArgs: ['exec'],   // re-parse what's behind `exec` as a new script\n};\n\nexport default {\n  title: 'my-plugin',\n  args\n}\n```\n\nAlso see [type definitions][1] and [examples in existing plugins][2].\n\n- [alias][3]\n- [args][4]\n- [binaries][5]\n- [boolean][6]\n- [config][7]\n- [fromArgs][8]\n- [nodeImportArgs][9]\n- [positional][10]\n- [resolve][11]\n- [resolveInputs][12]\n- [string][13]\n\n## alias\n\nDefine aliases.\n\nExample:\n\n```ts\n{\n  require: ['r'];\n}\n```\n\nAlso see [nodeImportArgs][9].\n\n## args\n\nModify or filter arguments before parsing. For edge cases preprocessing is\nuseful, e.g. if the parser has trouble parsing or to modify/discard arguments.\n\nExample:\n\n```ts\n{\n  args: (args: string[]) => args.filter(arg => arg !== 'omit');\n}\n```\n\n## binaries\n\nExecutables for the dependency.\n\nExample:\n\n```ts\n{\n  binaries: ['tsc'];\n}\n```\n\nDefault: plugin name, e.g. for the ESLint plugin the value is `[\"eslint\"]`\n\n## boolean\n\nMark arguments as boolean. By default, arguments are expected to have string\nvalues.\n\n## config\n\nDefine arguments that contain the configuration file path. Usually you'll want\nto set aliases too. Use `true` for shorthand to set `alias` + `string` +\n`config`.\n\nExample:\n\n```ts\n{\n  config: true;\n}\n```\n\nThe `tsup` plugin has this. Now `tsup --config tsup.client.json` will have\n`tsup.client.json` go through `resolveConfig` (also `-c` alias).\n\nExample:\n\n```ts\n{\n  config: ['p'];\n}\n```\n\nThis will mark e.g. `tsc -p tsconfig.lib.json` as a configuration file and it\nwill be handled by `resolveConfig` of the (typescript) plugin.\n\n## fromArgs\n\nParse return value as a new script. Can be a an array of strings, or function\nthat returns an array of strings and those values will be parsed separately.\n\nExample:\n\n```ts\n{\n  fromArgs: ['exec'];\n}\n```\n\nThen this script:\n\n```sh\nnodemon --exec \"node index.js\"\n```\n\nWill have `\"node index.js\"` being parsed as a new script.\n\n## nodeImportArgs\n\nSet to `true` as a shorthand for this [alias][3]:\n\n```ts\n{\n  import: ['r', 'experimental-loader', 'require', 'loader']\n}\n```\n\nExample:\n\n```ts\n{\n  nodeImportArgs: true;\n}\n```\n\n## positional\n\nSet to `true` to use the first positional argument as an entry point.\n\nExample:\n\n```ts\n{\n  positional: true;\n}\n```\n\nThe `tsx` plugin has this and `\"tsx script.ts\"` as a script will result in the\n`script.ts` file being an entry point.\n\n## resolve\n\nList of arguments to resolve to a dependency or entry file path.\n\nExample:\n\n```ts\n{\n  resolve: ['plugin'];\n}\n```\n\nNow for a script like `\"program --plugin package\"` this will result in\n`\"package\"` being resolved as a dependency.\n\n## resolveInputs\n\nReturn inputs from parsed arguments\n\n```ts\n{\n  resolveInputs: (parsed: ParsedArgs) =>\n    parsed['flag'] ? [toDependency('package')] : [];\n}\n```\n\n## string\n\nMark arguments as string. This is the default, but number-looking arguments are\nreturned as numbers.\n\n[1]: https://github.com/webpro-nl/knip/blob/main/packages/knip/src/types/args.ts\n[2]: https://github.com/search?q=repo%3Awebpro-nl%2Fknip++path%3Apackages%2Fknip%2Fsrc%2Fplugins+%22const+args+%3D%22&type=code\n[3]: #alias\n[4]: #args\n[5]: #binaries\n[6]: #boolean\n[7]: #config\n[8]: #fromargs\n[9]: #nodeimportargs\n[10]: #positional\n[11]: #resolve\n[12]: #resolveinputs\n[13]: #string\n","packages/docs/src/content/docs/writing-a-plugin/index.md":"---\ntitle: Writing A Plugin\ndescription: Tutorial for writing a Knip plugin with entry, config, resolveConfig, resolveFromAST and resolve to find entry files and dependencies.\n---\n\nPlugins provide Knip with entry files and dependencies it would be unable to\nfind otherwise. Plugins always do at least one of the following:\n\n1. Define entry file patterns\n2. Find dependencies in configuration files\n\nKnip v5.1.0 introduced a new plugin API, which makes them a breeze to write and\nmaintain.\n\n:::tip[The new plugin API]\n\nEasy things should be easy, and complex things possible.\n\n:::\n\nThis tutorial walks through example plugins so you'll be ready to write your\nown! The following examples demonstrate the elements a plugin can implement.\n\nThere's a handy command available to easily [create a new plugin][1] and get\nstarted right away.\n\n## Example 1: entry\n\nLet's dive right in. Here's the entire source code of the Tailwind plugin:\n\n```ts\nimport type { IsPluginEnabled, Plugin } from '../../types/config.js';\nimport { hasDependency } from '../../util/plugin.js';\n\nconst title = 'Tailwind';\n\nconst enablers = ['tailwindcss'];\n\nconst isEnabled: IsPluginEnabled = ({ dependencies }) =>\n  hasDependency(dependencies, enablers);\n\nconst entry = ['tailwind.config.{js,cjs,mjs,ts}'];\n\nconst plugin: Plugin = {\n  title,\n  enablers,\n  isEnabled,\n  entry,\n};\n\nexport default plugin;\n```\n\nYes, that's the entire plugin! Let's go over each item one by one:\n\n### 1. `title`\n\nThe title of the plugin displayed in the [list of plugins][2] and in debug\noutput.\n\n### 2. `enablers`\n\nAn array of strings to match one or more dependencies in `package.json` so the\n`isEnabled` function can determine whether the plugin should be enabled or not.\nRegular expressions are allowed as well.\n\n### 3. `isEnabled`\n\nThis function checks whether a match is found in the `dependencies` or\n`devDependencies` in `package.json`. The plugin is enabled if the dependency is\nlisted in `package.json`.\n\nThis function can be kept straightforward with the `hasDependency` helper.\n\n### 4. `entry`\n\nThis plugin exports `entry` file patterns. This means that if the Tailwind\nplugin is enabled, then `tailwind.config.*` files are added as entry files. A\nTailwind configuration file does not contain anything particular, so adding it\nas an `entry` to treat it as a regular source file is enough.\n\nThe next example shows how to handle a tool that has its own particular\nconfiguration object.\n\n## Example 2: config\n\nHere's the full source code of the `nyc` plugin:\n\n```ts\nimport { toDeferResolve } from '../../util/input.js';\nimport { hasDependency } from '../../util/plugin.js';\nimport type { NycConfig } from './types.js';\nimport type {\n  IsPluginEnabled,\n  Plugin,\n  ResolveConfig,\n} from '../../types/config.js';\n\nconst title = 'nyc';\n\nconst enablers = ['nyc'];\n\nconst isEnabled: IsPluginEnabled = ({ dependencies }) =>\n  hasDependency(dependencies, enablers);\n\nconst config = [\n  '.nycrc',\n  '.nycrc.{json,yml,yaml}',\n  'nyc.config.js',\n  'package.json',\n];\n\nconst resolveConfig: ResolveConfig<NycConfig> = config => {\n  const extend = config?.extends ?? [];\n  const requires = config?.require ?? [];\n  return [extend, requires].flat().map(id => toDeferResolve(id));\n};\n\nconst plugin: Plugin = {\n  title,\n  enablers,\n  isEnabled,\n  config,\n  resolveConfig,\n};\n\nexport default plugin;\n```\n\nHere's an example `config` file that will be handled by this plugin:\n\n```json title=\".nycrc.json\"\n{\n  \"extends\": \"@istanbuljs/nyc-config-typescript\",\n  \"check-coverage\": true\n}\n```\n\nCompared to the first example, this plugin has two new variables:\n\n### 5. `config`\n\nThe `config` array contains all possible locations of the config file for the\ntool. Knip loads matching files and passes the results (i.e. its default export)\ninto the `resolveConfig` function:\n\n### 6. `resolveConfig`\n\nThis function receives the exported value of the `config` file, and executes the\n`resolveConfig` function with this object. The plugin should return the entry\npaths and dependencies referenced in this object.\n\nKnip supports JSON, YAML, TOML, JavaScript and TypeScript config files. Files\nwithout an extension are provided as plain text strings.\n\n:::tip[Should I implement resolveConfig?]\n\nYou should implement `resolveConfig` if any of these are true:\n\n- The `config` file contains one or more options that represent [entry\n  points][3]\n- The `config` file references dependencies by strings (not import statements)\n\n:::\n\n## Example 3: entry paths\n\n### 7. entry and production\n\nSome tools operate mostly on entry files, some examples:\n\n- Mocha looks for test files at `test/*.{js,cjs,mjs}`\n- Storybook looks for stories at `*.stories.@(mdx|js|jsx|tsx)`\n\nAnd some of those tools allow to configure those locations and patterns in\nconfiguration files, such as `next.config.js` or `vite.config.ts`. If that's the\ncase we can define `resolveConfig` in our plugin to take this from the\nconfiguration object and return it to Knip:\n\nHere's an example from the Mocha plugin:\n\n```ts\nconst entry = ['**/test/*.{js,cjs,mjs}'];\n\nconst resolveConfig: ResolveConfig<MochaConfig> = localConfig => {\n  const entryPatterns = localConfig.spec ? [localConfig.spec].flat() : entry;\n  return entryPatterns.map(id => toEntry(id));\n};\n\nexport default {\n  entry,\n  resolveConfig,\n};\n```\n\nWith Mocha, you can configure `spec` file patterns. The result of implementing\n`resolveConfig` is that users don't need to duplicate this configuration in both\nthe tool (e.g. Mocha) and Knip.\n\nUse `production` entries to target source files that represent production code.\n\n:::tip\n\nRegardless of the presence of `resolveConfig`, add `entry` and `production` to\nthe default export so they will be displayed in the plugin's documentation as\ndefault values.\n\n:::\n\n## Example 4: Use the AST directly\n\nIf the `resolveConfig` function is implemented, Knip loads the configuration\nfile and passes the default-exported object to this plugin function. However,\nthat object might then not contain the information we need.\n\nHere's an example `astro.config.ts` configuration file with a Starlight\nintegration:\n\n```ts\nimport starlight from '@astrojs/starlight';\nimport { defineConfig } from 'astro/config';\n\nexport default defineConfig({\n  integrations: [\n    starlight({\n      components: {\n        Head: './src/components/Head.astro',\n        Footer: './src/components/Footer.astro',\n      },\n    }),\n  ],\n});\n```\n\nWith Starlight, components can be defined to override the default internal ones.\nThey're not otherwise referenced in your source code, so you'd have to manually\nadd them as entry files ([Knip itself did this][4]).\n\nIn the Astro plugin, there's no way to access this object containing\n`components` to add the component files as entry files if we were to try:\n\n```ts\nconst resolveConfig: ResolveConfig<AstroConfig> = async config => {\n  console.log(config); //  ¯\\_(ツ)_/¯\n};\n```\n\nThis is why plugins can implement the `resolveFromAST` function.\n\n### 8. resolveFromAST\n\nLet's take a look at the Astro plugin implementation. This example assumes some\nfamiliarity with Abstract Syntax Trees (AST). Knip provides AST helpers to make\nimplementing plugins more fun and a little less tedious.\n\nAnyway, let's dive in. Here's how we're adding the Starlight `components` paths\nto the default `production` file patterns:\n\n```ts\nimport type { Program } from 'oxc-parser';\nimport {\n  findCallArg,\n  getDefaultImportName,\n  getImportMap,\n  getPropertyValues,\n} from '../../typescript/ast-helpers.ts';\n\nconst title = 'Astro';\n\nconst production = [\n  'src/pages/**/*.{astro,mdx,js,ts}',\n  'src/content/**/*.mdx',\n  'src/middleware.{js,ts}',\n  'src/actions/index.{js,ts}',\n];\n\nconst getComponentPaths = (program: Program) => {\n  const importMap = getImportMap(program);\n  const importName = getDefaultImportName(importMap, '@astrojs/starlight');\n  if (!importName) return new Set<string>();\n  const starlightConfig = findCallArg(program, importName);\n  return getPropertyValues(starlightConfig, 'components');\n};\n\nconst resolveFromAST: ResolveFromAST = (program: Program) => {\n  const componentPaths = getComponentPaths(program);\n  return [...production, ...componentPaths].map(id => toProductionEntry(id));\n};\n\nconst plugin: Plugin = {\n  title,\n  production,\n  resolveFromAST,\n};\n\nexport default plugin;\n```\n\n## None Of The Above\n\n### 9. `resolve`\n\nIf there is no configuration file to parse or there is a need for customization,\nuse `resolve`:\n\n```ts\nconst resolve: Resolve = async options => {\n  return toDependency('troublesome', { optional: true });\n};\n```\n\n## Inputs\n\nYou may have noticed functions like `toDeferResolve` and `toEntry`. They're a\nway for plugins to tell what they've found and how Knip should handle those. The\nmore precision a plugin can provide here, the better results and performance\nwill be.\n\nFind all the details over at [Writing A Plugin → Inputs][5].\n\n## Argument Parsing\n\nAs part of the [script parser][6], Knip parses command-line arguments. Plugins\ncan implement the `arg` object to add custom argument parsing tailored to the\ntool.\n\nRead more in [Writing A Plugin → Argument Parsing][7].\n\n## Create a new plugin\n\nThe easiest way to create a new plugin is to use the `create-plugin` script:\n\n```sh\ncd packages/knip\npnpm create-plugin --name tool\n```\n\nThis adds source and test files and fixtures to get you started. Keep fixtures\ntidy, remove clutter that isn't required to test the plugin properly. E.g. using\na starterkit, script or wizard often creates more than what we need here.\n\nThe script adds the plugin to the JSON Schema and type definitions.\n\nRun the test for your new plugin using one of the following commands:\n\n```sh\nnode --test test/plugins/tool.test.ts\nbun test test/plugins/tool.test.ts\n```\n\nYou're ready to implement and submit a new Knip plugin! 🆕 🎉\n\n## Wrapping Up\n\nFeel free to check out the implementation of other similar plugins, and borrow\nideas and code from those!\n\nThe documentation website takes care of generating the [plugin list and the\nindividual plugin pages][2] from the exported plugin values.\n\nThanks for reading. If you have been following this guide to create a new\nplugin, this might be the right time to open a pull request!\n\n[1]: #create-a-new-plugin\n[2]: ../reference/plugins.md\n[3]: ../explanations/plugins.md#entry-files-from-config-files\n[4]: https://github.com/webpro-nl/knip/blob/6a6954386b33ee8a2919005230a4bc094e11bc03/knip.json#L12\n[5]: ../writing-a-plugin/inputs.md\n[6]: ../features/script-parser.md\n[7]: ../writing-a-plugin/argument-parsing.md\n","packages/docs/src/content/docs/writing-a-plugin/inputs.md":"---\ntitle: Inputs\ndescription: Reference for Knip plugin input functions like toEntry, toDependency, toDeferResolve, toConfig, toBinary and toAlias, plus their options.\n---\n\nYou may have noticed functions like `toDeferResolve` and `toEntry`. They're a\nway for plugins to tell what they've found and how Knip should handle those. The\nmore precise a plugin can be, the better it is for results and performance.\nHere's an overview of all input type functions:\n\n- [toEntry][1]\n- [toProductionEntry][2]\n- [toProject][3]\n- [toDependency][4]\n- [toProductionDependency][5]\n- [toDeferResolve][6]\n- [toDeferResolveEntry][7]\n- [toConfig][8]\n- [toBinary][9]\n- [toAlias][10]\n- [Options][11]\n\n## toEntry\n\nAn `entry` input is just like an `entry` in the configuration. It should either\nbe an absolute or relative path, and glob patterns are allowed.\n\n## toProductionEntry\n\nA production `entry` input is just like an `production` in the configuration. It\nshould either be an absolute or relative path, and it can have glob patterns.\n\n## toProject\n\nA `project` input is the equivalent of `project` patterns in the configuration.\nIt should either be an absolute or relative path, and (negated) glob patterns\nare allowed.\n\n## toDependency\n\nThe `dependency` indicates the entry is a dependency, belonging in either the\n`\"dependencies\"` or `\"devDependencies\"` section of `package.json`. Use it for\npackage names referenced from configuration, such as a plugin or transformer a\ntool loads at build time.\n\nKnip marks the package as referenced, and reports it as an unlisted dependency\nif it isn't listed at all. Such a reference is development-only: in [production\nmode][12] the package is still marked as referenced, but an unlisted one is no\nlonger reported.\n\n## toProductionDependency\n\nThe production `dependency` indicates the entry is a production dependency,\nexpected to be listed in `\"dependencies\"`. Unlike [toDependency][4] it's also\nreported as unlisted in production mode.\n\n## toDeferResolve\n\nThe `deferResolve` input type is used to defer the resolution of a specifier.\nThis could be resolved to a dependency or an entry file. For instance, the\nspecifier `\"input\"` could be resolved to `\"input.js\"`, `\"input.tsx\"`,\n`\"input/index.js\"` or the `\"input\"` package name. Local files are added as entry\nfiles, package names are external dependencies.\n\nIf this does not lead to a resolution, the specifier will be reported under\n\"unresolved imports\".\n\n## toDeferResolveEntry\n\nThe `deferResolveEntry` input type is similar to `deferResolve`, but it's used\nfor entry files only (not dependencies) and unresolved inputs are ignored. It's\ndifferent from `toEntry` as glob patterns are not supported.\n\n## toConfig\n\nThe `config` input type is a way for plugins to reference a configuration file\nthat should be handled by a different plugin. The specifier is a path to that\nfile.\n\nFor instance, `angular.json` has `tsConfig` and `karmaConfig` options pointing\nto files the TypeScript and Karma plugins know how to handle, so the Angular\nplugin hands them over:\n\n```ts\ntoConfig('typescript', 'tsconfig.app.json');\ntoConfig('karma', 'karma.conf.js');\n```\n\n## toBinary\n\nThe `binary` input type isn't used by plugins directly, but by the shell script\nparser (through the `getInputsFromScripts` helper). Think of GitHub Actions\nworkflow YAML files or husky scripts. Using this input type, a binary is\n\"assigned\" to the dependency that has it as a `\"bin\"` in their `package.json`.\n\n## toAlias\n\nThe `alias` input type adds path aliases to the core module resolver. They're\nadded to `compilerOptions.paths` so the syntax is identical.\n\n## Options\n\nWhen creating inputs from specifiers, an extra `options` object as the second\nargument can be provided.\n\n### dir\n\nThe optional `dir` option assigns the input to a different workspace. For\ninstance, GitHub Action workflows are always stored in the root workspace, and\nsupport `working-directory` in job steps. For example:\n\n```yaml\njobs:\n  stylelint:\n    runs-on: ubuntu-latest\n    steps:\n      - run: npx esbuild\n        working-directory: packages/app\n```\n\nThe GitHub Action plugin understands `working-directory` and adds this `dir` to\nthe input:\n\n```ts\ntoDependency('esbuild', { dir: 'packages/app' });\n```\n\nKnip now understands `esbuild` is a dependency of the workspace in the\n`packages/app` directory.\n\n### optional\n\nUse the `optional` flag to indicate the dependency is optional. Then, a\ndependency won't be flagged as unlisted if it isn't.\n\n### isTypeOnly\n\nUse `isTypeOnly` when only the types of a package are used, such as the packages\nlisted in `compilerOptions.types`. A `@types/pkg` dependency then satisfies the\nreference on its own, without `pkg` itself being installed. Don't use it for\npackages the tool actually loads, even if it does so only at build time.\n\n### allowIncludeExports\n\nBy default, exports of entry files such as `src/index.ts` or the files in\n`package.json#exports` are not reported as unused. When using the\n`--include-entry-exports` flag or `isIncludeExports: true` option, unused\nexports on such entry files are also reported.\n\nExports of entry files coming from plugins are not included in the analysis,\neven with the option enabled. This is because certain tools and frameworks\nconsume named exports from entry files, causing false positives.\n\nThe `allowIncludeExports` option allows the exports of entry files to be\nreported as unused when using `--include-entry-exports`. This option is\ntypically used with the [toProductionEntry][2] input type.\n\nExample:\n\n```ts\ntoProductionEntry('./entry.ts', { allowIncludeExports: true });\n```\n\n[1]: #toentry\n[2]: #toproductionentry\n[3]: #toproject\n[4]: #todependency\n[5]: #toproductiondependency\n[6]: #todeferresolve\n[7]: #todeferresolveentry\n[8]: #toconfig\n[9]: #tobinary\n[10]: #toalias\n[11]: #options\n[12]: ../features/production-mode.md\n","packages/docs/tsconfig.json":"{\n  \"extends\": \"astro/tsconfigs/strict\"\n}\n","packages/knip/README.md":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fknip%2FREADME.md -->","packages/language-server/README.md":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Flanguage-server%2FREADME.md -->","packages/mcp-server/README.md":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fmcp-server%2FREADME.md -->","packages/vscode-knip/README.md":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fvscode-knip%2FREADME.md -->"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Knip\n\nKnip is a tool to find and fix unused dependencies, exports and files in\nJavaScript and TypeScript projects.\n\n## Project overview\n\n- Monorepo, managed with pnpm\n- Main package is core in `packages/knip` (TypeScript)\n- Language Server in `packages/language-server` (JS + JSDoc for types)\n- VS Code Extension in `packages/vscode-knip` (JS + JSDoc for types)\n- [Documentation][1] content in `packages/docs` (Astro + MD/MDX)\n- Tracked `.agents` guides live in the checkout; there might be shared lessons and tasks in the workspace's `.agents`.\n\n## Code style\n\n- Performance is key, both high level (design) and low level (impl).\n- Avoid redundant code and abstractions; avoid unnecessary complexity and nesting.\n- Concise one-liners are fine, but prioritize clarity over cleverness.\n- Don't add comments to code, unless explicitly asked for.\n- Prefer AST-based tools and codemods (jscodeshift) over manual or regex-based refactors — except for tiny edits.\n- JavaScript\n  - Prefer plain `for..in/of` loops over iterator methods like `map`/`reduce`.\n- TypeScript\n  - Avoid `any` and type casting (`as`).\n  - Avoid runtime overhead just to get the types right.\n- Lint and check formatting from root: `pnpm run ci`; format with `pnpm fmt`\n- Format Markdown/MDX with `pnpm remark` in `packages/docs` (auto-numbers link refs, validates links)\n\n## Domain Knowledge\n\n- Unused file → unused exports/dependencies is a chain, not a bug\n- Non-JS/TS files (.css, .mdx, .vue) enter the graph via (usually plugin-registered) compilers (`registerCompilers`)\n- Library-specific AST patterns are caught by plugin-registered visitors (`registerVisitors`)\n- Use `--performance` or `--performance-fn [name]` to profile (→ [timerify][2])\n- If creating, modifying, or reviewing a plugin, read [PLUGINS.md][3] first.\n- If modifying core module graph, AST traversal, or CLI sequence, read [MODULE-GRAPH.md][4] first.\n- For issues re. exported identifiers (following refs, shadowing, `ignoreExportsUsedInFile`), see [EXPORTS.md][5].\n- Before any significant performance tuning, consult [PERFORMANCE.md][6].\n- When modifying or reviewing built-in compilers, read [COMPILERS.md][10].\n- For test/fixture structure, conventions, and where a new test goes, see [TESTS.md][7].\n\n## Issues and Pull Requests\n\n- Use `gh` for PR metadata, diffs, comments, and checks. Reuse retrieved evidence; browse upstream documentation separately.\n- When given a bug report, first confirm the behavior is actually wrong. Reproduce, then check if the reported behavior is correct-by-design before writing any fix.\n- Find repositories/CodeSandbox/StackBlitz source files and local fixtures to actually reproduce the issue at hand.\n- To fetch a stackblitz.com reproduction: `pnpx stackblitz-zip https://stackblitz.com/edit/{name} {filename}.zip`\n- For a fix, revert the source change and confirm the new test fails for the reported reason.\n- For a new plugin or a change in how a tool finds files, verify against the tool's source, not only its docs, and run Knip on the tool's examples or starters when available.\n- Follow the [AI contribution policy][11]: before opening an issue or PR, make sure the person you work for understands and stands behind it. Keep descriptions concise.\n\n## Run & Debug\n\nImportant: debug, don't guess.\n\nRun the CLI directly using `node` or `bun`. This document shows `knip` in\ncommands for consistency. Replace it with `node (path/to/)src/cli.ts` or\n`bun (path/to/)src/cli.ts` and keep using what works.\n\n- Run `knip` directly in a fixture or temp directory (over creating test scripts that import the `main` function).\n- Knip requires `package.json` in root dir.\n- Enable [debug & helpers][8] with `--debug` (not `DEBUG=`). Warning: noisy.\n- Use [trace][9] to debug\n  - exported identifiers (`knip --trace-export [name] --trace-file [file]`)\n  - external dependencies (`knip --trace-dependency [name] --workspace [dir]`)\n\n## Test\n\nPrefer TDD: add or update tests (and fixtures) before implementing.\n\nPrefer `bun` over `node` for speed. Don't run all tests at once (slow & noisy).\nStart out with running the relevant test(s) first:\n\n```sh\ncd packages/knip\nbun test test/util/get-inputs-from-scripts.test.ts\nnode --test test/commonjs.test.ts\n```\n\nRun smoke tests with Bun:\n\n```sh\ncd packages/knip\npnpm test --runtime bun --smoke\n```\n\nRun smoke tests with Node.js:\n\n```sh\ncd packages/knip\nnode --test test/commonjs.test.ts\npnpm test --runtime node --smoke\n```\n\nBuild core package and run all tests only if there are changes in auto-fix,\nformatting and reporter related functionality:\n\n```sh\ncd packages/knip\npnpm build\npnpm test\n```\n\nSee [TESTS.md][7] for test and fixture conventions and placements.\n\n## Build\n\nTo type-check `knip` with `tsc`:\n\n```sh\ncd packages/knip\npnpm build\n```\n\n[1]: https://knip.dev\n[2]: ./packages/knip/src/util/Performance.ts\n[3]: ./.agents/PLUGINS.md\n[4]: ./.agents/MODULE-GRAPH.md\n[5]: ./.agents/EXPORTS.md\n[6]: ./.agents/PERFORMANCE.md\n[7]: ./.agents/TESTS.md\n[8]: ./packages/knip/src/util/debug.ts\n[9]: ./packages/docs/src/content/docs/guides/troubleshooting.md#trace\n[10]: ./.agents/COMPILERS.md\n[11]: ./AI_POLICY.md\n","isInternal":false,"tokens":1330,"sizeBytes":5135},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"AGENTS.md","isInternal":false,"tokens":3,"sizeBytes":9},{"name":"copilot-instructions.md","path":".github/copilot-instructions.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/.github/copilot-instructions.md","title":"GitHub Copilot Instructions","category":"copilot-instructions","format":"markdown","content":"See [AGENTS.md][1].\n\n[1]: ../AGENTS.md\n","isInternal":false,"tokens":16,"sizeBytes":39},{"name":"contributors.json","path":"packages/docs/mock/contributors.json","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/mock/contributors.json","title":"Mock Skill","category":"anthropic-skill","format":"json","content":"[\n  {\n    \"login\": \"webpro\",\n    \"id\": 456426,\n    \"node_id\": \"MDQ6VXNlcjQ1NjQyNg==\",\n    \"avatar_url\": \"https://avatars.githubusercontent.com/u/456426?v=4\",\n    \"gravatar_id\": \"\",\n    \"url\": \"https://api.github.com/users/webpro\",\n    \"html_url\": \"https://github.com/webpro\",\n    \"followers_url\": \"https://api.github.com/users/webpro/followers\",\n    \"following_url\": \"https://api.github.com/users/webpro/following{/other_user}\",\n    \"gists_url\": \"https://api.github.com/users/webpro/gists{/gist_id}\",\n    \"starred_url\": \"https://api.github.com/users/webpro/starred{/owner}{/repo}\",\n    \"subscriptions_url\": \"https://api.github.com/users/webpro/subscriptions\",\n    \"organizations_url\": \"https://api.github.com/users/webpro/orgs\",\n    \"repos_url\": \"https://api.github.com/users/webpro/repos\",\n    \"events_url\": \"https://api.github.com/users/webpro/events{/privacy}\",\n    \"received_events_url\": \"https://api.github.com/users/webpro/received_events\",\n    \"type\": \"User\",\n    \"site_admin\": false,\n    \"contributions\": 1282\n  }\n]\n","isInternal":false,"tokens":291,"sizeBytes":1024},{"name":"package.json","path":"packages/docs/package.json","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/package.json","title":"@knip/docs","category":"anthropic-skill","format":"json","content":"{\n  \"name\": \"@knip/docs\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"description\": \"Documentation for Knip, hosted at knip.dev\",\n  \"homepage\": \"https://knip.dev\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"github:webpro-nl/knip\",\n    \"directory\": \"packages/docs\"\n  },\n  \"type\": \"module\",\n  \"scripts\": {\n    \"prebuild\": \"node ./scripts/generate-plugin-docs.ts\",\n    \"build\": \"astro check && astro build\",\n    \"postbuild\": \"[ \\\"$CF_PAGES\\\" = \\\"1\\\" ] && find dist -mindepth 2 -type f -name 'index.html' -exec bash -c 'f=\\\"$1\\\"; d=$(dirname \\\"$f\\\"); bn=$(basename \\\"$d\\\"); mv -v \\\"$f\\\" \\\"$d/../$bn.html\\\"' _ {} \\\\; && find dist -mindepth 1 -type d -empty -print -delete || true\",\n    \"dev\": \"astro dev\",\n    \"remark\": \"remark README.md 'src/content/docs/**/*.md' --verbose -o && mdxlint 'src/content/docs/**/*.mdx' --verbose -o\"\n  },\n  \"dependencies\": {\n    \"@astro-community/astro-embed-youtube\": \"0.5.10\",\n    \"@astrojs/starlight\": \"0.42.6\",\n    \"@octokit/graphql\": \"^9.0.5\",\n    \"astro\": \"7.3.8\",\n    \"sharp\": \"0.35.5\"\n  },\n  \"devDependencies\": {\n    \"@astrojs/check\": \"0.9.10\",\n    \"@astrojs/markdown-satteri\": \"0.4.3\",\n    \"picocolors\": \"^1.1.1\",\n    \"satteri\": \"0.10.5\",\n    \"starlight-blog\": \"^0.30.2\",\n    \"typescript\": \"6.0.3\"\n  },\n  \"engines\": {\n    \"node\": \">=22.12.0\"\n  }\n}\n","frontmatter":{"name":"@knip/docs","version":"0.0.0","private":true,"description":"Documentation for Knip, hosted at knip.dev","homepage":"https://knip.dev","repository":{"type":"git","url":"github:webpro-nl/knip","directory":"packages/docs"},"type":"module","scripts":{"prebuild":"node ./scripts/generate-plugin-docs.ts","build":"astro check && astro build","postbuild":"[ \"$CF_PAGES\" = \"1\" ] && find dist -mindepth 2 -type f -name 'index.html' -exec bash -c 'f=\"$1\"; d=$(dirname \"$f\"); bn=$(basename \"$d\"); mv -v \"$f\" \"$d/../$bn.html\"' _ {} \\; && find dist -mindepth 1 -type d -empty -print -delete || true","dev":"astro dev","remark":"remark README.md 'src/content/docs/**/*.md' --verbose -o && mdxlint 'src/content/docs/**/*.mdx' --verbose -o"},"dependencies":{"@astro-community/astro-embed-youtube":"0.5.10","@astrojs/starlight":"0.42.6","@octokit/graphql":"^9.0.5","astro":"7.3.8","sharp":"0.35.5"},"devDependencies":{"@astrojs/check":"0.9.10","@astrojs/markdown-satteri":"0.4.3","picocolors":"^1.1.1","satteri":"0.10.5","starlight-blog":"^0.30.2","typescript":"6.0.3"},"engines":{"node":">=22.12.0"}},"isInternal":false,"tokens":454,"sizeBytes":1289},{"name":"manifest.json","path":"packages/docs/public/manifest.json","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/public/manifest.json","title":"Knip","category":"anthropic-skill","format":"json","content":"{\n  \"name\": \"Knip\",\n  \"short_name\": \"Knip\",\n  \"icons\": [\n    {\n      \"src\": \"/favicon.svg\",\n      \"type\": \"image/svg+xml\",\n      \"sizes\": \"512x512\"\n    },\n    {\n      \"src\": \"/icon-192x192.png\",\n      \"sizes\": \"192x192\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icon-512x512.png\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/png\"\n    }\n  ],\n  \"theme_color\": \"#fbfbfb\",\n  \"background_color\": \"#f56e0f\",\n  \"display\": \"standalone\",\n  \"scope\": \"/\",\n  \"start_url\": \"/overview/getting-started/\"\n}\n","frontmatter":{"name":"Knip","short_name":"Knip","icons":[{"src":"/favicon.svg","type":"image/svg+xml","sizes":"512x512"},{"src":"/icon-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/icon-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#fbfbfb","background_color":"#f56e0f","display":"standalone","scope":"/","start_url":"/overview/getting-started/"},"isInternal":false,"tokens":170,"sizeBytes":507},{"name":"testimonials.json","path":"packages/docs/src/assets/testimonials.json","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/assets/testimonials.json","title":"Assets Skill","category":"anthropic-skill","format":"json","content":"{\n  \"data\": [\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"2061954856638967917\",\n      \"author_id\": \"5\",\n      \"created_at\": \"2026-06-02T23:35:21.000Z\",\n      \"text\": \"Knip is still my all time favorite piece of software.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"2061775207518343569\",\n      \"author_id\": \"20\",\n      \"created_at\": \"2026-06-02T11:41:30.000Z\",\n      \"text\": \"adding knip to our CI after deleting like 100k LOC of dead code was a game changer\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3mn5ccucpvk2z\",\n      \"author_id\": \"13\",\n      \"created_at\": \"2026-05-31T09:54:50.000Z\",\n      \"text\": \"Knip is essential tooling.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"2059921462891622770\",\n      \"author_id\": \"21\",\n      \"created_at\": \"2026-05-28T08:55:22.000Z\",\n      \"text\": \"Please dont ask your ai agent to find unused, dead code and remove them. Instead for js/ts projects install knip and see the magic it does. Save tokens🙏😂\"\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webpro.nl\"\n          }\n        ],\n        \"urls\": []\n      },\n      \"id\": \"3mgkwe4digs2l\",\n      \"author_id\": \"19\",\n      \"created_at\": \"2026-03-25T12:00:00.000Z\",\n      \"text\": \"Two things about knip.dev I don't get:\\n- how did we live without it for so long\\n- how did @webpro.nl NAIL the timing? Gave it to us right when AI started to produce left-overs in our codes faster than we ever could.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"cdn.bsky.app/img/dummy-02\",\n            \"display_url\": \"cdn.bsky.app/img/julien.deniau.me\",\n            \"media_key\": \"4\"\n          }\n        ]\n      },\n      \"id\": \"3mdrubg3y5c2z\",\n      \"author_id\": \"11\",\n      \"created_at\": \"2026-02-01T07:57:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Done on a mono-repo in two times.\\nWhat's impressive is that there were no false positive!\\ncdn.bsky.app/img/dummy-02\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/EwIeRiHaXf\",\n            \"display_url\": \"pic.x.com/EwIeRiHaXf\",\n            \"media_key\": \"6\"\n          }\n        ]\n      },\n      \"id\": \"2017122504914161979\",\n      \"author_id\": \"16\",\n      \"created_at\": \"2026-01-30T06:27:00.000Z\",\n      \"text\": \"Good morning 🌄\\nA tool I discovered lately.\\nIf you care about clean codebases, this one's a gem 💎\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3mcky5ps3r22p\",\n      \"author_id\": \"12\",\n      \"created_at\": \"2026-01-16T20:53:09.000Z\",\n      \"text\": \"Knip is a cracking-looking open source tool for trimming unused JavaScript.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"cdn.bsky.app/img/dummy-03\",\n            \"display_url\": \"cdn.bsky.app/img/patak.dev\",\n            \"media_key\": \"5\"\n          }\n        ]\n      },\n      \"id\": \"3mcjtmv35wc2y\",\n      \"author_id\": \"15\",\n      \"created_at\": \"2026-01-16T09:59:29.000Z\",\n      \"attachments\": {},\n      \"text\": \"From the report, we could improve the situation if we stop sending unused JavaScript. @webpro.nl is doing an incredible job growing the usage of knip.dev, and that should hopefully make a dent in the future.\\ncdn.bsky.app/img/dummy-03\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://knip.dev/blog/for-editors-and-agents\",\n            \"expanded_url\": \"https://knip.dev/blog/for-editors-and-agents\",\n            \"display_url\": \"knip.dev/blog/for-edi...\"\n          }\n        ]\n      },\n      \"id\": \"3mby3zkzhfs2t\",\n      \"author_id\": \"13\",\n      \"created_at\": \"2026-01-09T08:41:49.000Z\",\n      \"text\": \"The VSCode/Cursor extension is ace!\\nAnd you can use the Knip MCP to create the config file.\\nIt works for Svelte as well.\\nKnip is really really good 🙏\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/6rcslWBqIV\",\n            \"display_url\": \"pic.x.com/6rcslWBqIV\",\n            \"media_key\": \"6\"\n          }\n        ]\n      },\n      \"id\": \"2007481125610914217\",\n      \"author_id\": \"17\",\n      \"created_at\": \"2026-01-03T15:56:00.000Z\",\n      \"attachments\": { \"media_keys\": [\"6\"] },\n      \"text\": \"This is both embarrassing and satisfying after running @Knip https://t.co/6rcslWBqIV\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/hneEWMqdnm\",\n            \"expanded_url\": \"https://knip.dev\",\n            \"display_url\": \"Knip.dev\"\n          }\n        ]\n      },\n      \"id\": \"2007221517562904675\",\n      \"author_id\": \"18\",\n      \"created_at\": \"2026-01-02T23:44:00.000Z\",\n      \"text\": \"You can't spell Opus without https://t.co/hneEWMqdnm\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3mbggqrihuk2r\",\n      \"author_id\": \"14\",\n      \"created_at\": \"2026-01-02T08:05:50.000Z\",\n      \"text\": \"Knip is amazing and you should be using it.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3lvwax6bemc22\",\n      \"author_id\": \"22\",\n      \"created_at\": \"2025-08-08T22:02:18.000Z\",\n      \"text\": \"Just used `npx knip` to find my unused files, components, and packages and 😱! So cool. \\n\\nHow have I not come across it before?\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1932778410691949034\",\n      \"author_id\": \"10\",\n      \"created_at\": \"2025-06-11T14:34:00.000Z\",\n      \"text\": \"\\\"Thanks Knip!\\\"\\neveryday,\\nevery team member,\\nliterally..\\nknip.dev 🏅\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"url\": \"https://github.com/webpro-nl/knip/issues/1120#issuecomment-2943978262\",\n      \"author_id\": \"9\",\n      \"created_at\": \"2025-06-05T14:00:00.000Z\",\n      \"text\": \"Thank you so much for this incredible piece of software! Knip is one of the most impressive tools I've seen in my career.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://github.com/webpro-nl/knip/pull/1022\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip/pull/1022\",\n            \"display_url\": \"https://github.com/webpro-nl/knip/pull/1022\",\n            \"title\": \"feat: add create-typescript-app plugin\",\n            \"description\": \"feat: add create-typescript-app plugin\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip/pull/1022\"\n          }\n        ]\n      },\n      \"id\": \"3lmhgsj2n622o\",\n      \"author_id\": \"7\",\n      \"created_at\": \"2025-04-10T13:50:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Got my first plugin merged into Knip by @webpro.nl today! ☺️\\n\\nThe contribution experience was fantastic: the docs were super clear, the code was straightforward to navigate, and the helper script to generate a new plugin got me 90% of the way there. Awesome. Thanks Lars!\\n\\nhttps://github.com/webpro-nl/knip/pull/1022\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1904580358307250634\",\n      \"author_id\": \"6\",\n      \"created_at\": \"2025-03-25T18:05:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"All of the TanStack monorepos make use of knip.dev\\n\\nIt's like eslint for detecting unused dependencies or even your own files/modules.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"cdn.bsky.app/img/dummy-01\",\n            \"display_url\": \"cdn.bsky.app/img/opw3iapscc55nlgrx6q2yjah\",\n            \"media_key\": \"2\"\n          }\n        ]\n      },\n      \"id\": \"3ll5ioywml223\",\n      \"author_id\": \"8\",\n      \"created_at\": \"2025-03-24T20:32:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"The joy of adding knip.dev (by @webpro.nl) on a codebase! Right in time for spring cleaning 🧹🍃\\ncdn.bsky.app/img/dummy-01\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1874692207472726401\",\n      \"author_id\": \"5\",\n      \"created_at\": \"2025-01-02T06:40:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Knip helped us delete ~300k lines of unused code at Vercel.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/kA81p5gkmP\",\n            \"expanded_url\": \"https://www.npmx.dev/package/knip\",\n            \"display_url\": \"npmx.dev/package/knip\",\n            \"title\": \"Knip\",\n            \"description\": \"Find unused dependencies, exports and files in your TypeScript and JavaScript projects.\",\n            \"unwound_url\": \"https://www.npmx.dev/package/knip\"\n          }\n        ]\n      },\n      \"id\": \"1850975288362221628\",\n      \"author_id\": \"5\",\n      \"created_at\": \"2024-10-28T19:57:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Knip may be the greatest tool ever conceived.\\nhttps://t.co/kA81p5gkmP\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3k3obqi65oy2p\",\n      \"author_id\": \"4\",\n      \"created_at\": \"2023-07-29T17:33:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"`knip` is the best code maintenance tool I've used in my 20 years of development, just an absolute work of art\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1808672067900092505\",\n      \"author_id\": \"3\",\n      \"created_at\": \"2024-07-04T03:19:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"knip is great.\\n\\nA great example of stuff just working. It detects your environment so well and its defaults are almost too good because I didn’t realise it was doing everything automatically.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1808808208229707835\",\n      \"author_id\": \"3\",\n      \"created_at\": \"2024-07-04T12:20:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Then was like “this is how tooling should be, this has taken me an hour not a day and it’s faster and more accurate and more future proof”\\n\\nFive stars ⭐️⭐️⭐️⭐️⭐️\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1803013555907698921\",\n      \"author_id\": \"2\",\n      \"created_at\": \"2024-06-18T12:35:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Crazy useful tool. Thought it would be a nightmare to setup in my Next.js+Workers repo but it has crazy good automatic detection for code dependencies. In short, Knip creates a graph of code use and highlights dead code for you to snip (knip).\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1793913676896031033\",\n      \"author_id\": \"44217212\",\n      \"created_at\": \"2024-05-24T09:55:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Lars is singlehandedly building the best tool to keep your code clean and your dependencies minimal. And he's so engaging and helpful. Can't imagine going back to not using knip 👏\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/dummy-01\",\n            \"display_url\": \"pic.twitter.com/uOuO1ch5ij\",\n            \"media_key\": \"1\"\n          }\n        ]\n      },\n      \"id\": \"1745972825490604506\",\n      \"author_id\": \"1\",\n      \"created_at\": \"2024-01-13T01:55:00.000Z\",\n      \"attachments\": { \"media_keys\": [\"1\"] },\n      \"text\": \"warning: do not use a tool like knip.dev + code search to delete a ton of unused code. It works too well.\\n\\nI just did this in https://github.com/sourcegraph/cody/pull/2705, and my boss said if I end the week with net negative lines of code committed, I'm in deep trouble. https://t.co/dummy-01\"\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"argos_ci\",\n            \"id\": \"1554000987022663681\"\n          },\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"annotations\": [\n          {\n            \"probability\": 0.6699,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Prettier\"\n          },\n          {\n            \"probability\": 0.7586,\n            \"type\": \"Other\",\n            \"normalized_text\": \"ESLint\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/uOuO1ch5ij\",\n            \"expanded_url\": \"https://twitter.com/gregberge_/status/1730180003453927560/photo/1\",\n            \"display_url\": \"pic.twitter.com/uOuO1ch5ij\",\n            \"media_key\": \"3_1730179997682552832\"\n          }\n        ]\n      },\n      \"author_id\": \"22918124\",\n      \"text\": \"Ran knip.dev in @argos_ci, and boom 💥! Dead code detected instantly. With a good config, it can run on CI to keep projects clean. Installing this tool should be a no-brainer, like Prettier or ESLint.\\n\\nKudos, @webprolific! 👏 https://t.co/uOuO1ch5ij\",\n\n      \"id\": \"1730180003453927560\",\n      \"created_at\": \"2023-11-30T11:00:32.000Z\",\n      \"edit_history_tweet_ids\": [\"1730180003453927560\"],\n      \"attachments\": { \"media_keys\": [\"3_1730179997682552832\"] }\n    },\n    {\n      \"note_tweet\": {\n        \"text\": \"Problem: \\n🚫 Your project has unused files.\\n🚫 It has unused npm dependencies.\\n🚫 It has unused TypeScript exports.\\n\\nBut you haven't noticed, because these things are hard to spot.\\n\\nSolution: knip\\n\\nI just used knip to find and resolve dozens of issues.\\n\\nhttps://t.co/QmN3sNlmbm\",\n        \"entities\": {\n          \"urls\": [\n            {\n              \"url\": \"https://t.co/QmN3sNlmbm\",\n              \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n              \"display_url\": \"github.com/webpro-nl/knip\"\n            }\n          ]\n        }\n      },\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.8569,\n            \"type\": \"Other\",\n            \"normalized_text\": \"TypeScript\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/grbeTqMtt6\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n            \"display_url\": \"github.com/webpro-nl/knip\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig\",\n                \"width\": 1280,\n                \"height\": 640\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!\",\n            \"description\": \"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip\"\n          },\n          {\n            \"url\": \"https://t.co/qaOXBlD3eo\",\n            \"expanded_url\": \"https://twitter.com/i/web/status/1691460974518353920\",\n            \"display_url\": \"twitter.com/i/web/status/1…\"\n          }\n        ]\n      },\n      \"author_id\": \"19268321\",\n      \"text\": \"Problem: \\n🚫 Your project has unused files.\\n🚫 It has unused npm dependencies.\\n🚫 It has unused TypeScript exports.\\n\\nBut you haven't noticed, because these things are hard to spot.\\n\\nSolution: knip\\n\\nI just used knip to find and resolve dozens of issues.\\n\\nhttps://t.co/grbeTqMtt6 https://t.co/qaOXBlD3eo\",\n\n      \"id\": \"1691460974518353920\",\n      \"created_at\": \"2023-08-15T14:44:56.000Z\",\n      \"edit_history_tweet_ids\": [\"1691460974518353920\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"annotations\": [\n          {\n            \"probability\": 0.6322,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ]\n      },\n      \"author_id\": \"3126044440\",\n      \"text\": \"@webprolific Knip helped me get rid of over 41k lines of code in legacy codebase 🥺🥺💕\",\n\n      \"id\": \"1729181106715632088\",\n      \"created_at\": \"2023-11-27T16:51:17.000Z\",\n      \"edit_history_tweet_ids\": [\"1729181106715632088\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"contra\",\n            \"id\": \"973313523790082053\"\n          }\n        ],\n        \"annotations\": [\n          {\n            \"probability\": 0.8474,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/UgCunYQWzu\",\n            \"expanded_url\": \"https://twitter.com/webprolific/status/1729105865683435542\",\n            \"display_url\": \"twitter.com/webprolific/st…\"\n          }\n        ]\n      },\n      \"author_id\": \"95668959\",\n      \"text\": \"Big fans of Knip at @Contra. Such an extremely well developed and maintained project https://t.co/UgCunYQWzu\",\n\n      \"id\": \"1729157761215369264\",\n      \"created_at\": \"2023-11-27T15:18:31.000Z\",\n      \"edit_history_tweet_ids\": [\"1729157761215369264\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/ZUYYdvkBJc\",\n            \"expanded_url\": \"https://github.com/getsentry/sentry/\",\n            \"display_url\": \"github.com/getsentry/sent…\",\n            \"title\": \"GitHub - getsentry/sentry: Developer-first error tracking and performance monitoring\",\n            \"description\": \"Developer-first error tracking and performance monitoring - GitHub - getsentry/sentry: Developer-first error tracking and performance monitoring\",\n            \"unwound_url\": \"https://github.com/getsentry/sentry/\"\n          }\n        ]\n      },\n      \"author_id\": \"1632752318994153472\",\n      \"text\": \"@webprolific Just tried this on https://t.co/ZUYYdvkBJc - got some super useful results! Nice work.\",\n\n      \"id\": \"1727040036334424406\",\n      \"created_at\": \"2023-11-21T19:03:26.000Z\",\n      \"edit_history_tweet_ids\": [\"1727040036334424406\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          { \"username\": \"TkDodo\", \"id\": \"44217212\" },\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          },\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ]\n      },\n      \"author_id\": \"1513218780167655427\",\n      \"text\": \"@TkDodo @webprolific I've manage to delete 6k LOC in the last 30 minutes 🫣\\n\\nGreat job here @webprolific 👍🏽\",\n\n      \"id\": \"1726807293583609935\",\n      \"created_at\": \"2023-11-21T03:38:35.000Z\",\n      \"edit_history_tweet_ids\": [\"1726807293583609935\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/Tg5E6C7gqa\",\n            \"expanded_url\": \"https://twitter.com/housecor/status/1713975785273303286\",\n            \"display_url\": \"twitter.com/housecor/statu…\"\n          }\n        ]\n      },\n      \"author_id\": \"44217212\",\n      \"text\": \"knip is an amazing tool. Shoutout to @webprolific for building it 🙌.\\n\\nNot cleaning up correctly has a real maintenance cost. I've deleted lots of dead code - functions that were only used in tests and components that were only used in stories - all thanks to knip 🚀. https://t.co/Tg5E6C7gqa\",\n\n      \"id\": \"1714023231689031941\",\n      \"created_at\": \"2023-10-16T20:59:18.000Z\",\n      \"edit_history_tweet_ids\": [\"1714023231689031941\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9562,\n            \"type\": \"Other\",\n            \"normalized_text\": \"JavaScript\"\n          },\n          {\n            \"probability\": 0.8666,\n            \"type\": \"Other\",\n            \"normalized_text\": \"TypeScript\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/f3fzC5UPtR\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n            \"display_url\": \"github.com/webpro-nl/knip\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig\",\n                \"width\": 1280,\n                \"height\": 640\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!\",\n            \"description\": \"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip\"\n          }\n        ]\n      },\n      \"author_id\": \"481186762\",\n      \"text\": \"🛠️ Knip\\n\\n👉🏻 Knip finds unused dependencies, exports and files in your JavaScript and TypeScript projects.\\n👉🏻 Less code and dependencies lead to improved performance, less maintenance and easier refactorings. \\n\\nhttps://t.co/f3fzC5UPtR\",\n      \"id\": \"1696221274039595363\",\n      \"created_at\": \"2023-08-28T18:00:40.000Z\",\n      \"edit_history_tweet_ids\": [\"1696221274039595363\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9354,\n            \"type\": \"Other\",\n            \"normalized_text\": \"JavaScript\"\n          },\n          {\n            \"probability\": 0.7027,\n            \"type\": \"Other\",\n            \"normalized_text\": \"TypeScript\"\n          },\n          {\n            \"probability\": 0.7208,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Josh\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/nKtvr2wEg6\",\n            \"expanded_url\": \"https://twitter.com/JoshuaKGoldberg/status/1693713311836115286\",\n            \"display_url\": \"twitter.com/JoshuaKGoldberg\"\n          }\n        ]\n      },\n      \"author_id\": \"416394303\",\n      \"text\": \"Knip is wonderful at finding out unused code/dependencies in a legacy JavaScript/TypeScript application\\n\\nRecommend 💯\\n\\nHere's how Josh used it to remove code bloat in Centered: https://t.co/nKtvr2wEg6\",\n      \"id\": \"1693944495472046382\",\n      \"created_at\": \"2023-08-22T11:13:34.000Z\",\n      \"edit_history_tweet_ids\": [\"1693944495472046382\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.5513,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/L8w9V11PRL\",\n            \"expanded_url\": \"https://www.smashingmagazine.com/2023/08/knip-automated-tool-find-unused-files-exports-dependencies/\",\n            \"display_url\": \"smashingmagazine.com/2023/08/knip-a…\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1727384011872366592/W-M5klkJ?format=jpg&name=orig\",\n                \"width\": 1200,\n                \"height\": 675\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1727384011872366592/W-M5klkJ?format=jpg&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"Knip: An Automated Tool For Finding Unused Files, Exports, And Dependencies — Smashing Magazine\",\n            \"description\": \"Most of the projects have at least a few unused files, exports, and dependencies lying around, often because it’s difficult knowing when one thing relies on another and scary removing something you’re not sure is in use. Lars Kappert shares a tool he’s been working on that offers a solution.\",\n            \"unwound_url\": \"https://www.smashingmagazine.com/2023/08/knip-automated-tool-find-unused-files-exports-dependencies/\"\n          }\n        ]\n      },\n      \"author_id\": \"15736190\",\n      \"text\": \"Unused files, exports, and dependencies often clutter projects, as it’s difficult knowing when one thing relies on another and scary to remove something you’re not sure is in use. 👀\\n\\n↬ Meet Knip, which scours projects for these unused artifacts: https://t.co/L8w9V11PRL\",\n      \"id\": \"1691120132901240832\",\n      \"created_at\": \"2023-08-14T16:10:33.000Z\",\n      \"edit_history_tweet_ids\": [\"1691120132901240832\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"typescript\",\n            \"id\": \"809233214\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/1mRMwvjIpw\",\n            \"expanded_url\": \"https://effectivetypescript.com/2023/07/29/knip/\",\n            \"display_url\": \"effectivetypescript.com/2023/07/29/kni…\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1696204795353219085/ZjmFlTVW?format=jpg&name=orig\",\n                \"width\": 560,\n                \"height\": 735\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1696204795353219085/ZjmFlTVW?format=jpg&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"Effective TypeScript › Recommendation Update: ✂️ Use knip to detect dead code and types\",\n            \"description\": \"TL;DR: Use ts-prune is in maintenance mode. Use knip to find dead code instead. It's great!\",\n            \"unwound_url\": \"https://effectivetypescript.com/2023/07/29/knip/\"\n          }\n        ]\n      },\n      \"author_id\": \"21046936\",\n      \"text\": \"Recommendation update: use knip to find dead code, types and dependencies in your @typescript ✂️https://t.co/1mRMwvjIpw\",\n      \"id\": \"1685298103094554625\",\n      \"created_at\": \"2023-07-29T14:35:53.000Z\",\n      \"edit_history_tweet_ids\": [\"1685298103094554625\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9661,\n            \"type\": \"Other\",\n            \"normalized_text\": \"GitHub\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/vnxNbiJs1I\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n            \"display_url\": \"github.com/webpro-nl/knip\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig\",\n                \"width\": 1280,\n                \"height\": 640\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!\",\n            \"description\": \"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip\"\n          }\n        ]\n      },\n      \"author_id\": \"380616577\",\n      \"text\": \"This is worth checking out on GitHub. 👍 https://t.co/vnxNbiJs1I\",\n      \"id\": \"1581910299846012928\",\n      \"created_at\": \"2022-10-17T07:29:40.000Z\",\n      \"edit_history_tweet_ids\": [\"1581910299846012928\"]\n    },\n    {\n      \"note_tweet\": {\n        \"text\": \"Streamlining React projects with Knip:\\n\\nRecently, I employed Knip for a project, and it worked wonders! \\n\\nIt efficiently resolved issues with removing\\n✅ Unused files, \\n✅ Unused npm dependencies, \\n✅ Unneeded TypeScript exports.\\n\\n A real time-saver for maintaining a clean and efficient codebase. 🛠️ #ReactDevelopment \\n\\nhttps://t.co/IbJH2fIzsE\",\n        \"entities\": {\n          \"urls\": [\n            {\n              \"url\": \"https://t.co/IbJH2fIzsE\",\n              \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n              \"display_url\": \"github.com/webpro-nl/knip\"\n            }\n          ],\n          \"hashtags\": [{ \"tag\": \"ReactDevelopment\" }]\n        }\n      },\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.743,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          },\n          {\n            \"probability\": 0.7667,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/P39xg0qCrT\",\n            \"expanded_url\": \"https://twitter.com/i/web/status/1693502146128281657\",\n            \"display_url\": \"twitter.com/i/web/status/1…\"\n          }\n        ]\n      },\n      \"author_id\": \"827145937030148097\",\n      \"text\": \"Streamlining React projects with Knip:\\n\\nRecently, I employed Knip for a project, and it worked wonders! \\n\\nIt efficiently resolved issues with removing\\n✅ Unused files, \\n✅ Unused npm dependencies, \\n✅ Unneeded TypeScript exports.\\n\\n A real time-saver for maintaining a clean and… https://t.co/P39xg0qCrT\",\n      \"id\": \"1693502146128281657\",\n      \"created_at\": \"2023-08-21T05:55:50.000Z\",\n      \"edit_history_tweet_ids\": [\"1693502146128281657\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9331,\n            \"type\": \"Other\",\n            \"normalized_text\": \"JavaScript\"\n          },\n          {\n            \"probability\": 0.5907,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ]\n      },\n      \"author_id\": \"18191376\",\n      \"text\": \"Found a bunch of unused code, -dependencies, and unnecessary exports. Had just one false positive but overall pretty good. 10/10 would recommend.\\n\\nIf you’ve got a JavaScript package/project use Knip and remove unnecessary code. ✂️\",\n      \"id\": \"1692942539614028086\",\n      \"created_at\": \"2023-08-19T16:52:09.000Z\",\n      \"edit_history_tweet_ids\": [\"1692942539614028086\"]\n    }\n  ],\n  \"includes\": {\n    \"media\": [\n      {\n        \"media_key\": \"1\",\n        \"url\": \"https://pbs.twimg.com/media/GDrwdB3aYAAu4am?format=png&name=orig\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"2\",\n        \"url\": \"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:opw3iapscc55nlgrx6q2yjah/bafkreihzszb56agbe6dtuf6xfutl65mjg5ethnrvw264d5bljbm377jora@jpeg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"3_1730179997682552832\",\n        \"url\": \"https://pbs.twimg.com/media/GALVin9a0AAsn0-.jpg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"4\",\n        \"url\": \"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:4dsclu5hjmht3shxutxtge6h/bafkreid63o3hwvwpk6emgzj64vywusztofhz2yihuvwkywuuajn4eekvom@jpeg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"5\",\n        \"url\": \"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:2gkh62xvzokhlf6li4ol3b3d/bafkreiahk2jbsb2stw276lkrkxrkvialqs25zrpgo2n3cigzfb7qvgfsmq@jpeg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"6\",\n        \"url\": \"https://pbs.twimg.com/media/G9wBaMFWoAAkgv5.png\",\n        \"type\": \"photo\"\n      }\n    ],\n    \"users\": [\n      {\n        \"id\": \"22\",\n        \"username\": \"molliboyle.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:uwwm2qtpni4gvzzhujhh56ps/bafkreib5w76mmc6lxazhkymadd3oj5skped63b6ugvswiikrss7ljgcfi4@jpeg\",\n        \"name\": \"Molly Boyle\"\n      },\n      {\n        \"id\": \"20\",\n        \"username\": \"RozenMD\",\n        \"profile_image_url\": \"https://unavatar.io/x/RozenMD\",\n        \"name\": \"Max Rozen\"\n      },\n      {\n        \"id\": \"21\",\n        \"username\": \"06_Shreehari\",\n        \"profile_image_url\": \"https://unavatar.io/x/06_Shreehari\",\n        \"name\": \"Shreehari\"\n      },\n      {\n        \"id\": \"19\",\n        \"username\": \"janis.me\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:kmekwulhn26kgfwjzrry76d7/bafkreihtzvhhk7oz6cjbgnsbaravu46zhai3zwogkcg7hxv3dlhvecrqw4@jpeg\",\n        \"name\": \"Janis Jansen\"\n      },\n      {\n        \"id\": \"11\",\n        \"username\": \"julien.deniau.me\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:4dsclu5hjmht3shxutxtge6h/bafkreiht3iqxcmelwe7oysawrdpynzevf4dt2ndzeln4f5c2izf62zm57q@jpeg\",\n        \"name\": \"Julien Deniau\"\n      },\n      {\n        \"id\": \"12\",\n        \"username\": \"alexharfordseo.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:y3arowkhgiexpyvmmxvquavg/bafkreiazlcx5fdxylsqtsdng3beq3ayuoc7nzyqcddeequhi7uploqcjny@jpeg\",\n        \"name\": \"AlexHarford-TechSEO\"\n      },\n      {\n        \"id\": \"13\",\n        \"username\": \"fubits.dev\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:6aglx53tojyuwxwueap5og3h/bafkreiclnob3mnfvo74an6ugrnbdikrkxcskndjojrdtkwf5vwjuu77z5u@jpeg\",\n        \"name\": \"Ilja\"\n      },\n      {\n        \"id\": \"14\",\n        \"username\": \"alexanderkaran.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:3n4fccuhdomkkebojjdurnco/bafkreiggltcvdoh4igf5yxvrxggysmasv5efn6hffyav2o6swxslbc3lp4@jpeg\",\n        \"name\": \"Alexander Karan\"\n      },\n      {\n        \"id\": \"15\",\n        \"username\": \"patak.dev\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:2gkh62xvzokhlf6li4ol3b3d/bafkreibi7rw745tbcea7ljrpbkkkoragy2xa5a2lrxhdb3m23s7n3wkv3q@jpeg\",\n        \"name\": \"patak\"\n      },\n      {\n        \"id\": \"16\",\n        \"username\": \"psparwez\",\n        \"profile_image_url\": \"https://unavatar.io/x/psparwez\",\n        \"name\": \"PS\"\n      },\n      {\n        \"id\": \"17\",\n        \"username\": \"k_shehadeh\",\n        \"profile_image_url\": \"https://unavatar.io/x/k_shehadeh\",\n        \"name\": \"Karim Shehadeh\"\n      },\n      {\n        \"id\": \"18\",\n        \"username\": \"cramforce\",\n        \"profile_image_url\": \"https://unavatar.io/x/cramforce\",\n        \"name\": \"Malte Ubl\"\n      },\n      {\n        \"id\": \"1\",\n        \"username\": \"sqs\",\n        \"profile_image_url\": \"https://unavatar.io/x/sqs\",\n        \"name\": \"Quinn Slack\"\n      },\n      {\n        \"id\": \"2\",\n        \"username\": \"jokull\",\n        \"profile_image_url\": \"https://unavatar.io/x/jokull\",\n        \"name\": \"Jökull Solberg\"\n      },\n      {\n        \"id\": \"3\",\n        \"username\": \"Hicksyfern\",\n        \"profile_image_url\": \"https://unavatar.io/x/Hicksyfern\",\n        \"name\": \"Tom Hicks\"\n      },\n      {\n        \"id\": \"4\",\n        \"username\": \"daviduzumeri.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:6ykajndqngy2kxozo37mpsgc/bafkreif2xu6bini3tpv2hfauw53ng43zbefgqol36yt4baehcbdfxahihu@jpeg\",\n        \"name\": \"Old Man Uzi\"\n      },\n      {\n        \"id\": \"5\",\n        \"username\": \"gary__tyr\",\n        \"profile_image_url\": \"https://unavatar.io/x/gary__tyr\",\n        \"name\": \"Gary Tyr\"\n      },\n      {\n        \"id\": \"6\",\n        \"username\": \"KevinVanCott\",\n        \"profile_image_url\": \"https://unavatar.io/x/KevinVanCott\",\n        \"name\": \"Kevin Thomas Van Cott\"\n      },\n      {\n        \"id\": \"7\",\n        \"username\": \"joshuakgoldberg.com\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:hwtki3j7oghodc7h6gqnrtro/bafkreicvkrpjmc7yoviwf5vhkecgcgyn23x24ix4aqdwiikcl226c64k2q@jpeg\",\n        \"name\": \"Josh Goldberg 💖\"\n      },\n      {\n        \"id\": \"8\",\n        \"username\": \"beaussan.io\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:opw3iapscc55nlgrx6q2yjah/bafkreiaj72657msogojjdk4wr76fe3umimydon3pzzrquuj7opcftntrqa@jpeg\",\n        \"name\": \"Nicolas Beaussart\"\n      },\n      {\n        \"id\": \"9\",\n        \"username\": \"MidnightDesign\",\n        \"name\": \"Rudolph Gottesheim\",\n        \"profile_image_url\": \"https://avatars.githubusercontent.com/u/743172?v=4\"\n      },\n      {\n        \"id\": \"10\",\n        \"username\": \"stephaneledorze\",\n        \"name\": \"stephane le dorze\",\n        \"profile_image_url\": \"https://unavatar.io/x/stephaneledorze\"\n      },\n      {\n        \"id\": \"22918124\",\n        \"username\": \"gregberge_\",\n        \"profile_image_url\": \"https://unavatar.io/x/gregberge_\",\n        \"name\": \"Greg Bergé\"\n      },\n      {\n        \"id\": \"19268321\",\n        \"username\": \"housecor\",\n        \"profile_image_url\": \"https://unavatar.io/x/housecor\",\n        \"name\": \"Cory House\"\n      },\n      {\n        \"id\": \"3126044440\",\n        \"username\": \"pkgacek\",\n        \"profile_image_url\": \"https://unavatar.io/x/pkgacek\",\n        \"name\": \"Piotr Gacek 🐟\"\n      },\n      {\n        \"id\": \"95668959\",\n        \"username\": \"kuizinas\",\n        \"profile_image_url\": \"https://unavatar.io/x/kuizinas\",\n        \"name\": \"Gajus\"\n      },\n      {\n        \"id\": \"1632752318994153472\",\n        \"username\": \"imabhiprasad\",\n        \"profile_image_url\": \"https://unavatar.io/x/imabhiprasad\",\n        \"name\": \"Abhijeet Prasad\"\n      },\n      {\n        \"id\": \"1513218780167655427\",\n        \"username\": \"fernandoeeu_dev\",\n        \"profile_image_url\": \"https://unavatar.io/x/fernandoeeu_dev\",\n        \"name\": \"Fernando\"\n      },\n      {\n        \"id\": \"44217212\",\n        \"username\": \"TkDodo\",\n        \"profile_image_url\": \"https://unavatar.io/x/TkDodo\",\n        \"name\": \"Dominik 🔮\"\n      },\n      {\n        \"id\": \"481186762\",\n        \"username\": \"Mokkapps\",\n        \"profile_image_url\": \"https://unavatar.io/x/Mokkapps\",\n        \"name\": \"Michael Hoffmann\"\n      },\n      {\n        \"id\": \"416394303\",\n        \"username\": \"nicoespeon\",\n        \"profile_image_url\": \"https://unavatar.io/x/nicoespeon\",\n        \"name\": \"Nicolas Carlo\"\n      },\n      {\n        \"id\": \"15736190\",\n        \"username\": \"smashingmag\",\n        \"profile_image_url\": \"https://unavatar.io/x/smashingmag\",\n        \"name\": \"Smashing Magazine 🇺🇦 🏳️‍🌈\"\n      },\n      {\n        \"id\": \"21046936\",\n        \"username\": \"danvdk\",\n        \"profile_image_url\": \"https://unavatar.io/x/danvdk\",\n        \"name\": \"Dan Vanderkam\"\n      },\n      {\n        \"id\": \"380616577\",\n        \"username\": \"stefanjudis\",\n        \"profile_image_url\": \"https://unavatar.io/x/stefanjudis\",\n        \"name\": \"Stefan Judis\"\n      },\n      {\n        \"id\": \"827145937030148097\",\n        \"username\": \"BKailaash\",\n        \"profile_image_url\": \"https://unavatar.io/x/BKailaash\",\n        \"name\": \"Kailaash\"\n      },\n      {\n        \"id\": \"18191376\",\n        \"username\": \"waldekm\",\n        \"profile_image_url\": \"https://unavatar.io/x/waldekm\",\n        \"name\": \"Waldek Mastykarz\"\n      }\n    ]\n  }\n}\n","frontmatter":{"data":[{"entities":{"urls":[]},"id":"2061954856638967917","author_id":"5","created_at":"2026-06-02T23:35:21.000Z","text":"Knip is still my all time favorite piece of software."},{"entities":{"urls":[]},"id":"2061775207518343569","author_id":"20","created_at":"2026-06-02T11:41:30.000Z","text":"adding knip to our CI after deleting like 100k LOC of dead code was a game changer"},{"entities":{"urls":[]},"id":"3mn5ccucpvk2z","author_id":"13","created_at":"2026-05-31T09:54:50.000Z","text":"Knip is essential tooling."},{"entities":{"urls":[]},"id":"2059921462891622770","author_id":"21","created_at":"2026-05-28T08:55:22.000Z","text":"Please dont ask your ai agent to find unused, dead code and remove them. Instead for js/ts projects install knip and see the magic it does. Save tokens🙏😂"},{"entities":{"mentions":[{"username":"webpro.nl"}],"urls":[]},"id":"3mgkwe4digs2l","author_id":"19","created_at":"2026-03-25T12:00:00.000Z","text":"Two things about knip.dev I don't get:\n- how did we live without it for so long\n- how did @webpro.nl NAIL the timing? Gave it to us right when AI started to produce left-overs in our codes faster than we ever could."},{"entities":{"urls":[{"url":"cdn.bsky.app/img/dummy-02","display_url":"cdn.bsky.app/img/julien.deniau.me","media_key":"4"}]},"id":"3mdrubg3y5c2z","author_id":"11","created_at":"2026-02-01T07:57:00.000Z","attachments":{},"text":"Done on a mono-repo in two times.\nWhat's impressive is that there were no false positive!\ncdn.bsky.app/img/dummy-02"},{"entities":{"urls":[{"url":"https://t.co/EwIeRiHaXf","display_url":"pic.x.com/EwIeRiHaXf","media_key":"6"}]},"id":"2017122504914161979","author_id":"16","created_at":"2026-01-30T06:27:00.000Z","text":"Good morning 🌄\nA tool I discovered lately.\nIf you care about clean codebases, this one's a gem 💎"},{"entities":{"urls":[]},"id":"3mcky5ps3r22p","author_id":"12","created_at":"2026-01-16T20:53:09.000Z","text":"Knip is a cracking-looking open source tool for trimming unused JavaScript."},{"entities":{"urls":[{"url":"cdn.bsky.app/img/dummy-03","display_url":"cdn.bsky.app/img/patak.dev","media_key":"5"}]},"id":"3mcjtmv35wc2y","author_id":"15","created_at":"2026-01-16T09:59:29.000Z","attachments":{},"text":"From the report, we could improve the situation if we stop sending unused JavaScript. @webpro.nl is doing an incredible job growing the usage of knip.dev, and that should hopefully make a dent in the future.\ncdn.bsky.app/img/dummy-03"},{"entities":{"urls":[{"url":"https://knip.dev/blog/for-editors-and-agents","expanded_url":"https://knip.dev/blog/for-editors-and-agents","display_url":"knip.dev/blog/for-edi..."}]},"id":"3mby3zkzhfs2t","author_id":"13","created_at":"2026-01-09T08:41:49.000Z","text":"The VSCode/Cursor extension is ace!\nAnd you can use the Knip MCP to create the config file.\nIt works for Svelte as well.\nKnip is really really good 🙏"},{"entities":{"urls":[{"url":"https://t.co/6rcslWBqIV","display_url":"pic.x.com/6rcslWBqIV","media_key":"6"}]},"id":"2007481125610914217","author_id":"17","created_at":"2026-01-03T15:56:00.000Z","attachments":{"media_keys":["6"]},"text":"This is both embarrassing and satisfying after running @Knip https://t.co/6rcslWBqIV"},{"entities":{"urls":[{"url":"https://t.co/hneEWMqdnm","expanded_url":"https://knip.dev","display_url":"Knip.dev"}]},"id":"2007221517562904675","author_id":"18","created_at":"2026-01-02T23:44:00.000Z","text":"You can't spell Opus without https://t.co/hneEWMqdnm"},{"entities":{"urls":[]},"id":"3mbggqrihuk2r","author_id":"14","created_at":"2026-01-02T08:05:50.000Z","text":"Knip is amazing and you should be using it."},{"entities":{"urls":[]},"id":"3lvwax6bemc22","author_id":"22","created_at":"2025-08-08T22:02:18.000Z","text":"Just used `npx knip` to find my unused files, components, and packages and 😱! So cool. \n\nHow have I not come across it before?"},{"entities":{"urls":[]},"id":"1932778410691949034","author_id":"10","created_at":"2025-06-11T14:34:00.000Z","text":"\"Thanks Knip!\"\neveryday,\nevery team member,\nliterally..\nknip.dev 🏅"},{"entities":{"urls":[]},"url":"https://github.com/webpro-nl/knip/issues/1120#issuecomment-2943978262","author_id":"9","created_at":"2025-06-05T14:00:00.000Z","text":"Thank you so much for this incredible piece of software! Knip is one of the most impressive tools I've seen in my career."},{"entities":{"urls":[{"url":"https://github.com/webpro-nl/knip/pull/1022","expanded_url":"https://github.com/webpro-nl/knip/pull/1022","display_url":"https://github.com/webpro-nl/knip/pull/1022","title":"feat: add create-typescript-app plugin","description":"feat: add create-typescript-app plugin","unwound_url":"https://github.com/webpro-nl/knip/pull/1022"}]},"id":"3lmhgsj2n622o","author_id":"7","created_at":"2025-04-10T13:50:00.000Z","attachments":{},"text":"Got my first plugin merged into Knip by @webpro.nl today! ☺️\n\nThe contribution experience was fantastic: the docs were super clear, the code was straightforward to navigate, and the helper script to generate a new plugin got me 90% of the way there. Awesome. Thanks Lars!\n\nhttps://github.com/webpro-nl/knip/pull/1022"},{"entities":{"urls":[]},"id":"1904580358307250634","author_id":"6","created_at":"2025-03-25T18:05:00.000Z","attachments":{},"text":"All of the TanStack monorepos make use of knip.dev\n\nIt's like eslint for detecting unused dependencies or even your own files/modules."},{"entities":{"urls":[{"url":"cdn.bsky.app/img/dummy-01","display_url":"cdn.bsky.app/img/opw3iapscc55nlgrx6q2yjah","media_key":"2"}]},"id":"3ll5ioywml223","author_id":"8","created_at":"2025-03-24T20:32:00.000Z","attachments":{},"text":"The joy of adding knip.dev (by @webpro.nl) on a codebase! Right in time for spring cleaning 🧹🍃\ncdn.bsky.app/img/dummy-01"},{"entities":{"urls":[]},"id":"1874692207472726401","author_id":"5","created_at":"2025-01-02T06:40:00.000Z","attachments":{},"text":"Knip helped us delete ~300k lines of unused code at Vercel."},{"entities":{"urls":[{"url":"https://t.co/kA81p5gkmP","expanded_url":"https://www.npmx.dev/package/knip","display_url":"npmx.dev/package/knip","title":"Knip","description":"Find unused dependencies, exports and files in your TypeScript and JavaScript projects.","unwound_url":"https://www.npmx.dev/package/knip"}]},"id":"1850975288362221628","author_id":"5","created_at":"2024-10-28T19:57:00.000Z","attachments":{},"text":"Knip may be the greatest tool ever conceived.\nhttps://t.co/kA81p5gkmP"},{"entities":{"urls":[]},"id":"3k3obqi65oy2p","author_id":"4","created_at":"2023-07-29T17:33:00.000Z","attachments":{},"text":"`knip` is the best code maintenance tool I've used in my 20 years of development, just an absolute work of art"},{"entities":{"urls":[]},"id":"1808672067900092505","author_id":"3","created_at":"2024-07-04T03:19:00.000Z","attachments":{},"text":"knip is great.\n\nA great example of stuff just working. It detects your environment so well and its defaults are almost too good because I didn’t realise it was doing everything automatically."},{"entities":{"urls":[]},"id":"1808808208229707835","author_id":"3","created_at":"2024-07-04T12:20:00.000Z","attachments":{},"text":"Then was like “this is how tooling should be, this has taken me an hour not a day and it’s faster and more accurate and more future proof”\n\nFive stars ⭐️⭐️⭐️⭐️⭐️"},{"entities":{"urls":[]},"id":"1803013555907698921","author_id":"2","created_at":"2024-06-18T12:35:00.000Z","attachments":{},"text":"Crazy useful tool. Thought it would be a nightmare to setup in my Next.js+Workers repo but it has crazy good automatic detection for code dependencies. In short, Knip creates a graph of code use and highlights dead code for you to snip (knip)."},{"entities":{"urls":[]},"id":"1793913676896031033","author_id":"44217212","created_at":"2024-05-24T09:55:00.000Z","attachments":{},"text":"Lars is singlehandedly building the best tool to keep your code clean and your dependencies minimal. And he's so engaging and helpful. Can't imagine going back to not using knip 👏"},{"entities":{"urls":[{"url":"https://t.co/dummy-01","display_url":"pic.twitter.com/uOuO1ch5ij","media_key":"1"}]},"id":"1745972825490604506","author_id":"1","created_at":"2024-01-13T01:55:00.000Z","attachments":{"media_keys":["1"]},"text":"warning: do not use a tool like knip.dev + code search to delete a ton of unused code. It works too well.\n\nI just did this in https://github.com/sourcegraph/cody/pull/2705, and my boss said if I end the week with net negative lines of code committed, I'm in deep trouble. https://t.co/dummy-01"},{"entities":{"mentions":[{"username":"argos_ci","id":"1554000987022663681"},{"username":"webprolific","id":"218833730"}],"annotations":[{"probability":0.6699,"type":"Other","normalized_text":"Prettier"},{"probability":0.7586,"type":"Other","normalized_text":"ESLint"}],"urls":[{"url":"https://t.co/uOuO1ch5ij","expanded_url":"https://twitter.com/gregberge_/status/1730180003453927560/photo/1","display_url":"pic.twitter.com/uOuO1ch5ij","media_key":"3_1730179997682552832"}]},"author_id":"22918124","text":"Ran knip.dev in @argos_ci, and boom 💥! Dead code detected instantly. With a good config, it can run on CI to keep projects clean. Installing this tool should be a no-brainer, like Prettier or ESLint.\n\nKudos, @webprolific! 👏 https://t.co/uOuO1ch5ij","id":"1730180003453927560","created_at":"2023-11-30T11:00:32.000Z","edit_history_tweet_ids":["1730180003453927560"],"attachments":{"media_keys":["3_1730179997682552832"]}},{"note_tweet":{"text":"Problem: \n🚫 Your project has unused files.\n🚫 It has unused npm dependencies.\n🚫 It has unused TypeScript exports.\n\nBut you haven't noticed, because these things are hard to spot.\n\nSolution: knip\n\nI just used knip to find and resolve dozens of issues.\n\nhttps://t.co/QmN3sNlmbm","entities":{"urls":[{"url":"https://t.co/QmN3sNlmbm","expanded_url":"https://github.com/webpro-nl/knip","display_url":"github.com/webpro-nl/knip"}]}},"entities":{"annotations":[{"probability":0.8569,"type":"Other","normalized_text":"TypeScript"}],"urls":[{"url":"https://t.co/grbeTqMtt6","expanded_url":"https://github.com/webpro-nl/knip","display_url":"github.com/webpro-nl/knip","images":[{"url":"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig","width":1280,"height":640},{"url":"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150","width":150,"height":150}],"title":"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!","description":"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...","unwound_url":"https://github.com/webpro-nl/knip"},{"url":"https://t.co/qaOXBlD3eo","expanded_url":"https://twitter.com/i/web/status/1691460974518353920","display_url":"twitter.com/i/web/status/1…"}]},"author_id":"19268321","text":"Problem: \n🚫 Your project has unused files.\n🚫 It has unused npm dependencies.\n🚫 It has unused TypeScript exports.\n\nBut you haven't noticed, because these things are hard to spot.\n\nSolution: knip\n\nI just used knip to find and resolve dozens of issues.\n\nhttps://t.co/grbeTqMtt6 https://t.co/qaOXBlD3eo","id":"1691460974518353920","created_at":"2023-08-15T14:44:56.000Z","edit_history_tweet_ids":["1691460974518353920"]},{"entities":{"mentions":[{"username":"webprolific","id":"218833730"}],"annotations":[{"probability":0.6322,"type":"Other","normalized_text":"Knip"}]},"author_id":"3126044440","text":"@webprolific Knip helped me get rid of over 41k lines of code in legacy codebase 🥺🥺💕","id":"1729181106715632088","created_at":"2023-11-27T16:51:17.000Z","edit_history_tweet_ids":["1729181106715632088"]},{"entities":{"mentions":[{"username":"contra","id":"973313523790082053"}],"annotations":[{"probability":0.8474,"type":"Other","normalized_text":"Knip"}],"urls":[{"url":"https://t.co/UgCunYQWzu","expanded_url":"https://twitter.com/webprolific/status/1729105865683435542","display_url":"twitter.com/webprolific/st…"}]},"author_id":"95668959","text":"Big fans of Knip at @Contra. Such an extremely well developed and maintained project https://t.co/UgCunYQWzu","id":"1729157761215369264","created_at":"2023-11-27T15:18:31.000Z","edit_history_tweet_ids":["1729157761215369264"]},{"entities":{"mentions":[{"username":"webprolific","id":"218833730"}],"urls":[{"url":"https://t.co/ZUYYdvkBJc","expanded_url":"https://github.com/getsentry/sentry/","display_url":"github.com/getsentry/sent…","title":"GitHub - getsentry/sentry: Developer-first error tracking and performance monitoring","description":"Developer-first error tracking and performance monitoring - GitHub - getsentry/sentry: Developer-first error tracking and performance monitoring","unwound_url":"https://github.com/getsentry/sentry/"}]},"author_id":"1632752318994153472","text":"@webprolific Just tried this on https://t.co/ZUYYdvkBJc - got some super useful results! Nice work.","id":"1727040036334424406","created_at":"2023-11-21T19:03:26.000Z","edit_history_tweet_ids":["1727040036334424406"]},{"entities":{"mentions":[{"username":"TkDodo","id":"44217212"},{"username":"webprolific","id":"218833730"},{"username":"webprolific","id":"218833730"}]},"author_id":"1513218780167655427","text":"@TkDodo @webprolific I've manage to delete 6k LOC in the last 30 minutes 🫣\n\nGreat job here @webprolific 👍🏽","id":"1726807293583609935","created_at":"2023-11-21T03:38:35.000Z","edit_history_tweet_ids":["1726807293583609935"]},{"entities":{"mentions":[{"username":"webprolific","id":"218833730"}],"urls":[{"url":"https://t.co/Tg5E6C7gqa","expanded_url":"https://twitter.com/housecor/status/1713975785273303286","display_url":"twitter.com/housecor/statu…"}]},"author_id":"44217212","text":"knip is an amazing tool. Shoutout to @webprolific for building it 🙌.\n\nNot cleaning up correctly has a real maintenance cost. I've deleted lots of dead code - functions that were only used in tests and components that were only used in stories - all thanks to knip 🚀. https://t.co/Tg5E6C7gqa","id":"1714023231689031941","created_at":"2023-10-16T20:59:18.000Z","edit_history_tweet_ids":["1714023231689031941"]},{"entities":{"annotations":[{"probability":0.9562,"type":"Other","normalized_text":"JavaScript"},{"probability":0.8666,"type":"Other","normalized_text":"TypeScript"}],"urls":[{"url":"https://t.co/f3fzC5UPtR","expanded_url":"https://github.com/webpro-nl/knip","display_url":"github.com/webpro-nl/knip","images":[{"url":"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig","width":1280,"height":640},{"url":"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150","width":150,"height":150}],"title":"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!","description":"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...","unwound_url":"https://github.com/webpro-nl/knip"}]},"author_id":"481186762","text":"🛠️ Knip\n\n👉🏻 Knip finds unused dependencies, exports and files in your JavaScript and TypeScript projects.\n👉🏻 Less code and dependencies lead to improved performance, less maintenance and easier refactorings. \n\nhttps://t.co/f3fzC5UPtR","id":"1696221274039595363","created_at":"2023-08-28T18:00:40.000Z","edit_history_tweet_ids":["1696221274039595363"]},{"entities":{"annotations":[{"probability":0.9354,"type":"Other","normalized_text":"JavaScript"},{"probability":0.7027,"type":"Other","normalized_text":"TypeScript"},{"probability":0.7208,"type":"Other","normalized_text":"Josh"}],"urls":[{"url":"https://t.co/nKtvr2wEg6","expanded_url":"https://twitter.com/JoshuaKGoldberg/status/1693713311836115286","display_url":"twitter.com/JoshuaKGoldberg"}]},"author_id":"416394303","text":"Knip is wonderful at finding out unused code/dependencies in a legacy JavaScript/TypeScript application\n\nRecommend 💯\n\nHere's how Josh used it to remove code bloat in Centered: https://t.co/nKtvr2wEg6","id":"1693944495472046382","created_at":"2023-08-22T11:13:34.000Z","edit_history_tweet_ids":["1693944495472046382"]},{"entities":{"annotations":[{"probability":0.5513,"type":"Other","normalized_text":"Knip"}],"urls":[{"url":"https://t.co/L8w9V11PRL","expanded_url":"https://www.smashingmagazine.com/2023/08/knip-automated-tool-find-unused-files-exports-dependencies/","display_url":"smashingmagazine.com/2023/08/knip-a…","images":[{"url":"https://pbs.twimg.com/news_img/1727384011872366592/W-M5klkJ?format=jpg&name=orig","width":1200,"height":675},{"url":"https://pbs.twimg.com/news_img/1727384011872366592/W-M5klkJ?format=jpg&name=150x150","width":150,"height":150}],"title":"Knip: An Automated Tool For Finding Unused Files, Exports, And Dependencies — Smashing Magazine","description":"Most of the projects have at least a few unused files, exports, and dependencies lying around, often because it’s difficult knowing when one thing relies on another and scary removing something you’re not sure is in use. Lars Kappert shares a tool he’s been working on that offers a solution.","unwound_url":"https://www.smashingmagazine.com/2023/08/knip-automated-tool-find-unused-files-exports-dependencies/"}]},"author_id":"15736190","text":"Unused files, exports, and dependencies often clutter projects, as it’s difficult knowing when one thing relies on another and scary to remove something you’re not sure is in use. 👀\n\n↬ Meet Knip, which scours projects for these unused artifacts: https://t.co/L8w9V11PRL","id":"1691120132901240832","created_at":"2023-08-14T16:10:33.000Z","edit_history_tweet_ids":["1691120132901240832"]},{"entities":{"mentions":[{"username":"typescript","id":"809233214"}],"urls":[{"url":"https://t.co/1mRMwvjIpw","expanded_url":"https://effectivetypescript.com/2023/07/29/knip/","display_url":"effectivetypescript.com/2023/07/29/kni…","images":[{"url":"https://pbs.twimg.com/news_img/1696204795353219085/ZjmFlTVW?format=jpg&name=orig","width":560,"height":735},{"url":"https://pbs.twimg.com/news_img/1696204795353219085/ZjmFlTVW?format=jpg&name=150x150","width":150,"height":150}],"title":"Effective TypeScript › Recommendation Update: ✂️ Use knip to detect dead code and types","description":"TL;DR: Use ts-prune is in maintenance mode. Use knip to find dead code instead. It's great!","unwound_url":"https://effectivetypescript.com/2023/07/29/knip/"}]},"author_id":"21046936","text":"Recommendation update: use knip to find dead code, types and dependencies in your @typescript ✂️https://t.co/1mRMwvjIpw","id":"1685298103094554625","created_at":"2023-07-29T14:35:53.000Z","edit_history_tweet_ids":["1685298103094554625"]},{"entities":{"annotations":[{"probability":0.9661,"type":"Other","normalized_text":"GitHub"}],"urls":[{"url":"https://t.co/vnxNbiJs1I","expanded_url":"https://github.com/webpro-nl/knip","display_url":"github.com/webpro-nl/knip","images":[{"url":"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig","width":1280,"height":640},{"url":"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150","width":150,"height":150}],"title":"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!","description":"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...","unwound_url":"https://github.com/webpro-nl/knip"}]},"author_id":"380616577","text":"This is worth checking out on GitHub. 👍 https://t.co/vnxNbiJs1I","id":"1581910299846012928","created_at":"2022-10-17T07:29:40.000Z","edit_history_tweet_ids":["1581910299846012928"]},{"note_tweet":{"text":"Streamlining React projects with Knip:\n\nRecently, I employed Knip for a project, and it worked wonders! \n\nIt efficiently resolved issues with removing\n✅ Unused files, \n✅ Unused npm dependencies, \n✅ Unneeded TypeScript exports.\n\n A real time-saver for maintaining a clean and efficient codebase. 🛠️ #ReactDevelopment \n\nhttps://t.co/IbJH2fIzsE","entities":{"urls":[{"url":"https://t.co/IbJH2fIzsE","expanded_url":"https://github.com/webpro-nl/knip","display_url":"github.com/webpro-nl/knip"}],"hashtags":[{"tag":"ReactDevelopment"}]}},"entities":{"annotations":[{"probability":0.743,"type":"Other","normalized_text":"Knip"},{"probability":0.7667,"type":"Other","normalized_text":"Knip"}],"urls":[{"url":"https://t.co/P39xg0qCrT","expanded_url":"https://twitter.com/i/web/status/1693502146128281657","display_url":"twitter.com/i/web/status/1…"}]},"author_id":"827145937030148097","text":"Streamlining React projects with Knip:\n\nRecently, I employed Knip for a project, and it worked wonders! \n\nIt efficiently resolved issues with removing\n✅ Unused files, \n✅ Unused npm dependencies, \n✅ Unneeded TypeScript exports.\n\n A real time-saver for maintaining a clean and… https://t.co/P39xg0qCrT","id":"1693502146128281657","created_at":"2023-08-21T05:55:50.000Z","edit_history_tweet_ids":["1693502146128281657"]},{"entities":{"annotations":[{"probability":0.9331,"type":"Other","normalized_text":"JavaScript"},{"probability":0.5907,"type":"Other","normalized_text":"Knip"}]},"author_id":"18191376","text":"Found a bunch of unused code, -dependencies, and unnecessary exports. Had just one false positive but overall pretty good. 10/10 would recommend.\n\nIf you’ve got a JavaScript package/project use Knip and remove unnecessary code. ✂️","id":"1692942539614028086","created_at":"2023-08-19T16:52:09.000Z","edit_history_tweet_ids":["1692942539614028086"]}],"includes":{"media":[{"media_key":"1","url":"https://pbs.twimg.com/media/GDrwdB3aYAAu4am?format=png&name=orig","type":"photo"},{"media_key":"2","url":"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:opw3iapscc55nlgrx6q2yjah/bafkreihzszb56agbe6dtuf6xfutl65mjg5ethnrvw264d5bljbm377jora@jpeg","type":"photo"},{"media_key":"3_1730179997682552832","url":"https://pbs.twimg.com/media/GALVin9a0AAsn0-.jpg","type":"photo"},{"media_key":"4","url":"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:4dsclu5hjmht3shxutxtge6h/bafkreid63o3hwvwpk6emgzj64vywusztofhz2yihuvwkywuuajn4eekvom@jpeg","type":"photo"},{"media_key":"5","url":"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:2gkh62xvzokhlf6li4ol3b3d/bafkreiahk2jbsb2stw276lkrkxrkvialqs25zrpgo2n3cigzfb7qvgfsmq@jpeg","type":"photo"},{"media_key":"6","url":"https://pbs.twimg.com/media/G9wBaMFWoAAkgv5.png","type":"photo"}],"users":[{"id":"22","username":"molliboyle.bsky.social","profile_image_url":"https://cdn.bsky.app/img/avatar/plain/did:plc:uwwm2qtpni4gvzzhujhh56ps/bafkreib5w76mmc6lxazhkymadd3oj5skped63b6ugvswiikrss7ljgcfi4@jpeg","name":"Molly Boyle"},{"id":"20","username":"RozenMD","profile_image_url":"https://unavatar.io/x/RozenMD","name":"Max Rozen"},{"id":"21","username":"06_Shreehari","profile_image_url":"https://unavatar.io/x/06_Shreehari","name":"Shreehari"},{"id":"19","username":"janis.me","profile_image_url":"https://cdn.bsky.app/img/avatar/plain/did:plc:kmekwulhn26kgfwjzrry76d7/bafkreihtzvhhk7oz6cjbgnsbaravu46zhai3zwogkcg7hxv3dlhvecrqw4@jpeg","name":"Janis Jansen"},{"id":"11","username":"julien.deniau.me","profile_image_url":"https://cdn.bsky.app/img/avatar/plain/did:plc:4dsclu5hjmht3shxutxtge6h/bafkreiht3iqxcmelwe7oysawrdpynzevf4dt2ndzeln4f5c2izf62zm57q@jpeg","name":"Julien Deniau"},{"id":"12","username":"alexharfordseo.bsky.social","profile_image_url":"https://cdn.bsky.app/img/avatar/plain/did:plc:y3arowkhgiexpyvmmxvquavg/bafkreiazlcx5fdxylsqtsdng3beq3ayuoc7nzyqcddeequhi7uploqcjny@jpeg","name":"AlexHarford-TechSEO"},{"id":"13","username":"fubits.dev","profile_image_url":"https://cdn.bsky.app/img/avatar/plain/did:plc:6aglx53tojyuwxwueap5og3h/bafkreiclnob3mnfvo74an6ugrnbdikrkxcskndjojrdtkwf5vwjuu77z5u@jpeg","name":"Ilja"},{"id":"14","username":"alexanderkaran.bsky.social","profile_image_url":"https://cdn.bsky.app/img/avatar/plain/did:plc:3n4fccuhdomkkebojjdurnco/bafkreiggltcvdoh4igf5yxvrxggysmasv5efn6hffyav2o6swxslbc3lp4@jpeg","name":"Alexander Karan"},{"id":"15","username":"patak.dev","profile_image_url":"https://cdn.bsky.app/img/avatar/plain/did:plc:2gkh62xvzokhlf6li4ol3b3d/bafkreibi7rw745tbcea7ljrpbkkkoragy2xa5a2lrxhdb3m23s7n3wkv3q@jpeg","name":"patak"},{"id":"16","username":"psparwez","profile_image_url":"https://unavatar.io/x/psparwez","name":"PS"},{"id":"17","username":"k_shehadeh","profile_image_url":"https://unavatar.io/x/k_shehadeh","name":"Karim Shehadeh"},{"id":"18","username":"cramforce","profile_image_url":"https://unavatar.io/x/cramforce","name":"Malte Ubl"},{"id":"1","username":"sqs","profile_image_url":"https://unavatar.io/x/sqs","name":"Quinn Slack"},{"id":"2","username":"jokull","profile_image_url":"https://unavatar.io/x/jokull","name":"Jökull Solberg"},{"id":"3","username":"Hicksyfern","profile_image_url":"https://unavatar.io/x/Hicksyfern","name":"Tom Hicks"},{"id":"4","username":"daviduzumeri.bsky.social","profile_image_url":"https://cdn.bsky.app/img/avatar/plain/did:plc:6ykajndqngy2kxozo37mpsgc/bafkreif2xu6bini3tpv2hfauw53ng43zbefgqol36yt4baehcbdfxahihu@jpeg","name":"Old Man Uzi"},{"id":"5","username":"gary__tyr","profile_image_url":"https://unavatar.io/x/gary__tyr","name":"Gary Tyr"},{"id":"6","username":"KevinVanCott","profile_image_url":"https://unavatar.io/x/KevinVanCott","name":"Kevin Thomas Van Cott"},{"id":"7","username":"joshuakgoldberg.com","profile_image_url":"https://cdn.bsky.app/img/avatar/plain/did:plc:hwtki3j7oghodc7h6gqnrtro/bafkreicvkrpjmc7yoviwf5vhkecgcgyn23x24ix4aqdwiikcl226c64k2q@jpeg","name":"Josh Goldberg 💖"},{"id":"8","username":"beaussan.io","profile_image_url":"https://cdn.bsky.app/img/avatar/plain/did:plc:opw3iapscc55nlgrx6q2yjah/bafkreiaj72657msogojjdk4wr76fe3umimydon3pzzrquuj7opcftntrqa@jpeg","name":"Nicolas Beaussart"},{"id":"9","username":"MidnightDesign","name":"Rudolph Gottesheim","profile_image_url":"https://avatars.githubusercontent.com/u/743172?v=4"},{"id":"10","username":"stephaneledorze","name":"stephane le dorze","profile_image_url":"https://unavatar.io/x/stephaneledorze"},{"id":"22918124","username":"gregberge_","profile_image_url":"https://unavatar.io/x/gregberge_","name":"Greg Bergé"},{"id":"19268321","username":"housecor","profile_image_url":"https://unavatar.io/x/housecor","name":"Cory House"},{"id":"3126044440","username":"pkgacek","profile_image_url":"https://unavatar.io/x/pkgacek","name":"Piotr Gacek 🐟"},{"id":"95668959","username":"kuizinas","profile_image_url":"https://unavatar.io/x/kuizinas","name":"Gajus"},{"id":"1632752318994153472","username":"imabhiprasad","profile_image_url":"https://unavatar.io/x/imabhiprasad","name":"Abhijeet Prasad"},{"id":"1513218780167655427","username":"fernandoeeu_dev","profile_image_url":"https://unavatar.io/x/fernandoeeu_dev","name":"Fernando"},{"id":"44217212","username":"TkDodo","profile_image_url":"https://unavatar.io/x/TkDodo","name":"Dominik 🔮"},{"id":"481186762","username":"Mokkapps","profile_image_url":"https://unavatar.io/x/Mokkapps","name":"Michael Hoffmann"},{"id":"416394303","username":"nicoespeon","profile_image_url":"https://unavatar.io/x/nicoespeon","name":"Nicolas Carlo"},{"id":"15736190","username":"smashingmag","profile_image_url":"https://unavatar.io/x/smashingmag","name":"Smashing Magazine 🇺🇦 🏳️‍🌈"},{"id":"21046936","username":"danvdk","profile_image_url":"https://unavatar.io/x/danvdk","name":"Dan Vanderkam"},{"id":"380616577","username":"stefanjudis","profile_image_url":"https://unavatar.io/x/stefanjudis","name":"Stefan Judis"},{"id":"827145937030148097","username":"BKailaash","profile_image_url":"https://unavatar.io/x/BKailaash","name":"Kailaash"},{"id":"18191376","username":"waldekm","profile_image_url":"https://unavatar.io/x/waldekm","name":"Waldek Mastykarz"}]}},"isInternal":false,"tokens":11389,"sizeBytes":38649},{"name":"comparison-and-migration.md","path":"packages/docs/src/content/docs/explanations/comparison-and-migration.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/explanations/comparison-and-migration.md","title":"Explanations Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Comparison & Migration\ndescription: How Knip compares to depcheck, unimported, ts-prune, ts-unused-exports and tsr, and how to migrate from them.\n---\n\nFirst of all, Knip owes a lot to the projects on this page and they've all been\ninspirational in their own way. For best results, Knip has [a vision embracing\ncomprehensiveness][1] which is larger in scope than any of the alternatives. So\nif any of those tools has the right scope for your requirements, then by all\nmeans, use what suits you best. Note that most projects are no longer\nmaintained.\n\nAll tools have in common that they have less features and don't support the\nconcept of [monorepos/workspaces][2]. Feel free to send in projects that Knip\ndoes not handle better, Knip loves to be challenged!\n\n## Migration\n\nA migration consists of deleting the dependency and its configuration file and\n[getting started with Knip][3]. You should end up with less configuration.\n\n## Comparison\n\n### depcheck\n\n> [Depcheck][4] is a tool for analyzing the dependencies in a project to see:\n> how each dependency is used, which dependencies are useless, and which\n> dependencies are missing from package.json.\n\nThe project has plugins (specials), yet not as many as Knip has and they're not\nas advanced. It also supports compilers (parsers) for non-standard files.\n\nThe following commands are similar:\n\n```sh\ndepcheck\nknip --dependencies\n```\n\n**Project status**: The project is archived and recommends Knip.\n\n### unimported\n\n> Find and fix dangling files and unused dependencies in your JavaScript\n> projects.\n\n[unimported][5] is fast and works well. It works in what Knip calls \"production\nmode\" exclusively. If you're fine with a little bit of configuration and don't\nwant or need to deal with non-production items (such as `devDependencies` and\ntest files), then this might work well for you.\n\nThe following commands are similar:\n\n```sh\nunimported\nknip --production --dependencies --files\n```\n\n**Project status**: The project is archived and recommends Knip.\n\n### ts-prune\n\n> Find unused exports in a typescript project. 🛀\n\n[ts-prune][6] aims to find potentially unused exports in your TypeScript project\nwith zero configuration.\n\nThe following commands are similar:\n\n```sh\nts-prune\nknip --include exports,types,nsExports,nsTypes\n```\n\nUse `knip --exports` to also include enum and namespace members.\n\n**Project status**: The project is archived and recommends Knip.\n\n### ts-unused-exports\n\n> [ts-unused-exports][7] finds unused exported symbols in your Typescript\n> project\n\nThe following commands are similar:\n\n```sh\nts-unused-exports\nknip --include exports,types,nsExports,nsTypes\n```\n\nUse `knip --exports` to also include enum and namespace members.\n\n### tsr\n\n> Remove unused code from your TypeScript Project\n\n[tsr][8] (previously `ts-remove-unused`) removes unused exports, and works based\non a single `tsconfig.json` file (`includes` and `excludes`) and requires no\nconfiguration. It removes the `export` keyword or the whole export declaration.\n\n**Project status**: The project is archived and recommends Knip.\n\n## Related projects\n\nAdditional alternative and related projects include:\n\n- [deadfile][9]\n- [DepClean][10]\n- [dependency-check][11]\n- [find-unused-exports][12]\n- [next-unused][13]\n- [npm-check][14]\n- [renoma][15]\n\nIn general, the [e18e.dev][16] website and in particular the [Cleanup][17]\nsection is a great resource when dealing with technical debt.\n\n[1]: ./why-use-knip.md#comprehensive\n[2]: ../features/monorepos-and-workspaces.md\n[3]: ../overview/getting-started.mdx\n[4]: https://github.com/depcheck/depcheck\n[5]: https://github.com/smeijer/unimported\n[6]: https://github.com/nadeesha/ts-prune\n[7]: https://github.com/pzavolinsky/ts-unused-exports\n[8]: https://github.com/line/tsr\n[9]: https://github.com/M-Izadmehr/deadfile\n[10]: https://github.com/mysteryven/depclean\n[11]: https://github.com/dependency-check-team/dependency-check\n[12]: https://github.com/jaydenseric/find-unused-exports\n[13]: https://github.com/pacocoursey/next-unused\n[14]: https://github.com/dylang/npm-check\n[15]: https://github.com/bluwy/renoma\n[16]: https://e18e.dev\n[17]: https://e18e.dev/guide/cleanup.html\n","frontmatter":{"title":"Comparison & Migration","description":"How Knip compares to depcheck, unimported, ts-prune, ts-unused-exports and tsr, and how to migrate from them."},"isInternal":false,"tokens":1056,"sizeBytes":4169},{"name":"entry-files.md","path":"packages/docs/src/content/docs/explanations/entry-files.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/explanations/entry-files.md","title":"Explanations Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Entry Files\ndescription: What entry files are and how Knip and its plugins find them automatically from defaults, `package.json`, plugins and dynamic imports.\n---\n\nEntry files are the starting point for Knip to determine what files are used in\nthe codebase. More entry files lead to increased coverage of the codebase. This\nalso leads to more dependencies to be discovered. This page explains how Knip\nand its plugins try to find entry files so you don't need to configure them\nyourself.\n\n## Default entry file patterns\n\nFor brevity, the [default configuration][1] on the previous page mentions only\n`index.js` and `index.ts`, but the default set of file names and extensions is\nactually a bit larger:\n\n- `index`, `main` and `cli`\n- `js`, `mjs`, `cjs`, `jsx`, `ts`, `mts`, `cts` and `tsx`\n\nThis means files like `main.cjs` and `src/cli.ts` are automatically added as\nentry files. Here's the default configuration in full:\n\n```json\n{\n  \"entry\": [\n    \"{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\",\n    \"src/{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\"\n  ],\n  \"project\": [\"**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}!\"]\n}\n```\n\nNext to the default locations, Knip looks for `entry` files in other places. In\na monorepo, this is done for each workspace separately.\n\nThe values you set override the default values, they are not merged.\n\n## Plugins\n\nPlugins often add entry files. For instance, the Remix, Storybook and Vitest\nplugins add additional entry files. See [the next page about plugins][2] for\nmore details about this.\n\n## Scripts in package.json\n\nThe `package.json` is scanned for entry files. The `main`, `bin`, and `exports`\nfields may contain entry files. The `scripts` are also parsed to find entry\nfiles and dependencies. See [Script Parser][3] for more details.\n\n## Ignored files\n\nKnip respects `.gitignore` files. By default, ignored files are not added as\nentry files. This behavior can be disabled by using the [`--no-gitignore`][4]\nflag on the CLI.\n\n## Configuring project files\n\nSee [configuring project files][5] for guidance on tuning `entry` and `project`\nand when to use `ignore`.\n\n## Where Knip looks for entry files\n\nPutting it together, Knip discovers entry files from:\n\n- Default locations such as `index.js` and `src/index.ts`\n- The `main`, `bin` and `exports` fields in `package.json`\n- Entry and config files added by enabled plugins (the config files are entry\n  files too)\n- Dynamic imports: `require()` and `import()`\n- `require.resolve()` and `import.meta.resolve()`\n- `new URL('./file.js', import.meta.url)`\n- `new Worker(…)` and `child_process` `fork`/`spawn`/`execFile` when the target\n  is `path.join(__dirname, …)`\n- `module.register('./loader.js')` loader registration\n- Scripts the [script parser][3] extracts: `package.json` scripts, CI workflow\n  `run` commands, and source-code calls (tagged `$` templates,\n  `node:child_process`, `execa`, `nano-spawn`)\n\nEntry files are added to the module graph, and module resolution may pull in\nfurther entry files recursively until none remain.\n\n[1]: ../overview/configuration.md#defaults\n[2]: ./plugins.md\n[3]: ../features/script-parser.md\n[4]: ../reference/cli.md#--no-gitignore\n[5]: ../guides/configuring-project-files.md\n","frontmatter":{"title":"Entry Files","description":"What entry files are and how Knip and its plugins find them automatically from defaults, `package.json`, plugins and dynamic imports."},"isInternal":false,"tokens":838,"sizeBytes":3222},{"name":"how-knip-works.md","path":"packages/docs/src/content/docs/explanations/how-knip-works.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/explanations/how-knip-works.md","title":"Explanations Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: How Knip works\ndescription: The mental model behind Knip. How entry files, the module graph and reachability decide what counts as unused, and why surprising results trace back to them.\n---\n\nKnip finds and removes unused code and dependencies. It starts at your entry\nfiles, follows every import to the files they reach, and builds a graph of\neverything connected. Anything left out is reported as unused: a file no entry\nreaches, an export no file imports, a dependency no file uses.\n\nThis page explains how Knip produces its results.\n\n## Build and analyze\n\nKnip runs in two phases.\n\nThe build phase starts from the entry files. Knip reads a file, parses it,\ncollects its imports and exports, resolves each import to another file, and\nrepeats for every newly reached file. The result is a graph of the project:\nevery reachable file, what it imports, and what imports it.\n\nResolution is broad by design. Knip follows custom path aliases and extensions,\nreads references out of config files and [shell scripts][1], and \"[compiles][2]\"\nnon-standard files like `.vue` and `.svelte` so their imports are in the graph\ntoo.\n\nThe analysis phase queries that graph. It never re-parses anything. It walks the\nedges already recorded:\n\n- a **file** is unused when no entry reaches it\n- an **export** is unused when no other file imports it\n- a **dependency** is unused when no file imports it (and _unlisted_ when a file\n  imports it but `package.json` doesn't list it)\n\nAnalysis happens by quering the graph. Your results are only as accurate as the\ngraph is complete. And the graph depends on your entry files.\n\n## Entry files decide what Knip can see\n\nThe graph contains only what's reachable from an entry file. Miss one entry, and\neverything reachable _only_ from it looks unused.\n\nIdeally you don't need to list entries by hand. Knip starts from sensible\n[defaults][3] like `src/index.ts`, and [plugins][4] automatically add the entry\npoints specific to your frameworks and libraries. The Vitest plugin adds your\ntest files, the Astro plugin adds your pages, and so on. This is why plugins are\nimportant: each one tells Knip about a whole class of files it might otherwise\nnever reach.\n\n## Findings come in chains\n\nUnused results cascade. They don't appear in isolation. Say a tool generates an\nentry file Knip doesn't know about:\n\n- that file looks unused, because nothing reaches it\n- every file it imports looks unused too, because nothing else reaches them\n- every export in those files looks unused\n- every dependency only those files used looks unused\n\nOne unreached entry can turn into dozens of findings. The chain also runs in\nreverse: add the entry, and the whole cascade collapses at once.\n\nSo read the output from the root down: **unused files first, then exports, then\ndependencies.** A single unused file usually explains a long list of results\nbelow it. Fix causes at the root and the rest disappears.\n\nSome chains only show up one run at a time. An export counts as used when\nanother file imports it, even if the importing code is unused. Remove that code,\nand the next run may report the export. Unused exports that import each other\nacross files are never reported.\n\n## A surprising result might be a gap, not a bug\n\nWhen Knip flags something you're sure is used, it's based on the graph: it\ncouldn't reach that code from an entry. The cause is usually one of:\n\n- a missing entry for a tool or convention Knip doesn't know yet\n- a dynamic import Knip can't follow statically, or a path it can't resolve\n- a transitive dependency of a package that resolves only because something else\n  installs it\n\nIn each case the fix is to teach Knip: add the entry, configure the plugin, list\nthe dependency. Don't hide the result. [Configuring project files][5] and\n[resolving reported issues][6] cover how, issue type by issue type.\n\n[1]: ../features/script-parser.md\n[2]: ../features/compilers.md\n[3]: ./entry-files.md\n[4]: ./plugins.md\n[5]: ../guides/configuring-project-files.md\n[6]: ../guides/handling-issues.mdx\n","frontmatter":{"title":"How Knip works","description":"The mental model behind Knip. How entry files, the module graph and reachability decide what counts as unused, and why surprising results trace back to them."},"isInternal":false,"tokens":931,"sizeBytes":4030},{"name":"plugins.md","path":"packages/docs/src/content/docs/explanations/plugins.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/explanations/plugins.md","title":"Explanations Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Plugins\ndescription: How Knip plugins work and the difference between `config` files (parsed for dependencies) and `entry` files (added to the module graph).\n---\n\nThis page describes why Knip uses plugins and the difference between `config`\nand `entry` files.\n\nKnip has an extensive and growing [list of built-in plugins][1]. Feel free to\n[write a plugin][2] so others can benefit too!\n\n## What does a plugin do?\n\nPlugins are enabled if the related package is listed in the list of dependencies\nin `package.json`. For instance, if `astro` is listed in `dependencies` or\n`devDependencies`, then the Astro plugin is enabled. And this means that this\nplugin will:\n\n- Handle [configuration files][3] like `astro.config.mjs`\n- Add [entry files][4] such as `src/pages/**/*.astro`\n- Define [command-line arguments][5]\n\n## Configuration files\n\nKnip uses [entry files][6] as starting points to scan your source code and\nresolve other internal files and external dependencies. The module graph can be\nstatically resolved through the `require` and `import` statements in those\nsource files. However, configuration files reference external dependencies in\nvarious ways. Knip uses a plugin for each tool to parse configuration files and\nfind those dependencies.\n\n### Example: ESLint\n\nIn the first example we look at [the ESLint plugin][7]. The default `config`\nfile patterns include `.eslintrc.json`. Here's a minimal example:\n\n```json title=\".eslintrc.json\"\n{\n  \"extends\": [\"airbnb\", \"prettier\"],\n  \"plugins\": [\"@typescript-eslint\"]\n}\n```\n\nConfiguration files like this don't `import` or `require` anything, but they do\nrequire the referenced dependencies to be installed.\n\nIn this case, the plugin will return three dependencies:\n\n- `eslint-config-airbnb`\n- `eslint-config-prettier`\n- `@typescript-eslint/eslint-plugin`\n\nKnip will then look for missing dependencies in `package.json` and report those\nas unlisted. And vice versa, if there are any ESLint plugins listed in\n`package.json`, but unused, those will be reported as well.\n\n### Example: Vitest\n\nThe second example uses [the Vitest plugin][8]. Here's a minimal example of a\nVitest configuration file:\n\n```ts title=\"vitest.config.ts\"\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    coverage: {\n      provider: 'istanbul',\n    },\n    environment: 'happy-dom',\n  },\n});\n```\n\nThe Vitest plugin reads this configuration and returns two dependencies:\n\n- `@vitest/coverage-istanbul`\n- `vitest-environment-happy-dom`\n\nKnip will look for missing and unused dependencies in `package.json` and report\naccordingly.\n\nSome tools allow configuration to be stored in `package.json`, that's why some\nplugins contain `package.json` in the list of `config` files.\n\n:::tip[Summary]\n\nPlugins load configuration files to find referenced dependencies, and determine\nunused and unlisted dependencies.\n\n:::\n\n## Entry files\n\nMany plugins have default `entry` files configured. When the plugin is enabled,\nKnip will add entry files as configured by the plugin to resolve used files and\ndependencies.\n\nFor example, if `next` is listed as a dependency in `package.json`, the Next.js\nplugin will automatically add multiple patterns as entry files, such as\n`pages/**/*.{js,jsx,ts,tsx}`. If `vitest` is listed, the Vitest plugin adds\n`**/*.{test,test-d,spec,spec-d}.ts` as entry file patterns. Most plugins have\nentry files configured, so you don't have to.\n\nIt's mostly plugins for meta frameworks and test runners that have `entry` files\nconfigured.\n\n:::tip[Plugins result in less configuration]\n\nPlugins use entry file patterns as defined in your configuration file of these\ntools. So you don't need to repeat this in your Knip configuration.\n\n:::\n\nFor example, let's say your Playwright configuration contains the following:\n\n```ts title=\"playwright.config.ts\"\nimport type { PlaywrightTestConfig } from '@playwright/test';\n\nconst config: PlaywrightTestConfig = {\n  testDir: 'integration',\n  testMatch: ['**/*-test.ts'],\n};\n\nexport default config;\n```\n\nThe Playwright plugin will read this configuration file and return those entry\npatterns (`integration/**/*-test.ts`). Knip will then not use the default entry\npatterns.\n\nYou can still override this behavior in your Knip configuration:\n\n```json title=\"knip.json\"\n{\n  \"playwright\": {\n    \"entry\": \"src/**/*.integration.ts\"\n  }\n}\n```\n\nThis should not be necessary though. Please consider opening a pull request or a\nbug report if any plugin is not behaving as expected.\n\n:::tip[Summary]\n\nPlugins try hard to automatically add the correct entry files.\n\n:::\n\n## Entry files from config files\n\nEntry files are part of plugin configuration (as described in the previous\nsection). Yet plugins can also return additional entry files after parsing\nconfiguration files. Below are some examples of configuration files parsed by\nplugins to return additional entry files. The goal of these examples is to give\nyou an idea about the various ways Knip and its plugins try to find entry files\nso you don't need to configure them yourself.\n\n### Angular\n\nThe Angular plugin parses the Angular configuration file. Here's a fragment:\n\n```json title=\"angular.json\"\n{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"projects\": {\n    \"knip-angular-example\": {\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit/build-angular:browser\",\n          \"options\": {\n            \"outputPath\": \"dist/knip-angular-example\",\n            \"main\": \"src/main.ts\",\n            \"tsConfig\": \"tsconfig.app.json\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nThis will result in `src/main.ts` being added as an entry file (and\n`@angular-devkit/build-angular` as a referenced dependency).\n\nAdditionally, the Angular plugin returns `tsconfig.app.json` as a configuration\nfile for the TypeScript plugin.\n\n### GitHub Actions\n\nThis plugin parses workflow YAML files. This fragment contains three `run`\nscripts:\n\n```yml title=\".github/workflows/deploy.yml\"\njobs:\n  integration:\n    runs-on: ubuntu-latest\n    steps:\n      - run: npm install\n      - run: node scripts/build.js\n      - run: node --loader tsx scripts/deploy.ts\n      - run: playwright test -c playwright.web.config.ts\n        working-directory: e2e\n```\n\nFrom these scripts, the `scripts/build.js` and `scripts/deploy.ts` files will be\nadded as entry files by the GitHub Actions plugin.\n\nAdditionally, the file `e2e/playwright.web.config.ts` is detected and will be\nhanded over as a Playwright configuration file.\n\nRead more about this in [command-line arguments][5].\n\n### webpack\n\nLet's take a look at this example webpack configuration file:\n\n```js title=\"webpack.config.js\"\nmodule.exports = env => {\n  return {\n    entry: {\n      main: './src/app.ts',\n      vendor: './src/vendor.ts',\n    },\n    module: {\n      rules: [\n        {\n          test: /\\.(woff|ttf|ico|woff2|jpg|jpeg|png|webp)$/i,\n          use: 'base64-inline-loader',\n        },\n      ],\n    },\n  };\n};\n```\n\nThe webpack plugin will parse this and add `./src/app.ts` and `./src/vendor.ts`\nas entry files. It will also add `base64-inline-loader` as a referenced\ndependency.\n\n:::tip[Summary]\n\nIn your config files, plugins can find additional entry files and also other\nconfig files recursively.\n\n:::\n\n## Bringing it all together\n\nSometimes a configuration file is a JavaScript or TypeScript file that imports\ndependencies, but also contains configuration that needs to be parsed by a\nplugin to find additional dependencies.\n\nLet's take a look at this example Vite configuration file:\n\n```ts title=\"vite.config.ts\"\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig(async ({ mode, command }) => {\n  return {\n    plugins: [react()],\n    test: {\n      setupFiles: ['./setup-tests.ts'],\n      environment: 'happy-dom',\n      coverage: {\n        provider: 'c8',\n      },\n    },\n  };\n});\n```\n\nThis file imports `vite` and `@vitejs/plugin-react` directly, but also\nindirectly references the `happy-dom` and `@vitest/coverage-c8` packages.\n\nThe Vite plugin of Knip will **dynamically** load this configuration file and\nparse the exported configuration. But it's not aware of the `vite` and\n`@vitejs/plugin-react` imports. This is why such `config` files are also\nautomatically added as `entry` files for Knip to **statically** resolve the\n`import` and `require` statements.\n\nAdditionally, `./setup-tests.ts` will be added as an `entry` file.\n\n:::note\n\nWhen plugins dynamically load configuration files, conditional dependencies may\nnot be detected if the condition evaluates differently during analysis. See\n[conditional or dynamic dependencies][9] for details and workarounds.\n\n:::\n\n## Command-Line Arguments\n\nPlugins may define the arguments where Knip should look for entry files,\nconfiguration files and dependencies. We've already seen some examples above:\n\n```sh\nnode --loader tsx scripts/deploy.ts\nplaywright test -c playwright.web.config.ts\n```\n\nPlease see [script parser][10] for more details.\n\n## Config File Location\n\nIf configuration files aren't in their default location and they are not\nreferenced through some script like `vite -c ./dir/vite.config.ts`, then make\nsure to tell Knip about it. Two examples:\n\n```json title=\"knip.jsonc\"\n{\n  \"playwright\": { \"config\": [\"e2e/playwright.config.ts\"] },\n  \"vite\": \"packages/*/vite.config.ts\" // shorthand without `config` and array notation\n}\n```\n\nThis is common in projects where a directory like `packages/lib` is not an\nactual workspace with a `package.json` file. Also see [integrated monorepos][11]\nfor similar cases.\n\n## Summary\n\n:::tip[Summary]\n\nPlugins are configured with two distinct types of files:\n\n- `config` files are dynamically loaded and parsed by the plugin\n- `entry` files are added to the module graph\n- Both can recursively lead to additional entry files, config files and\n  dependencies\n\n:::\n\n[1]: ../reference/plugins.md\n[2]: ../writing-a-plugin/index.md\n[3]: #configuration-files\n[4]: #entry-files\n[5]: #command-line-arguments\n[6]: ./entry-files.md\n[7]: ../reference/plugins/eslint.md\n[8]: ../reference/plugins/vitest.md\n[9]: ../guides/handling-issues.mdx#conditional-or-dynamic-dependencies\n[10]: ../features/script-parser.md\n[11]: ../features/integrated-monorepos.md\n","frontmatter":{"title":"Plugins","description":"How Knip plugins work and the difference between `config` files (parsed for dependencies) and `entry` files (added to the module graph)."},"isInternal":false,"tokens":2404,"sizeBytes":10252},{"name":"why-use-knip.md","path":"packages/docs/src/content/docs/explanations/why-use-knip.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/explanations/why-use-knip.md","title":"Explanations Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Why use Knip?\ndescription: Why remove unused files, exports and dependencies, and how Knip finds them comprehensively across greenfield and legacy (mono)repos.\n---\n\nThe value of removing clutter is clear, but finding it manually is tedious. Meet\nKnip: comprehensive and accurate results at any scale.\n\n:::tip[TL;DR]\n\nUnused files, exports and dependencies pile up as projects grow. Removing them\nimproves maintenance, performance, security and onboarding, and prevents\nregressions in CI. Knip automates finding (and fixing) all three,\ncomprehensively and at any scale.\n\n:::\n\n## Less is more\n\nThere are plenty of reasons to delete unused files, dependencies and \"dead\ncode\":\n\n- Easier maintenance: things are easier to manage when there's less of it.\n- Improved performance: startup time, build time and/or bundle size can be\n  negatively impacted when unused code, files and/or dependencies are included.\n  Relying on tree-shaking when bundling code helps, but it's not a silver\n  bullet.\n- Increased security: less code and dependencies means less room for weak spots.\n- Easier onboarding: there should be no doubts about whether files, dependencies\n  and exports are actually in use or not. Especially for people new to the\n  project and/or taking over responsibilities this is harder to grasp.\n- Prevent regressions: tools like TypeScript, ESLint and Prettier do all sorts\n  of checks and linting to report violations and prevent regressions. Knip does\n  the same for dependencies, exports and files that are obsolete.\n- Keeping dead code around has a negative value on readability, as it can be\n  misleading and distracting. Even if it serves no purpose it will need to be\n  maintained (source: [Safe dead code removal → YAGNI][1]).\n- Also see [Why are unused dependencies a problem?][2] and [Why are unused\n  exports a problem?][3].\n\n## Automation\n\nCode and dependency management is usually not the most exciting task for most of\nus. Knip's mission is to automate finding clutter. This is such a tedious job if\nyou were to do it manually, and where would you even start? Knip applies many\ntechniques and heuristics to report what you need and save a lot of time.\n\n:::tip\n\nKnip not only finds clutter, it can also [remove clutter][4]!\n\nUse Knip next to a linter like ESLint or Biome: after removing unused variables\ninside files, Knip might find even more unused code. Rinse and repeat!\n\n:::\n\n## Comprehensive\n\nYou can use alternative tools that do the same. However, the advantage of a\nstrategy that addresses all of dependencies, exports and files is in their\nsynergy:\n\n- Utilizing plugins to find their dependencies includes the capacity to find\n  additional entry and configuration files. This results in more resolved and\n  used files. Better coverage gives better insights into unused files and\n  exports.\n- Analyzing more files reveals more unused exports and dependency usage,\n  refining the list of both unused and unlisted dependencies.\n- This approach is amplified in a [monorepo setting][5]. In fact, files and\n  internal dependencies can recursively reference each other (across\n  workspaces).\n\nKnip reaches this coverage through [fine-grained entry points][6], [custom\nmodule resolution][7], [configuration-file parsers][8], an [advanced\nshell-script parser][9], and [built-in and custom compilers][10], then [fixes\nmost of it automatically][4].\n\n## Greenfield or Legacy\n\nInstalling Knip in greenfield projects ensures the project stays neat and tidy\nfrom the start. Add it to your CI workflow and prevent any regressions from\nentering the codebase.\n\n:::tip\n\nUse Knip in a CI environment to prevent future regressions.\n\n:::\n\nIn large and/or legacy projects, Knip may report false positives and require\nsome configuration. It aims to be a great assistant when cleaning up parts of\nthe project or doing large refactors. Even a list of results with a few false\npositives is many times better and faster than if you were to do it manually.\n\n## Unobtrusive\n\nKnip does not introduce new syntax for you to learn. This may sound obvious, but\nconsider comments like the following:\n\n```js\n// eslint-disable-next-line\n// prettier-ignore\n// @ts-expect-error\n```\n\nKnip doesn't have similar comments like `// knip-ignore` so you can get rid of\nfalse positives for a variety of reasons:\n\n1. A false positive may be a bug in Knip, and should be reported, not dismissed.\n2. Instead of proprietary comments, use [standardized annotations][11] that also\n   serve as documentation.\n3. In the event you want to remove Knip, just uninstall `knip` without having to\n   remove useless comments scattered throughout the codebase.\n\nTip: use `@lintignore` in JSDoc comments, so other linters can use the same.\n\n[1]: https://jfmengels.net/safe-dead-code-removal/#yagni-you-arent-gonna-need-it\n[2]: ../typescript/unused-dependencies.md#why-are-unused-dependencies-a-problem\n[3]: ../typescript/unused-exports.md#why-are-unused-exports-a-problem\n[4]: ../features/auto-fix.mdx\n[5]: ../features/monorepos-and-workspaces.md\n[6]: ./entry-files.md\n[7]: ../reference/faq.md#why-doesnt-knip-use-an-existing-module-resolver\n[8]: ./plugins.md#configuration-files\n[9]: ../features/script-parser.md\n[10]: ../features/compilers.md\n[11]: ../reference/jsdoc-tsdoc-tags.md\n","frontmatter":{"title":"Why use Knip?","description":"Why remove unused files, exports and dependencies, and how Knip finds them comprehensively across greenfield and legacy (mono)repos."},"isInternal":false,"tokens":1237,"sizeBytes":5258},{"name":"catalogs.md","path":"packages/docs/src/content/docs/features/catalogs.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/features/catalogs.md","title":"Features Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Catalogs\ndescription: How Knip finds unused pnpm, Yarn and Bun catalog entries referenced through the `catalog:` protocol, and removes them with auto-fix.\n---\n\nCatalogs let you define dependency version ranges once and reference them across\nworkspaces in a monorepo. Knip reports catalog entries that are defined but no\nlonger referenced, and references to entries that do not exist. It can remove\nunused entries with [auto-fix][1].\n\n## Supported catalogs\n\nKnip reads catalogs from the first applicable location:\n\n- `pnpm-workspace.yaml` — the `catalog` (default) and `catalogs` (named) keys\n- `.yarnrc.yml` — the `catalog` and `catalogs` keys\n- `package.json` — the `catalog` and `catalogs` keys\n- `package.json#workspaces` — the `catalog` and `catalogs` keys (Bun)\n\n## Unused catalog entries\n\nA catalog entry is reported as unused when no workspace references it through\nthe `catalog:` protocol in its `package.json`:\n\n```json title=\"packages/app/package.json\"\n{\n  \"dependencies\": {\n    \"react\": \"catalog:\",\n    \"zod\": \"catalog:validation\"\n  }\n}\n```\n\n`catalog:` references the `default` catalog, while `catalog:validation`\nreferences the named `validation` catalog. References are resolved from\n`dependencies`, `devDependencies`, `peerDependencies`, `optionalDependencies`,\n`resolutions`, `pnpm-workspace.yaml#overrides`, and `pnpm.overrides` in the root\n`package.json` (pnpm 10 and older).\n\nEntries defined in a catalog but not referenced anywhere are reported as [unused\ncatalog entries][2].\n\n## Unresolved catalog references\n\nA `catalog:` reference is reported when the selected catalog does not define\nthat package. These issues point to the consuming `package.json` or\n`pnpm-workspace.yaml`, where package managers would otherwise fail to resolve\nthe version.\n\n## Filter and fix\n\nThe `catalog` and `catalogReferences` issue types are included by the\n[`--dependencies`][3] shortcut. Focus on them (or exclude them) like any other\nissue type:\n\n```sh\nknip --include catalog,catalogReferences\nknip --exclude catalog,catalogReferences\n```\n\n[Auto-fix][1] removes unused catalog entries from the catalog file:\n\n```sh\nknip --fix --fix-type catalog\n```\n\n[1]: ./auto-fix.mdx#catalog-entries\n[2]: ../reference/issue-types.md\n[3]: ./rules-and-filters.md#shorthands\n","frontmatter":{"title":"Catalogs","description":"How Knip finds unused pnpm, Yarn and Bun catalog entries referenced through the `catalog:` protocol, and removes them with auto-fix."},"isInternal":false,"tokens":553,"sizeBytes":2279},{"name":"compilers.md","path":"packages/docs/src/content/docs/features/compilers.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/features/compilers.md","title":"Features Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Compilers\ndescription: Built-in and custom compilers let Knip analyze non-standard files like `.astro`, `.mdx`, `.svelte` and `.vue` for imports and exports.\n---\n\nProjects may have source files that are not JavaScript or TypeScript, and thus\nrequire compilation (or transpilation, or pre-processing, you name it). Files\nlike `.mdx`, `.astro`, `.vue` and `.svelte` may also import other source files\nand external dependencies. So ideally, these files are included when linting the\nproject. That's why Knip supports compilers.\n\n## Built-in compilers\n\nKnip has built-in \"compilers\" for the following file extensions:\n\n- `.astro`\n- `.css` (only enabled by `tailwindcss`)\n- `.mdx`\n- `.prisma`\n- `.sass` + `.scss`\n- `.less`\n- `.styl` + `.stylus`\n- `.svelte`\n- `.tsrx`\n- `.vue`\n\nKnip does not include real compilers for those files, but regular expressions to\ncollect `import` statements. This is fast, requires no dependencies, and enough\nfor Knip to build the module graph. The tradeoff is that unused exports inside\nthese files go unreported.\n\nReal compilers recover those exports, but bring their own challenges. The Svelte\ncompiler, for instance, keeps `exports` intact even when they represent\ncomponent properties, so Knip reports them as unused. When you need that\nfidelity, override any built-in with the framework's own compiler (see the\n[Svelte][1] and [Vue][2] examples below). For example, to report unused exports\nin [`.tsrx`][3] files.\n\nCompilers are enabled only when a related dependency is found. The `.tsrx`\ncompiler when a `@tsrx/*` package is installed, for example. If that detection\ndoesn't work for your project, set `true` to enable any compiler manually:\n\n```ts title=\"knip.ts\"\nexport default {\n  compilers: {\n    mdx: true,\n  },\n};\n```\n\n## Compiled files and `project` patterns\n\nThe default `project` patterns include compiler extensions automatically. When\nyou override `project`, list them explicitly:\n\n```ts title=\"knip.ts\"\nexport default {\n  project: ['src/**/*.{ts,tsx,css}'],\n};\n```\n\nFiles outside `project` are not analyzed, so their imports don't count. A\nnarrowed pattern like `['src/**/*.{ts,tsx}']` silently drops everything a\nstylesheet imports, which is a common source of false positives: `@import\n'tailwindcss'` in an excluded `.css` file gets `tailwindcss` reported as an\nunused dependency. Knip reports a configuration hint when a compiled extension\nis excluded this way.\n\n## Custom compilers\n\nBuilt-in compilers can be overridden, and additional compilers can be added.\nSince compilers are functions, the Knip configuration file must be a dynamic\n`.js` or `.ts` file.\n\n### Interface\n\nThe compiler function interface is straightforward. Text in, text out:\n\n```ts\n(source: string, filename: string) => string | PromiseLike<string>;\n```\n\nReturn a string or a Promise-like value that resolves to a string. Knip compiles\nfiles on demand and awaits asynchronous results; the `async` keyword is\noptional.\n\n### Examples\n\n- [CSS][4]\n- [MDX][5]\n- [Svelte][1]\n- [Vue][2]\n\n#### CSS\n\nHere's an example, minimal compiler for CSS files:\n\n```ts title=\"knip.ts\"\nexport default {\n  compilers: {\n    css: (text: string) => [...text.matchAll(/(?<=@)import[^;]+/g)].join('\\n'),\n  },\n};\n```\n\nYou may wonder why the CSS compiler is not included by default. It's currently\nnot clear if it should be included. And if so, what would be the best way to\ndetermine it should be enabled, and what syntax(es) it should support. Note that\nTailwind CSS, SASS/SCSS, Less and Stylus compilers are included.\n\n#### MDX\n\nAnother example, in case the built-in MDX compiler is not enough:\n\n```ts\nimport { compile } from '@mdx-js/mdx';\n\nexport default {\n  compilers: {\n    mdx: async text => (await compile(text)).toString(),\n  },\n};\n```\n\n#### Svelte\n\nIn a Svelte project, the compiler is automatically enabled. Override and use\nSvelte's compiler for better results if the built-in \"compiler\" is not enough:\n\n```ts\nimport type { KnipConfig } from 'knip';\nimport { compile } from 'svelte/compiler';\n\nexport default {\n  compilers: {\n    svelte: (source: string) => compile(source, {}).js.code,\n  },\n} satisfies KnipConfig;\n```\n\n#### Vue\n\nIn a Vue project, the compiler is automatically enabled. Override and use Vue's\nparser for better results if the built-in \"compiler\" is not enough:\n\n```ts\nimport type { KnipConfig } from 'knip';\nimport {\n  parse,\n  type SFCScriptBlock,\n  type SFCStyleBlock,\n} from 'vue/compiler-sfc';\n\nfunction getScriptBlockContent(block: SFCScriptBlock | null): string[] {\n  if (!block) return [];\n  if (block.src) return [`import '${block.src}'`];\n  return [block.content];\n}\n\nfunction getStyleBlockContent(block: SFCStyleBlock | null): string[] {\n  if (!block) return [];\n  if (block.src) return [`@import '${block.src}';`];\n  return [block.content];\n}\n\nfunction getStyleImports(content: string): string {\n  return [...content.matchAll(/(?<=@)import[^;]+/g)].join('\\n');\n}\n\nconst config = {\n  compilers: {\n    vue: (text: string, filename: string) => {\n      const { descriptor } = parse(text, { filename, sourceMap: false });\n      return [\n        ...getScriptBlockContent(descriptor.script),\n        ...getScriptBlockContent(descriptor.scriptSetup),\n        ...descriptor.styles.flatMap(getStyleBlockContent).map(getStyleImports),\n      ].join('\\n');\n    },\n  },\n} satisfies KnipConfig;\n\nexport default config;\n```\n\n## Tracking non-source files\n\nTo track any file extension that's not meant to compile to JavaScript, register\na no-op compiler:\n\n```ts title=\"knip.ts\"\nexport default {\n  compilers: { template: () => '' },\n};\n```\n\n[1]: #svelte\n[2]: #vue\n[3]: https://tsrx.dev\n[4]: #css\n[5]: #mdx\n","frontmatter":{"title":"Compilers","description":"Built-in and custom compilers let Knip analyze non-standard files like `.astro`, `.mdx`, `.svelte` and `.vue` for imports and exports."},"isInternal":false,"tokens":1424,"sizeBytes":5629},{"name":"custom-elements.md","path":"packages/docs/src/content/docs/features/custom-elements.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/features/custom-elements.md","title":"Features Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Custom Elements\ndescription: How Knip credits custom element classes registered via `customElements.define()` or Lit, FAST, Stencil and Catalyst decorators.\n---\n\nCustom elements are registered under a tag name. When such a class isn't\nreferenced elsewhere, Knip would report the export as unused. Instead, Knip\nrecognizes the registration and considers the class used.\n\nNative registration needs no configuration. Framework registrations are credited\nthrough their plugin, which is enabled when the framework is a dependency.\n\n## Native registration\n\nThe web standard `customElements.define()` credits the registered class:\n\n```ts\nexport class MyCard extends HTMLElement {}\n\ncustomElements.define('my-card', MyCard);\n```\n\nThe registry can be the global `customElements` — directly, through a `window`,\n`globalThis` or `self` prefix, or a local alias — a `CustomElementRegistry`\ninstance, or a shadow root's scoped registry:\n\n```ts\nconst registry = new CustomElementRegistry();\nregistry.define('my-card', MyCard);\n```\n\nA class can also register itself from a `static` block using `this`:\n\n```ts\nexport class MyCard extends HTMLElement {\n  static {\n    customElements.define('my-card', this);\n  }\n}\n```\n\n## Framework registration\n\n| Framework     | Plugin        | Registration                    | Imported from                                            |\n| ------------- | ------------- | ------------------------------- | -------------------------------------------------------- |\n| [Lit][1]      | [lit][2]      | `@customElement('tag')`         | `lit/decorators`, `lit-element`, `@lit/reactive-element` |\n| [FAST][3]     | [fast][4]     | `@customElement` or `.define()` | `@microsoft/fast-element`                                |\n| [Stencil][5]  | [stencil][6]  | `@Component({ tag })`           | `@stencil/core`                                          |\n| [Catalyst][7] | [catalyst][8] | `@controller`                   | `@github/catalyst`                                       |\n\nThe decorator counts only when imported from the framework. A locally defined or\ndifferently-imported decorator is ignored.\n\n### Lit\n\nA `@customElement('tag')` decorator credits the class when the matching plugin\nis enabled:\n\n```ts\nimport { LitElement } from 'lit';\nimport { customElement } from 'lit/decorators.js';\n\n@customElement('my-card')\nexport class MyCard extends LitElement {}\n```\n\n### FAST\n\n[FAST][3] also registers elements through a static `define()` or `defineAsync()`\nmethod. A class extending `FASTElement`, directly or through a mixin, is\ncredited when registered this way:\n\n```ts\nimport { FASTElement } from '@microsoft/fast-element';\n\nexport class MyCard extends FASTElement {}\n\nMyCard.define('my-card');\n```\n\n### Stencil\n\nA `@Component` decorator credits the class:\n\n```ts\nimport { Component } from '@stencil/core';\n\n@Component({ tag: 'my-card' })\nexport class MyCard {}\n```\n\n### Catalyst\n\nThe bare `@controller` decorator registers the element under a tag derived from\nthe class name:\n\n```ts\nimport { controller } from '@github/catalyst';\n\n@controller\nexport class MyCardElement extends HTMLElement {}\n```\n\n[1]: https://lit.dev\n[2]: ../reference/plugins/lit.md\n[3]: https://fast.design\n[4]: ../reference/plugins/fast.md\n[5]: https://stenciljs.com\n[6]: ../reference/plugins/stencil.md\n[7]: https://catalyst.rocks\n[8]: ../reference/plugins/catalyst.md\n","frontmatter":{"title":"Custom Elements","description":"How Knip credits custom element classes registered via `customElements.define()` or Lit, FAST, Stencil and Catalyst decorators."},"isInternal":false,"tokens":767,"sizeBytes":3377},{"name":"integrated-monorepos.md","path":"packages/docs/src/content/docs/features/integrated-monorepos.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/features/integrated-monorepos.md","title":"Features Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Integrated Monorepos\ndescription: Configure Knip for repositories with a single `package.json` and many projects, like the Nx integrated monorepo style.\n---\n\nSome repositories have a single `package.json`, but consist of multiple projects\nwith configuration files across the repository. A good example is the [Nx\nintegrated monorepo style][1].\n\n:::tip\n\nAn integrated monorepo is a single workspace.\n\n:::\n\n## Entry Files\n\nThe default entrypoints files might not be enough. Here's an idea that might fit\nthis type of monorepo:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"{apps,libs}/**/src/index.{ts,tsx}\"],\n  \"project\": [\"{apps,libs}/**/src/**/*.{ts,tsx}\"]\n}\n```\n\n## Plugins\n\nLet's assume some of these projects are applications (\"apps\") which have their\nown ESLint configuration files and Cypress configuration and test files. This\nmay result in those files getting reported as unused, and consequently also the\ndependencies they import and refer to.\n\nIn that case, we could configure the ESLint and Cypress plugins like this:\n\n```json title=\"knip.json\"\n{\n  \"eslint\": {\n    \"config\": [\"{apps,libs}/**/.eslintrc.json\"]\n  },\n  \"cypress\": {\n    \"entry\": [\"apps/**/cypress.config.ts\", \"apps/**/cypress/e2e/*.spec.ts\"]\n  }\n}\n```\n\nAdapt the file patterns to your project, and the relevant `config` and `entry`\nfiles and dependencies should no longer be reported as unused.\n\n## Internal Workspace Dependencies\n\nA note about repositories with multiple `package.json` files and **internal**\nworkspace packages: it is recommended to list all dependencies in each consuming\n`package.json`, allowing Knip to do fine-grained reporting of both unused and\nunlisted dependencies.\n\nAn alternative is to `ignoreDependencies: [\"@internal/*\"]`.\n\n[1]: https://nx.dev/getting-started/tutorials/integrated-repo-tutorial\n","frontmatter":{"title":"Integrated Monorepos","description":"Configure Knip for repositories with a single `package.json` and many projects, like the Nx integrated monorepo style."},"isInternal":false,"tokens":435,"sizeBytes":1806},{"name":"monorepos-and-workspaces.md","path":"packages/docs/src/content/docs/features/monorepos-and-workspaces.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/features/monorepos-and-workspaces.md","title":"Features Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Monorepos & Workspaces\ndescription: How Knip discovers and configures workspaces in package-based monorepos, with per-workspace options and the `--workspace` filter.\n---\n\nWorkspaces are handled out-of-the-box by Knip.\n\nWorkspaces are sometimes also referred to as package-based monorepos, or as\npackages in a monorepo. Knip uses the term workspace exclusively to indicate a\ndirectory that has a `package.json`.\n\n## Configuration\n\nHere's example configuration with custom `entry` and `project` patterns:\n\n```json title=\"knip.json\"\n{\n  \"workspaces\": {\n    \".\": {\n      \"entry\": \"scripts/*.js\",\n      \"project\": \"scripts/**/*.js\"\n    },\n    \"packages/*\": {\n      \"entry\": \"{index,cli}.ts\",\n      \"project\": \"**/*.ts\"\n    },\n    \"packages/cli\": {\n      \"entry\": \"bin/cli.js\"\n    }\n  }\n}\n```\n\n:::tip\n\nRun Knip without any configuration to see if and where custom `entry` and/or\n`project` files are necessary per workspace.\n\n:::\n\nEach workspace has the same [default configuration][1].\n\nThe root workspace is named `\".\"` under `workspaces` (like in the example\nabove).\n\n:::caution\n\nIn a project with workspaces, the `entry` and `project` options at the root\nlevel are ignored. Use the workspace named `\".\"` for those (like in the example\nabove).\n\n:::\n\n## Workspaces\n\nKnip reads workspaces from four possible locations:\n\n1. The `workspaces` array in `package.json` (npm, Bun, Yarn, Lerna)\n2. The `packages` array in `pnpm-workspace.yaml` (pnpm)\n3. The `workspaces.packages` array in `package.json` (legacy)\n4. The `workspaces` object in Knip configuration\n\nThe `workspaces` in Knip configuration (4) not already defined in the root\n`package.json` or `pnpm-workspace.yaml` (1, 2, 3) are added to the analysis.\n\n:::caution\n\nA workspace must have a `package.json` file.\n\n:::\n\nFor projects with only a root `package.json`, please see [integrated\nmonorepos][2].\n\n## Additional workspaces\n\nIf a workspace is not configured as such in `package.json#workspaces` (or\n`pnpm-workspace.yaml`) it can be added to the Knip configuration manually. Add\ntheir path to the `workspaces` configuration object the same way as\n`\"packages/cli\": {}` in the example above.\n\n## Source mapping\n\nSee [Source Mapping][3].\n\n## Additional options\n\nThe following options are available inside workspace configurations:\n\n- [ignore][4]\n- [ignoreBinaries][5]\n- [ignoreDependencies][6]\n- [ignoreIssues][7]\n- [ignoreMembers][8]\n- [ignoreUnresolved][9]\n- [includeEntryExports][10]\n\n[Plugins][11] can be configured separately per workspace.\n\nUse `--debug` for verbose output and see the workspaces Knip includes, their\nconfigurations, enabled plugins, glob options and resolved files.\n\n## Filter workspaces\n\nUse the `--workspace` (or `-W`) argument to select one or more workspaces:\n\n```sh\nknip --workspace packages/my-lib\n```\n\nThe filter supports multiple formats:\n\n```sh\nknip --workspace @myorg/my-lib     # Package name\nknip --workspace '@myorg/*'        # Package name glob\nknip --workspace packages/my-lib   # Directory path\nknip --workspace './apps/*'        # Directory glob\n```\n\nCombine selectors to include or exclude workspaces:\n\n```sh\nknip --workspace @myorg/* --workspace '!@myorg/legacy'\nknip --workspace './apps/*' --workspace '@shared/utils'\n```\n\nThis will include the target workspace(s), but also ancestor, dependency and\ndependent workspaces. For three reasons:\n\n- Ancestor workspaces may list dependencies in `package.json` the linted\n  workspace uses.\n- Dependency workspaces may provide configuration and source information used by\n  the linted workspace.\n- Dependent workspaces may reference exports from the linted workspace.\n\nTo lint the workspace in isolation, there are two options:\n\n- Combine the `workspace` argument with [strict production mode][12].\n- Run Knip from inside the workspace directory.\n\n[1]: ../overview/configuration.md#defaults\n[2]: ./integrated-monorepos.md\n[3]: ./source-mapping.md\n[4]: ../reference/configuration.md#ignore\n[5]: ../reference/configuration.md#ignorebinaries\n[6]: ../reference/configuration.md#ignoredependencies\n[7]: ../reference/configuration.md#ignoreissues\n[8]: ../reference/configuration.md#ignoremembers\n[9]: ../reference/configuration.md#ignoreunresolved\n[10]: ../reference/configuration.md#includeentryexports\n[11]: ../reference/configuration.md#plugins\n[12]: ./production-mode.md#strict-mode\n","frontmatter":{"title":"Monorepos & Workspaces","description":"How Knip discovers and configures workspaces in package-based monorepos, with per-workspace options and the `--workspace` filter."},"isInternal":false,"tokens":1070,"sizeBytes":4326},{"name":"production-mode.md","path":"packages/docs/src/content/docs/features/production-mode.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/features/production-mode.md","title":"Features Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Production Mode\ndescription: Use `--production` and `--strict` with `!` entry patterns to lint only shipped code, ignoring tests, stories and config files.\n---\n\nThe default mode for Knip is comprehensive and targets all project code,\nincluding configuration files, test files, Storybook stories, and so on. Test\nfiles usually import production files. This prevents production files or their\nexports from being reported as unused, while sometimes both of them can be\ndeleted. Knip features a \"production mode\" to focus only on the code that you\nship.\n\n## Configuration\n\nTo tell Knip what is production code, add an exclamation mark behind each\n`pattern!` that represents production code:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts!\", \"build/script.js\"],\n  \"project\": [\"src/**/*.ts!\", \"build/*.js\"]\n}\n```\n\nDepending on file structure and enabled plugins, you might not need to modify\nyour configuration at all.\n\nRun Knip with the `--production` flag:\n\n```sh\nknip --production\n```\n\nHere's what's included in production mode:\n\n- Only `entry` and `project` patterns suffixed with `!`\n- Only production `entry` file patterns exported by plugins (such as Next.js and\n  Remix)\n- Only the `start` script (of `package.json#scripts`)\n- Ignore exports with the [`@internal` tag][1]\n\n:::note\n\nThe production run does not replace the default run. Depending on your needs you\ncan run either of them or both separately. Usually both modes can share the same\nconfiguration.\n\n:::\n\nTo see the difference between default and production mode in great detail, use\nthe `--debug` flag and inspect what entry and project files are used, and the\nplugins that are enabled. For instance, in production mode this shows that files\nsuch as tests and Storybook files (stories) are excluded from the analysis.\n\nIn case files like mocks and test helpers are reported as unused files, use\nnegated patterns to exclude those files in production mode:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts!\"],\n  \"project\": [\"src/**/*.ts!\", \"!src/test-helpers/**!\"]\n}\n```\n\nAlso see [configuring project files][2] to align `entry` and `project` with\nproduction mode.\n\n## Strict Mode\n\nIn production mode, only `dependencies` (not `devDependencies`) are considered\nwhen finding unused or unlisted dependencies.\n\nAdditionally, the `--strict` flag can be added to:\n\n- Verify isolation: workspaces should use strictly their own `dependencies`\n- Include required `peerDependencies` when finding unused or unlisted\n  dependencies\n- [Distinguish development-only type imports from types exposed to package\n  consumers][3]\n\n```sh\nknip --production --strict\n```\n\nUsing `--strict` implies `--production`, so the latter can be omitted.\n\n## Types\n\nAdd `--exclude types` if you don't want to include types in the report:\n\n```sh\nknip --production --exclude types\n```\n\n[1]: ../reference/jsdoc-tsdoc-tags.md#internal\n[2]: ../guides/configuring-project-files.md\n[3]: ../guides/handling-issues.mdx#production-types\n","frontmatter":{"title":"Production Mode","description":"Use `--production` and `--strict` with `!` entry patterns to lint only shipped code, ignoring tests, stories and config files."},"isInternal":false,"tokens":698,"sizeBytes":2980},{"name":"reporters.md","path":"packages/docs/src/content/docs/features/reporters.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/features/reporters.md","title":"Features Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Reporters & Preprocessors\ndescription: Knip's built-in reporters (including the shape of `knip --reporter json` for scripts, CI and coding agents), plus custom reporters and preprocessors.\n---\n\n## Built-in Reporters\n\nKnip provides the following built-in reporters:\n\n- [`codeclimate`][1]\n- [`codeowners`][2]\n- `compact`\n- [`cycles`][3]\n- [`disclosure`][4]\n- [`github-actions`][5]\n- [`json`][6]\n- [`markdown`][7]\n- [`sarif`][8]\n- `symbols` (default)\n\nExample usage:\n\n```sh\nknip --reporter compact\n```\n\n### CodeClimate\n\nThe built-in `codeclimate` reporter generates output in the Code Climate Report\nJSON format. Example usage:\n\n```text\n$ knip --reporter codeclimate\n\n[\n  {\n    \"type\": \"issue\",\n    \"check_name\": \"Unused exports\",\n    \"description\": \"isUnused\",\n    \"categories\": [\"Bug Risk\"],\n    \"location\": {\n      \"path\": \"path/to/file.ts\",\n      \"positions\": {\n        \"begin\": {\n          \"line\": 6,\n          \"column\": 1\n        }\n      }\n    },\n    \"severity\": \"major\",\n    \"fingerprint\": \"e9789995c1fe9f7d75eed6a0c0f89e84\"\n  }\n]\n```\n\n### CODEOWNERS\n\nWhen a `.github/CODEOWNERS` file exists, each entry gains an `owners` array.\nPoint the reporter at a different path through [`--reporter-options`][9]:\n\n```sh\nknip --reporter json --reporter-options '{\"codeowners\":\"docs/CODEOWNERS\"}'\n```\n\n### Cycles\n\nA verbose, multi-line tree view of [circular dependencies][10]. Each file path\nis suffixed with the location of the import that continues the cycle. Each edge\nshows the import kind and specifier, descends one file per level, and closes\n(`↩`) back to the file it started from.\n\nUse `--cycles` to report only circular dependencies and `--reporter cycles` to\ndisplay them as a tree:\n\n```text\n$ knip --cycles --reporter cycles\n\nCircular dependencies (1)\n\nsrc/i18n/index.ts:1:28\n└── import ./middleware → src/i18n/middleware.ts:3:15\n    └── re-export ../core/i18n/handler → src/core/i18n/handler.ts:5:10\n        └── import ../../i18n → src/i18n/index.ts:1:28 ↩\n```\n\nKnip reports representative cycle paths found while walking the module graph.\nThis is not an exhaustive list of every possible simple cycle in a cyclic\nsubgraph, because that can produce a noisy and very large report. If the same\nfile participates in multiple distinct reported paths, each path is shown\nseparately.\n\nUse [`cycles.allow`][11] to accept known cycle paths.\n\nDynamic imports are ignored by default because they are commonly used to avoid\nsynchronous circular loads. Set [`cycles.dynamicImports`][11] to include them.\nRepeated starting imports are grouped under one heading.\n\nFor one line per cycle path, use `knip --cycles` with the default reporter. To\nreport unused code as well, [combine the issue-type shorthands][12].\n\nCycles are warnings by default. Set `\"rules\": { \"cycles\": \"error\" }` to make\nreported cycles cause a non-zero exit code.\n\n### Disclosure\n\nThis reporter is useful for sharing large reports. Groups of issues are rendered\nin a closed state initially. The reporter renders this:\n\n````text\n$ knip --reporter disclosure\n\n<details>\n<summary>Unused files (2)</summary>\n\n```\nunused.ts\ndangling.js\n```\n\n</details>\n\n<details>\n<summary>Unused dependencies (2)</summary>\n\n```\nmy-package     package.json:17:5\nunused-dep     package.json:20:5\n```\n\n</details>\n````\n\nThe above can be copy-pasted where HTML and Markdown is supported, such as a\nGitHub issue or pull request, and renders like so:\n\n<details>\n  <summary>Unused files (2)</summary>\n\n```\nunused.ts\ndangling.js\n```\n\n</details>\n\n<details>\n  <summary>Unused dependencies (2)</summary>\n\n```\nmy-package     package.json:17:5\nunused-dep     package.json:20:5\n```\n\n</details>\n\n### GitHub Actions\n\nUse the GitHub Actions reporter in a workflow for annotations in pull requests.\nExample usage:\n\n```sh\nknip --reporter github-actions\n```\n\nChanged files in pull requests will now contain inline annotations for lint\nfindings.\n\n### JSON\n\nThe `json` reporter prints machine-readable results for scripts, CI, and tools\n(including coding agents) to consume:\n\n```sh\nknip --reporter json\n```\n\nOutput is one line of JSON. Formatted here for readability:\n\n```json\n{\n  \"issues\": [\n    {\n      \"file\": \"src/legacy.ts\",\n      \"files\": [{ \"name\": \"src/legacy.ts\" }]\n    },\n    {\n      \"file\": \"src/math.ts\",\n      \"exports\": [{ \"name\": \"factorial\", \"line\": 12, \"col\": 14, \"pos\": 256 }],\n      \"types\": [{ \"name\": \"Radians\", \"line\": 20, \"col\": 13, \"pos\": 410 }]\n    },\n    {\n      \"file\": \"package.json\",\n      \"dependencies\": [{ \"name\": \"lodash\" }],\n      \"unlisted\": [{ \"name\": \"rimraf\" }]\n    }\n  ]\n}\n```\n\nThe top level is an object with a single `issues` array. Each element groups\nevery issue found in one file:\n\n| Field        | Type         | Notes                                               |\n| :----------- | :----------- | :-------------------------------------------------- |\n| `file`       | `string`     | Path relative to the working directory              |\n| `owners`     | `{ name }[]` | Code owners, only when a `CODEOWNERS` file is found |\n| _issue type_ | array        | One key per enabled issue type (see below)          |\n\nEach entry carries a key for **every enabled [issue type][10]**, so the keys are\nthe same across entries. An array is empty when that file has no issues of that\ntype. Drop a type's key by disabling it with [filters or rules][12].\n\nIssue-type items are objects with position info:\n\n| Field       | Type      | Notes                                          |\n| :---------- | :-------- | :--------------------------------------------- |\n| `name`      | `string`  | The unused symbol, dependency, file, or import |\n| `namespace` | `string?` | Set for namespace members                      |\n| `line`      | `number?` | 1-based line                                   |\n| `col`       | `number?` | 1-based column                                 |\n| `pos`       | `number?` | Character offset                               |\n\nSee [Issue types][10] for the full set of issue-type keys.\n\nFor a typed object instead of JSON to parse, write a [custom reporter][13].\nCoding agents can also call Knip through the [MCP server][14], which returns\nstructured results and configuration hints directly.\n\n### SARIF\n\nThe `sarif` reporter emits [SARIF 2.1.0][15] for code-scanning integrations:\n\n```sh\nknip --reporter sarif > knip.sarif\n```\n\nFor example, upload the report to GitHub Code Scanning after installing project\ndependencies:\n\n```yaml\npermissions:\n  contents: read\n  security-events: write\n\nsteps:\n  - uses: actions/checkout@v4\n  - run: pnpm exec knip --reporter sarif > knip.sarif\n  - if: always()\n    uses: github/codeql-action/upload-sarif@v4\n    with:\n      sarif_file: knip.sarif\n```\n\nThe upload step runs even when Knip finds issues and exits non-zero. GitHub Code\nScanning availability for private repositories depends on the repository's\nGitHub Code Security plan.\n\n### Markdown\n\nThe built-in `markdown` reporter output is meant to be saved to a Markdown file.\nThis allows following the changes in issues over time. It reports issues in\nMarkdown tables separated by issue types as headings, for example:\n\n```md\n# Knip report\n\n## Unused files (1)\n\n- src/unused.ts\n\n## Unlisted dependencies (2)\n\n| Name            | Location          | Severity |\n| :-------------- | :---------------- | :------- |\n| unresolved      | src/index.ts:8:23 | error    |\n| @org/unresolved | src/index.ts:9:23 | error    |\n\n## Unresolved imports (1)\n\n| Name         | Location           | Severity |\n| :----------- | :----------------- | :------- |\n| ./unresolved | src/index.ts:10:12 | error    |\n```\n\n## Custom Reporters\n\nWhen the provided built-in reporters are not sufficient, a custom local reporter\ncan be implemented or an external reporter can be used. Multiple reporters can\nbe used at once by repeating the `--reporter` argument.\n\nThe results are passed to the function from its default export and can be used\nto write issues to `stdout`, a JSON or CSV file, or sent to a service. It\nsupports a local JavaScript or TypeScript file or an external dependency.\n\n### Local\n\nThe default export of the reporter should be a function with this interface:\n\n```ts\ntype Reporter = (options: ReporterOptions) => void;\n\ntype ReporterOptions = {\n  report: Report;\n  issues: Issues;\n  counters: Counters;\n  configurationHints: ConfigurationHints;\n  isDisableConfigHints: boolean;\n  isTreatConfigHintsAsErrors: boolean;\n  cwd: string;\n  isProduction: boolean;\n  isShowProgress: boolean;\n  options: string;\n};\n```\n\nThe data can then be used to write issues to `stdout`, a JSON or CSV file, or\nsent to a service.\n\nHere's a most minimal reporter example:\n\n```ts title=\"./my-reporter.ts\"\nimport type { Reporter } from 'knip';\n\nconst reporter: Reporter = function (options) {\n  console.log(options.issues);\n  console.log(options.counters);\n};\n\nexport default reporter;\n```\n\nExample usage:\n\n```sh\nknip --reporter ./my-reporter.ts\n```\n\n### External\n\nPass `--reporter [pkg-name]` to use an external reporter. The default exported\nfunction of the `main` script (default: `index.js`) will be invoked with the\n`ReporterOptions`, just like a local reporter.\n\n## Preprocessors\n\nA preprocessor is a function that runs after the analysis is finished. It\nreceives the results from the analysis and should return data in the same\nshape/structure (unless you pass it to only your own reporter).\n\nThe data goes through the preprocessors before the final data is passed to the\nreporters. There are no built-in preprocessors. Just like reporters, use e.g.\n`--preprocessor ./my-preprocessor` from the command line (can be repeated).\n\nThe default export of the preprocessor should be a function with this interface:\n\n```ts\ntype Preprocessor = (options: ReporterOptions) => ReporterOptions;\n```\n\nLike reporters, you can use local JavaScript or TypeScript files and external\nnpm packages as preprocessors.\n\nExample preprocessor:\n\n```ts title=\"./preprocess.ts\"\nimport type { Preprocessor } from 'knip';\n\nconst preprocess: Preprocessor = function (options) {\n  // modify options.issues and options.counters\n  return options;\n};\n\nexport default preprocess;\n```\n\nExample usage:\n\n```sh\nknip --preprocessor ./preprocess.ts\n```\n\nPreprocessors can also be configured in the Knip configuration file:\n\n```json title=\"knip.json\"\n{\n  \"preprocessor\": \"./preprocess.ts\"\n}\n```\n\n[1]: #codeclimate\n[2]: #codeowners\n[3]: #cycles\n[4]: #disclosure\n[5]: #github-actions\n[6]: #json\n[7]: #markdown\n[8]: #sarif\n[9]: ../reference/cli.md#--reporter-options-json\n[10]: ../reference/issue-types.md\n[11]: ../reference/configuration.md#cycles\n[12]: ./rules-and-filters.md\n[13]: #custom-reporters\n[14]: ../reference/integrations.md\n[15]: https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html\n","frontmatter":{"title":"Reporters & Preprocessors","description":"Knip's built-in reporters (including the shape of `knip --reporter json` for scripts, CI and coding agents), plus custom reporters and preprocessors."},"isInternal":false,"tokens":2704,"sizeBytes":10727},{"name":"rules-and-filters.md","path":"packages/docs/src/content/docs/features/rules-and-filters.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/features/rules-and-filters.md","title":"Features Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Rules & Filters\ndescription: Customize Knip's output with `--include`/`--exclude` filters, shorthand flags and `rules` to set issue types to error, warn or off.\n---\n\nUse rules or filters to customize Knip's output. This has various use cases, a\nfew examples:\n\n- Temporarily focus on a specific issue type.\n- You don't want to see unused `type`, `interface` and `enum` exports reported.\n- Specific issue types should be printed, but not counted against the total\n  error count.\n\nIf you're looking to handle one-off exceptions, also see [JSDoc tags][1].\n\n## Filters\n\nYou can `--include` or `--exclude` any of the reported issue types to slice &\ndice the report to your needs. Alternatively, they can be added to the\nconfiguration (e.g. `\"exclude\": [\"dependencies\"]`).\n\nUse `--include` to report only specific issue types. The following example\ncommands do the same:\n\n```sh\nknip --include files --include dependencies\nknip --include files,dependencies\n```\n\nOr the other way around, use `--exclude` to ignore the types you're not\ninterested in:\n\n```sh\nknip --include files --exclude enumMembers,duplicates\n```\n\nThe `nsExports` and `nsTypes` types are [off by default][2]. Including only\nthose _adds_ them to the default report, rather than narrowing it to just those.\n\n`cycles` is also off by default. `--include cycles` (or `\"include\": [\"cycles\"]`\nin configuration) reports only circular dependencies. Use it with the [cycles\nreporter][3] for a detailed tree view.\n\nAlso see the [list of issue types][4].\n\n### Shorthands\n\nKnip has shortcuts to report only specific issue types.\n\n1. The `--dependencies` flag includes:\n   - `dependencies` (and `devDependencies` + `optionalPeerDependencies`)\n   - `unlisted`\n   - `binaries`\n   - `unresolved`\n   - `catalog`\n   - `catalogReferences`\n\n2. The `--exports` flag includes:\n   - `exports`\n   - `types`\n   - `enumMembers`\n   - `namespaceMembers`\n   - `duplicates`\n\n3. The `--files` flag is a shortcut to report only unused files.\n\n4. The `--cycles` flag is a shortcut to report only circular dependencies.\n\nCombine shorthands to report the default issue types plus circular dependencies:\n\n```sh\nknip --dependencies --exports --files --cycles\n```\n\n## Rules\n\nUse `rules` in the configuration to customize the issue types that count towards\nthe total error count, or to exclude them altogether.\n\n| Value     | Default | Printed | Counted | Description                       |\n| :-------- | :-----: | :-----: | :-----: | :-------------------------------- |\n| `\"error\"` |   ✓ ¹   |    ✓    |    ✓    | Similar to the `--include` filter |\n| `\"warn\"`  |    -    |    ✓    |    -    | Printed in faded/gray color       |\n| `\"off\"`   |    -    |    -    |    -    | Similar to the `--exclude` filter |\n\nExample:\n\n```json title=\"knip.json\"\n{\n  \"rules\": {\n    \"files\": \"warn\",\n    \"duplicates\": \"off\"\n  }\n}\n```\n\nNotes:\n\n- ¹ Exception: the `cycles` issue type is a warning by default.\n- If the `dependencies` issue type is included, the `devDependencies` and\n  `optionalPeerDependencies` types can still be set to `\"warn\"` separately.\n- The rules are modeled after the ESLint `rules` configuration, and could be\n  extended in the future.\n\nAlso see the [issue types overview][4].\n\n## Rules or filters?\n\nFilters are meant to be used as command-line flags, rules allow for more\nfine-grained configuration.\n\n- Rules are more fine-grained since they also have \"warn\".\n- Rules could be extended in the future.\n- Filters can be set in configuration and from CLI (rules only in\n  configuration).\n- Filters have shorthands (rules don't have this).\n\n[1]: ../reference/jsdoc-tsdoc-tags.md\n[2]: ../guides/namespace-imports.md\n[3]: ./reporters.md#cycles\n[4]: ../reference/issue-types.md\n","frontmatter":{"title":"Rules & Filters","description":"Customize Knip's output with `--include`/`--exclude` filters, shorthand flags and `rules` to set issue types to error, warn or off."},"isInternal":false,"tokens":936,"sizeBytes":3721},{"name":"script-parser.md","path":"packages/docs/src/content/docs/features/script-parser.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/features/script-parser.md","title":"Features Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Script Parser\ndescription: How Knip statically parses shell scripts and CLI arguments in `package.json`, plugins and source code to find entry files and dependencies.\n---\n\nKnip parses shell commands and scripts to find additional dependencies, entry\nfiles and configuration files in various places:\n\n- In [`package.json`][1]\n- In [CLI arguments][2]\n- In [scripts][3]\n- In [source code][4]\n\nShell scripts are parsed and statically analyzed, but they're not executed.\n\n## package.json\n\nThe `main`, `bin`, `exports` and `scripts` fields may contain entry files. Let's\ntake a look at this example:\n\n```json title=\"package.json\"\n{\n  \"name\": \"my-package\",\n  \"main\": \"index.js\",\n  \"exports\": {\n    \"./lib\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./dist/index.cjs\"\n    }\n  },\n  \"bin\": {\n    \"program\": \"bin/cli.js\"\n  },\n  \"scripts\": {\n    \"build\": \"rollup src/entry.ts\",\n    \"start\": \"node --loader tsx server.ts\"\n  }\n}\n```\n\nFrom this example, Knip automatically adds the following files as entry files:\n\n- `index.js`\n- `./dist/index.mjs`\n- `./dist/index.cjs`\n- `bin/cli.js`\n- `src/entry.ts`\n- `server.ts`\n\n### Excluded files\n\nKnip would not add the `exports` if the `dist` folder is matching a pattern in a\nrelevant `.gitignore` file or `ignore` option.\n\nKnip does not add scripts without a standard extension. For instance, the\n`bin/tool` file might be a valid executable for Node.js, but wouldn't be added\nor parsed by Knip.\n\n### CLI Arguments\n\nWhen parsing the `scripts` of `package.json` and other files, Knip detects\nvarious types of inputs. Some examples:\n\n- The first positional argument is usually an entry file\n- Configuration files are often in the `-c` or `--config` argument\n- The `--require`, `--loader` or `--import` arguments are often dependencies\n\n```json\n{\n  \"name\": \"my-lib\",\n  \"scripts\": {\n    \"start\": \"node --import tsx/esm run.ts\",\n    \"bundle\": \"tsup -c tsup.lib.config.ts\",\n    \"type-check\": \"tsc -p tsconfig.app.json\"\n  }\n}\n```\n\nThe `\"start\"` script will have `tsx` marked as a referenced dependency, and adds\n`run.ts` as an entry file.\n\nAdditionally, the following files are detected as configuration files:\n\n- `tsup.lib.config.ts` - to be handled by the tsup plugin\n- `tsconfig.app.json` - to be handled by the TypeScript plugin\n\nSuch executables and their arguments are all defined in plugins separately for\nfine-grained results.\n\n## Scripts\n\nPlugins may also use the script parser to extract entry files and dependencies\nfrom commands. A few examples:\n\n- GitHub Actions: workflow files may contain `run` commands (e.g.\n  `.github/workflows/ci.yml`)\n- Husky & Lefthook: Git hooks such as `.git/hooks/pre-push` contain scripts;\n  also `lefthook.yml` has `run` commands\n- Lint Staged: configuration values are all commands\n- Nx: task executors and `nx:run-commands` executors in `project.json` contains\n  scripts\n- Release It: `hooks` contain commands\n\nPlugins can also return configuration files. Some examples:\n\n- The Angular plugin detects `options.tsConfig` as a TypeScript config file\n- The GitHub Actions plugin parses `run` commands which may contain\n  configuration file paths\n\n## Source Code\n\nWhen Knip is walking the abstract syntax trees (ASTs) of JavaScript and\nTypeScript source code files, it looks for imports and exports. But there's a\nfew more (rather obscure) things that Knip detects in the process. Below are\nexamples of additional scripts Knip parses to find entry files and dependencies.\n\n### bun\n\nIf the `bun` dependency is imported in source code, Knip considers the contents\nof `$` template tags to be scripts:\n\n```ts\nimport { $ } from 'bun';\nawait $`bun boxen I ❤ unicorns`;\nawait $`boxen I ❤ unicorns`;\n```\n\nParsing the script results in the `boxen` binary (the `boxen-cli` dependency) as\nreferenced (twice).\n\n### execa\n\nIf the `execa` dependency is imported in source code, Knip considers the\ncontents of `$` template tags to be scripts:\n\n```ts\nawait $({ stdio: 'inherit' })`c8 node hydrate.js`;\n```\n\nParsing the script results in `hydrate.js` added as an entry file and the `c8`\nbinary/dependency as referenced. The `execa()`, `execaSync()`, `execaCommand()`\nand `execaCommandSync()` call forms are parsed the same way.\n\n### zx\n\nIf the `zx` dependency is imported in source code, Knip considers the contents\nof `$` template tags to be scripts:\n\n```ts\nawait $`node scripts/parse.js`;\n```\n\nThis will add `scripts/parse.js` as an entry file.\n\n### child\\_process\n\nIf `node:child_process` is imported in source code, Knip parses the command in\n`exec`/`execSync` calls and the executable (with its arguments) in\n`spawn`/`spawnSync`/`execFile`/`execFileSync` calls:\n\n```ts\nimport { execSync, execFile } from 'node:child_process';\nexecSync('eslint --cache');\nexecFile('boxen', ['I ❤ unicorns']);\n```\n\nThis marks the `eslint` and `boxen` binaries as referenced. An inline\n`path.join(__dirname, …)` argument to `spawn`, `execFile` or `fork` is added as\nan entry file instead.\n\n### nano-spawn\n\nIf `nano-spawn` is imported in source code, Knip parses the executable and its\narguments:\n\n```ts\nimport spawn from 'nano-spawn';\nawait spawn('gsutil', ['cp', './file.txt', 'gs://bucket/']);\n```\n\nThis marks the `gsutil` binary as referenced.\n\n[1]: #packagejson\n[2]: #cli-arguments\n[3]: #scripts\n[4]: #source-code\n","frontmatter":{"title":"Script Parser","description":"How Knip statically parses shell scripts and CLI arguments in `package.json`, plugins and source code to find entry files and dependencies."},"isInternal":false,"tokens":1385,"sizeBytes":5280},{"name":"source-mapping.md","path":"packages/docs/src/content/docs/features/source-mapping.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/features/source-mapping.md","title":"Features Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Source Mapping\ndescription: How Knip maps build artifacts in `dist`/`outDir` back to their original source files using `tsconfig.json` to avoid false positives.\n---\n\nKnip is mostly interested in source code. Analyzing build artifacts hurts\nperformance and often leads to false positives, as they potentially contain\nbundled code and unresolvable imports.\n\nThat's why Knip tries to map such build artifacts back to their original source\nfiles and analyze those instead. This is done based on `tsconfig.json` settings.\n\n## Example 1: package.json\n\nLet's look at an example case with `package.json` and `tsconfig.json` files, and\nsee how \"dist\" files are mapped to \"src\" files.\n\n```jsonc title=\"package.json\"\n{\n  \"name\": \"my-workspace\",\n  \"main\": \"index.js\",\n  \"exports\": {\n    \".\": \"./src/entry.js\",\n    \"./feat\": \"./lib/feat.js\",\n    \"./public\": \"./dist/app.js\",\n    \"./public/*\": \"./dist/*.js\",\n    \"./public/*.js\": \"./dist/*.js\",\n    \"./dist/internal/*\": null,\n  },\n}\n```\n\nWith this TypeScript configuration:\n\n```json title=\"tsconfig.json\"\n{\n  \"compilerOptions\": {\n    \"baseUrl\": \"src\",\n    \"outDir\": \"dist\"\n  }\n}\n```\n\n- `./src/entry.js` is not in an `outDir` folder, so it's added as an entry file\n- `./lib/feat.js` is not in an `outDir` folder, so it's added as an entry file\n- `./dist/app.js` is in a `dist` folder and mapped to `./src/app.{js,ts}` (¹)\n- `./dist/*.js` is in a `dist` folder and mapped to `./src/**/*.{js,ts}` (¹)\n- `./dist/internal/*` is translated to `./dist/internal/**` and files in this\n  directory and deeper are ignored when globbing entry files\n\n(¹) full extensions list is actually: `js`, `mjs`, `cjs`, `jsx`, `ts`, `tsx`,\n`mts`, `cts`\n\nIn `--debug` mode, look for \"Source mapping\" to see this in action.\n\n:::tip\n\nUsing `./dist/*.js` means that all files matching `./src/**/*.{js,ts}` are added\nas entry files. By default, unused exports of entry files are not reported. Use\n[includeEntryExports][1] to include them.\n\n:::\n\n## Example 2: monorepo\n\nLet's say we have this module in a monorepo that imports `helper` from another\nworkspace in the same monorepo:\n\n```ts title=\"index.js\"\nimport { helper } from '@org/shared';\n```\n\nThe target workspace `@org/shared` has this `package.json`:\n\n```json title=\"package.json\"\n{\n  \"name\": \"@org/shared\",\n  \"main\": \"dist/index.js\"\n}\n```\n\nThe module resolver will resolve `@org/shared` to `dist/index.js`. That file is\nusually compiled and git-ignored, while Knip wants the source file instead.\n\n:::tip\n\nYou may need to compile build artifacts to `outDir` first before Knip can\nsuccessfully apply source mapping for internal references in a monorepo.\n\n:::\n\nIf the target workspace has a `tsconfig.json` file with an `outDir` option, Knip\nwill try to map the \"dist\" file to the \"src\" file. Then if `src/index.ts`\nexists, Knip will use that file instead of `dist/index.js`.\n\nCurrently this only works based on `tsconfig.json`, in the future more source\nmappings may be added.\n\n## Example 3: source conditions\n\nSource-first monorepos may expose source files directly through a custom\ncondition in `package.json#exports` or `#imports` maps:\n\n```json title=\"package.json\"\n{\n  \"name\": \"@org/shared\",\n  \"exports\": {\n    \".\": {\n      \"@org/source\": \"./src/index.ts\",\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    }\n  }\n}\n```\n\nWhen module resolution fails because the targets aren't built, Knip falls back\nto the first conditional target of the workspace package that exists on disk,\nregardless of the condition's name. No build step or configuration required.\n\n[1]: ../reference/configuration.md#includeentryexports\n","frontmatter":{"title":"Source Mapping","description":"How Knip maps build artifacts in `dist`/`outDir` back to their original source files using `tsconfig.json` to avoid false positives."},"isInternal":false,"tokens":960,"sizeBytes":3616},{"name":"adopt-gradually.md","path":"packages/docs/src/content/docs/guides/adopt-gradually.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/guides/adopt-gradually.md","title":"Guides Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Adopt Knip gradually\ndescription: Roll Knip out on a large or legacy codebase without trying to reach zero on day one. Baseline, focus one issue type at a time, then ratchet with rules.\n---\n\nOn a large or legacy codebase the first run can report a lot. Reaching zero in\none sitting is then the wrong goal. Get a trustworthy signal first, then ratchet\nthe codebase toward clean and keep it there.\n\n## Actionable baseline\n\nMost of the noise on a first run comes from gaps in what Knip can reach: a\ndependency that Knip does not have a plugin for yet, an entry point it can't\nresolve, a phantom dependency. Fix the gaps before you delete anything:\n\n- Address [configuration hints][1].\n- Tune [entry and project files][2] so Knip analyzes the right set of files.\n- Tune configuration for your tools' [plugins][3].\n\nRead the output from the top. One unused file hides its exports and\ndependencies, so files come first.\n\nOnce the report reflects real findings instead of gaps, you have an actionable\nbaseline.\n\n## Focus one issue type at a time\n\nDon't fix everything at once. Narrow the report with [filters][4]:\n\n```sh\nknip --files        # unused files only (the major cascade!)\nknip --dependencies # then dependencies\nknip --exports      # then exports and types\n```\n\nClear one type, commit, move to the next.\n\n## Stage by rules\n\n[Rules][5] set a severity per issue type. Start by setting all types to\n`\"warn\"`, and then the types you've cleaned to `\"error\"`. Warnings are printed\nin gray, and they don't fail the run. Example:\n\n```json title=\"knip.json\"\n{\n  \"rules\": {\n    \"files\": \"error\",\n    \"dependencies\": \"error\",\n    \"exports\": \"warn\",\n    \"duplicates\": \"off\"\n  }\n}\n```\n\nAs each `\"warn\"` type reaches zero, set it to `\"error\"`. Keep iterating and\nprune the codebase to perfection.\n\n## Gate CI without blocking the team\n\nAdd Knip to [CI][6] as soon as you have a baseline, so new clutter is caught in\nreview. A few ways to stage it:\n\n- Mark cleaned types `\"error\"` and the rest `\"warn\"`, so CI fails only on the\n  types you've finished.\n- Workspace by workspace: in a [monorepo][7], scope passes with `--workspace`\n  (accepts multiple workspaces and glob patterns).\n- Production first: [`--production`][8] limits analysis to shipped code, so you\n  can clean what matters most and defer tests and tooling.\n- Set a budget, so CI fails only when the count exceeds the number (e.g. `knip\n--max-issues 50`). This blocks regressions while you burn down the rest.\n- Run report-only with [`--no-exit-code`][9] while you're still triaging.\n\n## Suppress only what's justified\n\nWhen something is genuinely fine as-is, prefer a specific, documented signal\nover a blanket `ignore`, for example:\n\n- tag an export with e.g. [`@lintignore` or `@internal`][10]\n- use [`ignoreExportsUsedInFile`][11] for internal-only exports\n- list known exceptions in [`ignoreDependencies`][12]\n\n[Resolving reported issues][13] covers the right tool for each case.\n\n[1]: ../reference/configuration-hints.md\n[2]: ./configuring-project-files.md\n[3]: ../explanations/plugins.md\n[4]: ../features/rules-and-filters.md#filters\n[5]: ../features/rules-and-filters.md#rules\n[6]: ./using-knip-in-ci.md\n[7]: ../features/monorepos-and-workspaces.md\n[8]: ../features/production-mode.md\n[9]: ../reference/cli.md#--no-exit-code\n[10]: ../reference/jsdoc-tsdoc-tags.md\n[11]: ../reference/configuration.md#ignoreexportsusedinfile\n[12]: ../reference/configuration.md#ignoredependencies\n[13]: ./handling-issues.mdx\n","frontmatter":{"title":"Adopt Knip gradually","description":"Roll Knip out on a large or legacy codebase without trying to reach zero on day one. Baseline, focus one issue type at a time, then ratchet with rules."},"isInternal":false,"tokens":886,"sizeBytes":3477},{"name":"configuring-project-files.md","path":"packages/docs/src/content/docs/guides/configuring-project-files.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/guides/configuring-project-files.md","title":"Guides Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Configuring Project Files\ndescription: How to set Knip's `entry` and `project` file patterns, use negations and production mode, and when to reach for `ignore`.\n---\n\nThe `entry` and `project` file patterns are the first and most important\noptions. Getting those right is essential to help you delete more code and make\nKnip faster:\n\n- Start with defaults. Only add targeted `entry` overrides when needed.\n- Use `project` patterns (with negations) to define the scope for Knip.\n- Use production mode to exclude tests and other non-production files.\n- Use `ignore` only to suppress issues in specific files; it does not exclude\n  files from analysis.\n\nLet's dive in and expand on all of these.\n\n## Entry files\n\nAvoid adding too many files as `entry` files:\n\n1. Knip does not report [unused exports][1] in entry files by default.\n2. Proper `entry` and `project` patterns allow Knip to find unused files and\n   exports.\n\n## Unused files\n\nFiles are reported as unused if they are in the set of `project` files, but are\nnot resolved from the `entry` files:\n\n```\nunused files = project files - (entry files + resolved files)\n```\n\nSee [entry files][2] to see where Knip looks for entry files. Fine-tune `entry`\nand adjust `project` to fit your codebase.\n\n:::tip\n\nUse negated `project` patterns to precisely include/exclude files for unused\nfiles detection.\n\nUse `ignore*` to suppress specific issues in matching files; it does not exclude\nfiles from analysis.\n\n:::\n\n## Negated patterns\n\nWhen there are too many files in the analysis, start here.\n\nFor instance, routes are entry files except those prefixed with an underscore:\n\n```json\n{\n  \"entry\": [\"src/routes/*.ts\", \"!src/routes/_*.ts\"]\n}\n```\n\nSome files are not part of your source and are reported as unused (false\npositives)? Use negated `project` patterns:\n\n```json\n{\n  \"entry\": [\"src/index.ts\"],\n  \"project\": [\"src/**/*.ts\", \"!src/exclude/**\"]\n}\n```\n\n❌   Don't use `ignore` for generated artifacts:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts\", \"scripts/*.ts\"],\n  \"ignore\": [\"build/**\", \"dist/**\", \"src/generated.ts\"]\n}\n```\n\n✅   Do define your project boundaries:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts\", \"scripts/*.ts\"],\n  \"project\": [\"src/**\", \"scripts/**\"],\n  \"ignore\": [\"src/generated.ts\"]\n}\n```\n\nWhy this is better:\n\n- `project` defines what belongs to the codebase, so build outputs are excluded\n  from analysis and unused file detection\n- `ignore` is for the few files that should be analyzed but contain exceptions\n- Improves performance by analyzing fewer files\n\n## Ignore issues in specific files\n\nUse `ignore` when a specific analyzed file is not handled properly by Knip or\nintentionally contains unused exports (e.g. generated files exporting\n\"everything\"):\n\n```json\n{\n  \"entry\": [\"src/index.ts\"],\n  \"project\": [\"src/**/*.ts\"],\n  \"ignore\": [\"src/generated.ts\"]\n}\n```\n\nAlso see [ignoreExportsUsedInFile][3] for a more targeted approach.\n\n## Production Mode\n\nDefault mode includes tests and other non-production files in the analysis. To\nfocus on production code, use [production mode][4].\n\nDon't try to exclude tests via `ignore` or negated `project` patterns. That's\ninefficient and ineffective due to entries added by plugins. Use production mode\ninstead.\n\n❌   Don't do this:\n\n```json\n{\n  \"ignore\": [\"**/*.test.js\"]\n}\n```\n\nWhy not: `ignore` hides issues from the report; it does not exclude files from\nanalysis.\n\n❌   Also don't do this:\n\n```json\n{\n  \"entry\": [\"index.ts\", \"!**/*.test.js\"]\n}\n```\n\nWhy not: plugins add test files as `entry` files; you can't and shouldn't\noverride that globally.\n\n❌   Or this:\n\n```json\n{\n  \"project\": [\"**/*.ts\", \"!**/*.spec.ts\"]\n}\n```\n\nWhy not: `project` is for unused file detection; negating test files is\nineffective because they are `entry` files.\n\n✅   Do this instead:\n\n```shell\nknip --production\n```\n\nTo fine-tune the resulting production file set, for instance to exclude test\nhelper files that still show as unused, use the exclamation mark suffix on\nproduction patterns:\n\n```json\n{\n  \"entry\": [\"src/index.ts!\"],\n  \"project\": [\"src/**/*.ts!\", \"!src/test-helpers/**!\"]\n}\n```\n\nRemember to keep adding the exclamation mark `suffix!` for production file\npatterns.\n\n:::tip\n\nUse the exclamation mark (`!`) on both ends (`!`) to exclude files in production\nmode.\n\n:::\n\n## Defaults & Plugins\n\nTo reiterate, the default `entry` and `project` files for each workspace:\n\n```json\n{\n  \"entry\": [\n    \"{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\",\n    \"src/{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\"\n  ],\n  \"project\": [\"**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}!\"]\n}\n```\n\nNext to this, there are other places where [Knip looks for entry files][2].\n\nAdditionally, [plugins have plenty of entry files configured][5] that are\nautomatically added as well.\n\n[1]: ../typescript/unused-exports.md\n[2]: ../explanations/entry-files.md\n[3]: ../reference/configuration.md#ignoreexportsusedinfile\n[4]: ../features/production-mode.md\n[5]: ../explanations/plugins.md#entry-files\n","frontmatter":{"title":"Configuring Project Files","description":"How to set Knip's `entry` and `project` file patterns, use negations and production mode, and when to reach for `ignore`."},"isInternal":false,"tokens":1302,"sizeBytes":5023},{"name":"contributing.md","path":"packages/docs/src/content/docs/guides/contributing.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/guides/contributing.md","title":"Guides Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Contributing to Knip\ndescription: Ways to contribute to Knip, including filing reproductions, opening pull requests, and writing a plugin.\n---\n\nHere are some ways to contribute to Knip:\n\n- Spread the word!\n- [Star the project][1]\n- [File an issue with a reproduction][2]\n- [Pull requests are welcome][3]\n\n[Writing a plugin][4] is a great and fun way to get started.\n\nThe [CONTRIBUTING.md][3] and [DEVELOPMENT.md][5] guides should get you up and\nrunning quickly.\n\nThe main goal of Knip is to keep projects clean & tidy. Everything that\ncontributes to that goal is welcome!\n\n[1]: https://github.com/webpro-nl/knip\n[2]: ./issue-reproduction.md\n[3]: https://github.com/webpro-nl/knip/blob/main/.github/CONTRIBUTING.md\n[4]: ../writing-a-plugin/index.md\n[5]: https://github.com/webpro-nl/knip/blob/main/.github/DEVELOPMENT.md\n","frontmatter":{"title":"Contributing to Knip","description":"Ways to contribute to Knip, including filing reproductions, opening pull requests, and writing a plugin."},"isInternal":false,"tokens":227,"sizeBytes":831},{"name":"issue-reproduction.md","path":"packages/docs/src/content/docs/guides/issue-reproduction.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/guides/issue-reproduction.md","title":"Guides Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Issue Reproduction\ndescription: How to create a minimal reproduction for a Knip bug or false positive using CodeSandbox, StackBlitz, a repo, or a test fixture.\n---\n\nIf you encounter an issue or false positives when using Knip, you can [open an\nissue on GitHub][1]. This will help you in your project, and will also improve\nKnip for everyone else!\n\nThink of Knip as a kitchen sink, it handles a large amount of projects and\nconfigurations, and your project is different from all others. Many factors may\ninfluence the issue at hand, such as:\n\n- Code syntax, import and export structure in source files\n- Dependencies, scripts and entry files in `package.json`\n- TypeScript configuration in `tsconfig.json`\n- Enabled plugins and related configuration files\n- Dependent or depending workspaces in a monorepo\n- Knip configuration in `knip.json`\n\n## Keep it minimal\n\nCreate the minimum of source code and configuration with a few files to\nreproduce and demonstrate the issue. Having this as a basis has many benefits:\n\n- Minimize barriers and unrelated contextual overhead\n- Optimize shared understanding of the situation\n- Serves as a \"contract\" to fix the actual issue\n- Files serve as a fixture to the project\n\nProviding this with an issue description will help us help you and improve the\nchances the issue can be looked into efficiently and in a timely manner.\n\nUseful **complements** to a minimal reproduction might include:\n\n- Screenshots, videos, code snippets or log output\n- Links to an existing project repository\n- Applications scaffolded by tools like Angular or Svelte CLI\n\n## Before opening an issue\n\nBefore opening an issue, please make sure you:\n\n- are using the latest version\n- have read the relevant documentation\n- have searched [existing issues][1]\n- have checked the list of [known issues][2]\n\nPlease file only a single issue at a time, so each of them can be labeled and\ntracked separately.\n\nThere is no need to open an issue if you're going to submit a pull request to\nclose it right away anyway. In that case it's preferred to keep things central\nin either an issue or pull request.\n\n## Templates\n\nA convenient way to create a minimal reproduction is by starting with one of\nthese templates in CodeSandbox or StackBlitz:\n\n| Template |                  |                 |\n| :------- | ---------------- | --------------- |\n| Basic    | [CodeSandbox][3] | [StackBlitz][4] |\n| Monorepo | [CodeSandbox][5] | [StackBlitz][6] |\n\nShoutout to [CodeSandbox][7] and [StackBlitz][8] for generously providing these\nfree dev containers!\n\n## Alternatives\n\nOther solutions to share a minimal and reproducible case may work well too,\nincluding:\n\n- A public repository on e.g. GitHub or GitLab.\n- A pull request with a new [test][9] and/or [fixture folder][10].\n\nThe goal is to have an easy and common understanding and reproduction. If you're\nunable to create a reproduction using one of the methods described then please\nclearly explain this in the issue or [contact me][11].\n\n## Pull Request\n\nThe optimal way is to add fixtures and failing tests to the Knip repository, and\nopen a pull request to discuss the issue! Also see [instructions for\ndevelopment][12].\n\n[1]: https://github.com/webpro-nl/knip/issues?q=is%3Aissue\n[2]: https://knip.dev/reference/known-issues\n[3]: https://codesandbox.io/p/devbox/github/webpro-nl/knip/main/templates/issue-reproduction/basic\n[4]: https://stackblitz.com/github/webpro-nl/knip/tree/main/templates/issue-reproduction/basic\n[5]: https://codesandbox.io/p/devbox/github/webpro-nl/knip/main/templates/issue-reproduction/monorepo\n[6]: https://stackblitz.com/github/webpro-nl/knip/tree/main/templates/issue-reproduction/monorepo\n[7]: https://codesandbox.io\n[8]: https://stackblitz.com\n[9]: https://github.com/webpro-nl/knip/blob/main/.github/DEVELOPMENT.md#tests\n[10]: https://github.com/webpro-nl/knip/tree/main/packages/knip/fixtures\n[11]: https://github.com/webpro\n[12]: https://github.com/webpro-nl/knip/blob/main/.github/DEVELOPMENT.md\n","frontmatter":{"title":"Issue Reproduction","description":"How to create a minimal reproduction for a Knip bug or false positive using CodeSandbox, StackBlitz, a repo, or a test fixture."},"isInternal":false,"tokens":958,"sizeBytes":3990},{"name":"namespace-imports.md","path":"packages/docs/src/content/docs/guides/namespace-imports.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/guides/namespace-imports.md","title":"Guides Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Namespace Imports\ndescription: How Knip handles exports used through `import * as NS` namespace imports, its usage heuristic, and the `nsExports` and `nsTypes` issue types.\n---\n\nThe intention of exports used through namespace imports may not always be clear\nto Knip. Here's a guide to better understand how Knip handles such exports.\n\n## Example\n\nWe start off by having two exports:\n\n```ts title=\"my-namespace.js\"\nexport const version = 'v5';\nexport const getRocket = () => '🚀';\n```\n\nThe next snippet shows how to import all the exports above on a namespace. All\nexports of the `my-namespace.js` module will be members on the `NS` object:\n\n```ts title=\"my-module.ts\"\nimport * as NS from './my-namespace.js';\nimport send from 'stats';\nsend(NS);\n```\n\nThe intention of export usage is not always clear. In the example above is\n`version` or `getRocket` used? We're not sure, but we _probably_ don't want them\nto be reported as unused. The same goes for the next example:\n\n```ts title=\"my-module.ts\"\nimport * as NS from './my-namespace.js';\n\nexport { NS };\n```\n\nIf this is all usage of the `NS` namespace object, we also don't know whether\nindividual exports like `version` or `getRocket` will be used. However, if at\nleast one reference to a property such as `NS.version` is found, then the\nindividual exports are considered separately again and `getRocket` will be\nmarked as unused:\n\n```ts title=\"index.ts\"\nimport { NS } from './my-module.js';\n\nconst version = NS.version;\n```\n\n## The default heuristic\n\nKnip uses the following heuristic to determine which of the individual exports\nare used:\n\n- If there's one or more references to the import namespace object, but without\n  any property access, all exports on that namespace are considered used.\n- Otherwise, exports are considered separately.\n\nBelow are a few more examples, and a way to disable this default behavior.\n\n## Examples\n\nLet's take a look at more examples:\n\n```ts title=\"my-namespace.ts\"\nexport const start = 1;\n\nexport const end = 1;\n```\n\nIn the following cases all exports of `my-namespace.ts` are considered used:\n\n```ts title=\"index.ts\"\nimport * as NS from './my-namespace.js';\nimport send from 'stats';\n\nsend(NS);\n\nconst spread = { ...NS };\n\nconst shorthand = { NS };\n\nconst assignment = NS;\n\nconst item = [NS];\n\ntype TypeOf = typeof NS;\n\nObject.values(NS);\n\nfor (const fruit in NS) {\n  //\n}\n\nexport { NS };\n\nexport { NS as AliasedNS };\n\nexport = NS;\n```\n\nHowever, this is no longer the case when one of the properties is accessed:\n\n```ts title=\"index.js\"\nimport * as NS from './namespace.js';\n\nconst begin = NS.start;\n\nsend(NS);\n```\n\nIn this case, the `end` export will be reported as unused, even though the `NS`\nobject itself is referenced on its own as well.\n\n## Include `nsExports` and `nsTypes`\n\nTo disable the heuristic as explained above, and enforce Knip to consider each\nexport on a namespace individually, include the `nsExports` issue type:\n\n```json\n{\n  \"include\": [\"nsExports\"]\n}\n```\n\nOr use the `--include nsExports` argument from the CLI. The `nsTypes` can be\nadded as well to do the same for exported types.\n\nIncluding these _adds_ them to the report; all other issue types are still\nreported.\n","frontmatter":{"title":"Namespace Imports","description":"How Knip handles exports used through `import * as NS` namespace imports, its usage heuristic, and the `nsExports` and `nsTypes` issue types."},"isInternal":false,"tokens":770,"sizeBytes":3191},{"name":"performance.md","path":"packages/docs/src/content/docs/guides/performance.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/guides/performance.md","title":"Guides Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Performance\ndescription: How to profile and speed up Knip using the `--cache`, `--performance`, and `--debug` flags, file patterns, and per-workspace linting.\n---\n\nThis page describes a few topics around Knip's performance, and how you might\nimprove it.\n\nKnip does not want to tell you how to structure files or how to write your code,\nbut it might still be good to understand inefficient patterns for Knip.\n\nUse the `--debug` and `--performance` flags to find potential bottlenecks.\n\n## Cache\n\nUse `--cache` to speed up consecutive runs.\n\n## Ignoring files\n\nFiles matching the `ignore` patterns are not excluded from the analysis. They're\njust not printed in the report. Use negated `entry` and `project` patterns to\nexclude files from the analysis.\n\nRead [configuring project files][1] for details and examples. Improving\nconfiguration may have a significant impact on performance.\n\n## Metrics\n\nUse [the `--performance` flag][2] to see how many times potentially expensive\nfunctions (e.g. `findReferences`) are invoked and how much time is spent in\nthose functions. Example usage:\n\n```sh\nknip --performance\n```\n\n## ignoreExportsUsedInFile\n\nThe [ignoreExportsUsedInFile][3] option slows down the process slightly.\nTypically, anywhere between 0.25% and 10% of total running time. To find out:\n\n```sh\nknip --performance-fn hasRefsInFile\n```\n\n## A last resort\n\nIn case Knip is unbearably slow (or even crashes), you could resort to [lint\nindividual workspaces][4].\n\n[1]: ./configuring-project-files.md\n[2]: ../reference/cli.md#--performance\n[3]: ../reference/configuration.md#ignoreexportsusedinfile\n[4]: ../features/monorepos-and-workspaces.md#filter-workspaces\n","frontmatter":{"title":"Performance","description":"How to profile and speed up Knip using the `--cache`, `--performance`, and `--debug` flags, file patterns, and per-workspace linting."},"isInternal":false,"tokens":408,"sizeBytes":1672},{"name":"troubleshooting.md","path":"packages/docs/src/content/docs/guides/troubleshooting.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/guides/troubleshooting.md","title":"Guides Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Troubleshooting\ndescription: Troubleshoot Knip lint issues and exceptions using exit codes, `--debug`, and `--trace` to see where exports and dependencies are used.\n---\n\nWe can distinguish two types of issues:\n\n- [Lint issues reported by Knip][1]\n- [Exceptions thrown by Knip][2]\n\nAlso see the [debug][3] and [trace][4] options below that can help to\ntroubleshoot issues.\n\n:::note[Rationale]\n\nThe JavaScript/TypeScript ecosystem has a vast amount of frameworks and tools.\nAdditionally, file locations, configuration semantics, command-line arguments\nand so on vary wildly. Files and dependencies are referenced in many ways. Knip\ntries harder than you think to cover it all.\n\nKnip is intentionally strict to maximize its potential. It may initially report\nmany unused files. However, getting this right will result in great reports and\ntidy codebases.\n\nIf it doesn't work out at first, a small change can go a long way.\n\n:::\n\n## Lint issues reported by Knip\n\nKnip reports lint issues in your codebase. See [handling issues][5] to deal with\nthe reported issues.\n\nIf you're considering filing an issue, please read [issue reproduction][6]\nfirst.\n\nExit code 1 indicates a successful run, but lint issues were found.\n\n## Exceptions thrown by Knip\n\nKnip may throw an exception, resulting in an unsuccessful run.\n\nSee [known issues][7] as it may be listed there and a workaround may be\navailable. If it isn't clear what's throwing the exception, try another run with\n`--debug` to locate the cause of the issue with more details.\n\nIf you're considering filing an issue, please read [issue reproduction][6]\nfirst.\n\nExit code 2 indicates an exception was thrown by Knip.\n\n## Debug\n\nTo better understand why Knip reports what it does, run it in debug mode by\nadding `--debug` to the command:\n\n```sh\nknip --debug\n```\n\nThis will give a lengthy output, including:\n\n- Included workspaces\n- Used configuration per workspace\n- Enabled plugins per workspace\n- Glob patterns and options followed by matching file paths\n- Plugin config file paths and found dependencies per plugin\n- Compiled non-standard source files\n\n## Trace\n\nUse `--trace` to see where exports or dependencies are used:\n\n- Use `--trace-file [path]` to output this only for the given file.\n- Use `--trace-export [name]` to output this only for the given export name.\n- Use `--trace-dependency [name]` to find where a dependency is imported\n- Use both to trace a specific named or default export of a certain file.\n\nThis works across re-exports, barrel files and workspaces. Here's an example\nscreenshot:\n\n<img src=\"/screenshots/trace-export.png\" alt=\"trace export\" class=\"mw500\" />\n\nIt's like a reversed module graph. Instead of traversing imports it goes in the\nopposite direction and shows where exports are imported.\n\nThe `--trace-dependency` accepts strings for exact matches, but if it looks like\na regex that works too:\n\n<img src=\"/screenshots/trace-dependency.png\" alt=\"trace dependency\" class=\"mw500\" />\n\nUse [--workspace \\[filter\\]][8] to filter accordingly.\n\n#### Legend\n\n| Marker | Description                         |\n| ------ | :---------------------------------- |\n| `✓`    | Referenced (not reported as unused) |\n| `✗`    | Reported as unused                  |\n| `⎆`    | Entry file                          |\n\nEach child node is prefixed with how the export is consumed: `import`,\n`importAs` (shown as `original → alias`), `importNS`, or a re-export\n(`reExport`, `reExportAs`, `reExportNS`, `reExportStar`). A `refs:` line lists\nthe references found in that file; a `members:` line shows per-member status for\nnamespaces and enums. An `[ambiguous]` line lists the competing definitions when\na name reaches the file through more than one `export *`. A name that reaches\nthe file only through `export *` is traced from its definition.\n\n## Opening an issue\n\nIf you want to open an issue, please see [issue reproduction][6].\n\n## Understanding Knip\n\nLooking to better understand how Knip works? The [entry files][9] and\n[plugins][10] explanations cover two core concepts. After this you might want to\ncheck out features like [production mode][11] and [monorepos & workspaces][12].\n\nIn a more general sense, [Why use Knip?][13] explains what Knip can do for you.\n\n## Asking for help\n\nIf you can't find your answer in any of the aforementioned resources, feel free\nto [open an issue on GitHub][14].\n\n[1]: #lint-issues-reported-by-knip\n[2]: #exceptions-thrown-by-knip\n[3]: #debug\n[4]: #trace\n[5]: ../guides/handling-issues.mdx\n[6]: ./issue-reproduction.md\n[7]: ../reference/known-issues.md\n[8]: ../reference/cli.md#--workspace-filter\n[9]: ../explanations/entry-files.md\n[10]: ../explanations/plugins.md\n[11]: ../features/production-mode.md\n[12]: ../features/monorepos-and-workspaces.md\n[13]: ../explanations/why-use-knip.md\n[14]: https://github.com/webpro-nl/knip/issues\n","frontmatter":{"title":"Troubleshooting","description":"Troubleshoot Knip lint issues and exceptions using exit codes, `--debug`, and `--trace` to see where exports and dependencies are used."},"isInternal":false,"tokens":1181,"sizeBytes":4850},{"name":"using-knip-in-ci.md","path":"packages/docs/src/content/docs/guides/using-knip-in-ci.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/guides/using-knip-in-ci.md","title":"Guides Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Using Knip in CI\ndescription: Run Knip in continuous integration to catch regressions, with a GitHub Actions workflow example, exit codes, caching, and reporters.\n---\n\nKnip is your companion during local development. But it is even more valuable in\na continuous integration (CI) environment to prevent regressions over time. Knip\nwill notify you of unused dependencies, exports and files if you forgot to\nremove them.\n\nKnip will exit the process with code `1` if there are one or more issues.\n\n## GitHub Actions\n\nHere's an example workflow configuration for GitHub Actions:\n\n```yaml\nname: Lint project\n\non: push\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    name: Ubuntu/Node v24\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions/setup-node@v6\n        with:\n          node-version: 24\n      - name: Install dependencies\n        run: npm install --ignore-scripts\n      - name: Run knip\n        run: npm run knip\n```\n\n## Notes\n\n- Use [--cache][1] to speed up consecutive runs (default location:\n  `./node_modules/.cache/knip`).\n- See [Reporters][2] including the GitHub Actions reporter.\n- Consider running Knip twice: a default run and a [production mode][3] run.\n- See [CLI arguments → Output][4] for some relevant options such as\n  `--treat-config-hints-as-errors` and `--no-exit-code`.\n- In CI environments, the [--no-progress][5] flag is set automatically.\n\n[1]: ../reference/cli.md#--cache\n[2]: ../features/reporters.md\n[3]: ../features/production-mode.md\n[4]: ../reference/cli.md#output\n[5]: ../reference/cli.md#--no-progress\n","frontmatter":{"title":"Using Knip in CI","description":"Run Knip in continuous integration to catch regressions, with a GitHub Actions workflow example, exit codes, caching, and reporters."},"isInternal":false,"tokens":396,"sizeBytes":1561},{"name":"working-with-commonjs.md","path":"packages/docs/src/content/docs/guides/working-with-commonjs.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/guides/working-with-commonjs.md","title":"Guides Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Working with CommonJS\ndescription: Conventions for `module.exports` and `require()` so Knip detects CommonJS named and default exports correctly and avoids false positives.\n---\n\nCommonJS is the JavaScript module system using `require()` and `module.exports`\nstatements.\n\nKnip works well with CommonJS. You don't need to use ES Modules or a\n`tsconfig.json` to use Knip.\n\nThe dynamic nature of CommonJS leaves room for ambiguity: it's sometimes unclear\nwhether an export is a default or a named export (and thus how it should be\nimported). So we'll have to agree on a few conventions to prevent false\npositives. Those conventions are designed to minimize impact on existing\ncodebases, improve consistency, and ease migration to ES Modules or TypeScript.\n\nFor **named exports**, the recommendation is to assign keys to `module.exports`:\n\n```js\nconst B = function () {};\n\nmodule.exports.A = { option: true };\nmodule.exports.B = B;\n```\n\nAlternatively, assign an object with ONLY shorthand property assignments to\n`module.exports`:\n\n```js\nconst A = function () {};\nconst B = { option: true };\n\nmodule.exports = { A, B };\n```\n\nAnything else assigned to `module.exports` is considered a default export, and\nshould be imported as such.\n\nThe following **default import** of the **named exports** above will result in\nall those exports reported as unused, even when referenced like below:\n\n```js\nconst DefaultImport = require('./common.js');\nconst runtime = [DefaultImport.A, DefaultImport.B];\n```\n\nInstead, do this:\n\n```js\nconst { A, B } = require('./common.js');\nconst runtime = [A, B];\n```\n\nNot recommended per se, but the following import syntax also results in the\nnamed export `A` being used:\n\n```js\nconst runtime = [require('./common.js').A];\n```\n\nAdd a non-shorthand property to turn the named object notation into a single\n**default export**:\n\n```js\nconst A = function () {};\nconst B = { option: true };\n\nmodule.exports = { __esModule: true, A, B };\n```\n\nThe `__esModule` key could be named differently (but makes sense given it's an\ninformal \"CJS/ESM interop\" standard amongst compilers and bundlers).\n","frontmatter":{"title":"Working with CommonJS","description":"Conventions for `module.exports` and `require()` so Knip detects CommonJS named and default exports correctly and avoids false positives."},"isInternal":false,"tokens":488,"sizeBytes":2112},{"name":"configuration.md","path":"packages/docs/src/content/docs/overview/configuration.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/overview/configuration.md","title":"Overview Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Configuration\ndescription: config\n---\n\n## Defaults\n\nKnip has good defaults and aims for \"zero config\". Here's a simplified version\nof the default `entry` and `project` values:\n\n```json\n{\n  \"entry\": [\"index.{js,ts}\", \"src/index.{js,ts}\"],\n  \"project\": [\"**/*.{js,ts}\"]\n}\n```\n\nEntry files are the starting point for Knip to find more source files and\nexternal dependencies.\n\n## Location\n\nBy default, Knip will look for a configuration file with the following names:\n\n- `knip.json`\n- `knip.jsonc`\n- `.knip.json`\n- `.knip.jsonc`\n- `knip.ts`\n- `knip.js`\n- `knip.config.ts`\n- `knip.config.js`\n- `package.json` (in the `\"knip\"` property)\n\nIf you want to use a custom file name or path, use the `--config` flag:\n\n```sh\nknip --config path/to/knip.json\n```\n\n## Customize\n\nYour project structure may not match the default `entry` and `project` files.\nHere's an example custom configuration to include `.js` files in the `scripts`\nfolder:\n\n```json title=\"knip.json\"\n{\n  \"$schema\": \"https://unpkg.com/knip@6/schema.json\",\n  \"entry\": [\"src/index.ts\", \"scripts/{build,create}.js\"],\n  \"project\": [\"src/**/*.ts\", \"scripts/**/*.js\"]\n}\n```\n\nThe set of `project` files determines the analysis scope. Use negated `project`\npatterns to exclude files from the analysis. See [configuring project files][1]\nfor details.\n\nThe values you set override the default values, they are not merged.\n\n:::tip\n\nBe specific with `entry` files. Minimize the number of entry files and wildcards\nfor better results.\n\nPlugins are enabled automatically, and their entry files are added\nautomatically. Such as for Next.js, Astro, Remix, Vitest, Playwright and many\nmore.\n\n:::\n\nKnip looks for entry files in many places. Learn more in the next page about\n[entry files][2].\n\n## Configuration Options\n\nSee [configuration file options][3].\n\nUse JavaScript or TypeScript in a [dynamic configuration file][4].\n\n## What's next?\n\nThe best way to understand Knip and what it can do for you is to read the pages\nin the \"Understanding Knip\" sections, starting with [entry files][2].\n\nWant to learn more about some of the main features?\n\n- Working with [monorepos & workspaces][5].\n- Learn more about [production mode][6].\n\nHaving trouble configuring Knip?\n\n- [Configuring project files][1]\n- [Troubleshooting][7]\n\nSearch this website using the bar at the top (`Ctrl+K` or `⌘+K`).\n\n[1]: ../guides/configuring-project-files.md\n[2]: ../explanations/entry-files.md\n[3]: ../reference/configuration.md\n[4]: ../reference/dynamic-configuration.mdx\n[5]: ../features/monorepos-and-workspaces.md\n[6]: ../features/production-mode.md\n[7]: ../guides/troubleshooting.md\n","frontmatter":{"title":"Configuration","description":"config"},"isInternal":false,"tokens":688,"sizeBytes":2613},{"name":"features.md","path":"packages/docs/src/content/docs/overview/features.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/overview/features.md","title":"Overview Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Features\ndescription: Table of Knip capabilities including auto-fix, cache, compilers, monorepos, plugins, reporters, production mode, trace and watch mode.\n---\n\nOverview of capabilities in support of the core feature: find many [types of\nissues][1].\n\nAlso see [related tooling][2].\n\n## Overview\n\n| Name                         | Description or example                                                |\n| :--------------------------- | :-------------------------------------------------------------------- |\n| [Auto-fix][3]                | Use `--fix` to auto-fix issues                                        |\n| [Cache][4]                   | Use `--cache` to speed up consecutive runs                            |\n| [Catalog][5]                 | Report & fix unused catalog entries                                   |\n| [CommonJS][6]                | CommonJS is still widely used & supported, but conditions apply       |\n| [Compilers][7]               | Support for Astro, MDX, Svelte, Vue and custom compilers              |\n| Configuration hints          | Display configuration hints to keep `knip.json` tidy                  |\n| [Debug][8]                   | Use `--debug` for troubleshooting                                     |\n| [Filters][9]                 | Exclude or focus on specific issue types                              |\n| [Format][10]                 | Use `--format` with `--fix` to auto-format modified files             |\n| [JSDoc tags][11]             | Tag and exclude specific exports from the report                      |\n| [Memory usage][12]           | Use `--memory` for detailed memory usage insights                     |\n| [Monorepos][13]              | Workspaces are first-class citizen                                    |\n| [Performance][14]            | Use `--performance` for detailed timing insights                      |\n| [Plugins][15]                | Over 100 plugins with custom entry paths and config parsing           |\n| [Plugins: inputs][16]        | Inputs are an affective mechanism to add entries, dependencies & more |\n| [Plugins: CLI arguments][17] | Tool-specific CLI argument parsing make plugins go the extra mile     |\n| [Preprocessors][18]          | Preprocess issues before being reported                               |\n| [Production mode][19]        | Use `--production` to lint only production code                       |\n| [Reporters][20]              | Choose from many built-in reporters or use your own                   |\n| [Rules][21]                  | Exclude or focus on specific issue types                              |\n| [Script parser][22]          | Shell scripts and `package.json` contain entry paths and dependencies |\n| [Source mapping][23]         | Map `dist` files back to `src` files                                  |\n| [Strict mode][24]            | Use `--strict` to tighten and lint only production `dependencies`     |\n| [Trace][25]                  | Trace exports to find where they are used                             |\n| [Watch mode][26]             | Use `--watch` for live updates of unused files and exports            |\n| [Workspace][27]              | Use `--workspace` to filter workspaces in a monorepo                  |\n\n[1]: ../reference/issue-types.md\n[2]: ../reference/related-tooling.md\n[3]: ../features/auto-fix.mdx\n[4]: ../reference/cli.md#--cache\n[5]: ../features/catalogs.md\n[6]: ../guides/working-with-commonjs.md\n[7]: ../features/compilers.md\n[8]: ../guides/troubleshooting.md#debug\n[9]: ../features/rules-and-filters.md#filters\n[10]: ../features/auto-fix.mdx#format\n[11]: ../reference/jsdoc-tsdoc-tags.md\n[12]: ../reference/cli.md#--memory\n[13]: ../features/monorepos-and-workspaces.md\n[14]: ../reference/cli.md#--performance\n[15]: ../explanations/plugins.md\n[16]: ../writing-a-plugin/inputs.md\n[17]: ../writing-a-plugin/argument-parsing.md\n[18]: ../features/reporters.md#preprocessors\n[19]: ../features/production-mode.md\n[20]: ../features/reporters.md\n[21]: ../features/rules-and-filters.md#rules\n[22]: ../features/script-parser.md\n[23]: ../features/source-mapping.md\n[24]: ../features/production-mode.md#strict-mode\n[25]: ../guides/troubleshooting.md#trace\n[26]: ../reference/cli.md#--watch\n[27]: ../features/monorepos-and-workspaces.md#filter-workspaces\n","frontmatter":{"title":"Features","description":"Table of Knip capabilities including auto-fix, cache, compilers, monorepos, plugins, reporters, production mode, trace and watch mode."},"isInternal":false,"tokens":938,"sizeBytes":4297},{"name":"screenshots-videos.md","path":"packages/docs/src/content/docs/overview/screenshots-videos.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/overview/screenshots-videos.md","title":"Overview Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Screenshots & videos\ndescription: Screenshots and videos showing Knip watch mode, auto-fix, export and file trace, and performance output in action.\n---\n\n## Watch & auto-fix\n\nThis video demonstrates using the `--watch` and `--fix` options inside Visual\nStudio Code:\n\n<video controls width=\"500\">\n  <source src=\"/screenshots/watch-fix.mp4\" type=\"video/mp4\" />\n\n  <source src=\"/screenshots/watch-fix.webm\" type=\"video/webm\" />\n</video>\n\nThis works in any terminal. See [--watch][1] and [auto-fix][2] for more details.\n\n## Trace\n\nHere's an example screenshot that traces the `mapIterator` export in the\nTypeScript codebase:\n\n<img src=\"/screenshots/trace-export.png\" alt=\"trace export\" class=\"mw500\" />\n\nInspect complicated import and re-export chains at a glance:\n\n<img src=\"/screenshots/trace-file.png\" alt=\"trace file\" class=\"mw500\" />\n\nSee [Trace][3] for more details.\n\n## Performance\n\nAn example screenshot showing `--performance` output for the Knip codebase:\n\n<img src=\"/screenshots/performance.png\" alt=\"performance\" class=\"mw500\" />\n\nAlso see [--performance][4].\n\n[1]: ../reference/cli.md#--watch\n[2]: ../features/auto-fix.mdx\n[3]: ../guides/troubleshooting.md#trace\n[4]: ../reference/cli.md#--performance\n","frontmatter":{"title":"Screenshots & videos","description":"Screenshots and videos showing Knip watch mode, auto-fix, export and file trace, and performance output in action."},"isInternal":false,"tokens":310,"sizeBytes":1222},{"name":"cli.md","path":"packages/docs/src/content/docs/reference/cli.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/reference/cli.md","title":"Reference Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: CLI Arguments\ndescription: Every Knip command-line flag, grouped by mode, scope, fix, output and troubleshooting, with shortcuts and exit codes.\n---\n\n## General\n\n### `--help`\n\nShortcut: `-h`\n\nPrints a summary of this page.\n\n### `--version`\n\nShortcut: `-V`\n\nPrint the version number.\n\n### `--no-progress`\n\nShortcut: `-n`\n\nDon't show dynamic progress updates. Progress is automatically disabled in CI\nenvironments.\n\n### `--config [file]`\n\nUse an alternative path for the configuration file. Default locations:\n\n- `knip.json`\n- `knip.jsonc`\n- `.knip.json`\n- `.knip.jsonc`\n- `knip.ts`\n- `knip.js`\n- `knip.config.ts`\n- `knip.config.js`\n- `package.json#knip`\n\nShortcut: `-c`\n\n### `--use-tsconfig-files`\n\nPer workspace, take project files from `tsconfig.json` (`files` + `include`,\nminus `exclude`, `node_modules` and `outDir`) and from the tsconfig files in its\n`references` instead of the `project` patterns. Workspaces without a\n`tsconfig.json` fall back to their `project` patterns.\n\nImplicitly enabled in the [editor extension, MCP server and language server][1]\nwhen there is no Knip configuration file.\n\n### `--tsConfig [file]`\n\nShortcut: `-t`\n\nUse an alternative path for the TypeScript configuration file.\n\nUsing `-t jsconfig.json` is also supported.\n\nDefault location: `tsconfig.json`\n\n### `knip-bun`\n\nRun Knip using the Bun runtime (instead of Node.js + jiti).\n\n```shell\nknip-bun\n```\n\nThis is equal to `bunx --bun knip`\n\nRequires [Bun][2] to be installed. Also see [known issues][3] for the type of\nissues this might help with.\n\n### NO\\_COLOR\n\nThe built-in reporters use the [NO\\_COLOR][4] friendly [picocolors][5]:\n\n```sh\nNO_COLOR=1 knip\n```\n\n### KNIP\\_DISABLE\\_RAW\\_TRANSFER\n\nSet `KNIP_DISABLE_RAW_TRANSFER=1` to disable oxc-parser raw transfer and use the\nnormal parser path.\n\n## Mode\n\n### `--cache`\n\nEnable caching.\n\nConsecutive runs are 10-40% faster as the results of file analysis (AST\ntraversal) are cached. Conservative. Cache strategy based on file meta data\n(modification time + file size).\n\nSee [stale cache results][6] for limitations and workarounds.\n\n### `--cache-location`\n\nProvide alternative cache location.\n\nDefault location: `./node_modules/.cache/knip`\n\n### `--include-entry-exports`\n\nWhen a repository is self-contained or private, you may want to include entry\nfiles when reporting unused exports:\n\n```sh\nknip --include-entry-exports\n```\n\nAlso see [includeEntryExports][7].\n\n### `--no-gitignore`\n\nIgnore `.gitignore` files.\n\n### `--production`\n\nShortcut: `-p`\n\nLint only production source files. This excludes:\n\n- entry files defined by plugins:\n  - test files\n  - configuration files\n  - Storybook stories\n- `devDependencies` from `package.json`\n\nRead more at [Production Mode][8].\n\n### `--strict`\n\nShortcut: `-s`\n\nIsolate workspaces and consider only direct dependencies. Implies [production\nmode][9].\n\nRead more at [Production Mode][8].\n\n### `--watch`\n\nShortcut: `-w`\n\nWatch current directory, and update reported issues when a file is modified,\nadded or deleted.\n\nWatch mode focuses on imports and exports in source files. During watch mode,\nchanges in `package.json` or `node_modules` may not cause an updated report.\n\n## Scope\n\n### `--workspace [filter]`\n\nSelect one or multiple workspaces (including its ancestor, dependency and\ndependent workspaces). The default behavior is to lint all configured\nworkspaces.\n\nShortcut: `-W`\n\nSee [filter workspaces][10] for more details and examples.\n\n### `--directory [dir]`\n\nShortcut: `-D`\n\nDefault: `cwd` (current directory)\n\nRun the process from a different directory.\n\n### `--exclude`\n\nExclude provided issue types from report. Can be comma-separated or repeated.\n\nExample:\n\n```sh\nknip --exclude enumMembers\n```\n\n### `--include`\n\nReport only provided issue types. Can be comma-separated or repeated.\n\nExample:\n\n```sh\nknip --include files,dependencies\nknip --include files --include dependencies\n```\n\n`nsExports` and `nsTypes` are [off by default][11]; including only those _adds_\nthem to the default report instead of narrowing it.\n\nAvailable [issue types][12] when filtering output using `--include` or\n`--exclude`:\n\n- `files`\n- `dependencies`\n- `unlisted`\n- `binaries`\n- `unresolved`\n- `exports`\n- `nsExports`\n- `types`\n- `nsTypes`\n- `enumMembers`\n- `namespaceMembers`\n- `duplicates`\n- `catalog`\n- `catalogReferences`\n\n### `--dependencies`\n\nShortcut to report only all types of dependency issues:\n\n```sh\n--include dependencies,unlisted,binaries,unresolved,catalog,catalogReferences\n```\n\n### `--exports`\n\nShortcut to report only all types of export issues:\n\n```sh\n--include exports,nsExports,types,nsTypes,enumMembers,namespaceMembers,duplicates\n```\n\n### `--files`\n\nShortcut to report only file issues:\n\n```sh\n--include files\n```\n\n### `--cycles`\n\nShortcut to report only circular dependencies:\n\n```sh\n--include cycles\n```\n\nAlso see the [cycles reporter][13].\n\n### `--tags`\n\nExports can be tagged with known or arbitrary JSDoc/TSDoc tags:\n\n```ts\n/**\n * Description of my exported value\n *\n * @type number\n * @internal Important matters\n * @lintignore\n */\nexport const myExport = 1;\n```\n\nAnd then include (`+`) or exclude (`-`) these tagged exports from the report\nlike so:\n\n```shell\nknip --tags=-lintignore,-internal\nknip --tags=+custom\n```\n\nThis way, you can either focus on or ignore specific tagged exports with tags\nyou define yourself. This also works for individual enum and namespace members.\n\nThe default directive is `+` (include) and the `@` prefix is ignored, so the\nnotation below is valid and will report only exports tagged `@lintignore` or\n`@internal`:\n\n```shell\nknip --tags @lintignore --tags @internal\n```\n\n## Fix\n\n### `--fix`\n\nShortcut: `-f`\n\nRead more at [auto-fix][14].\n\n### `--fix-type`\n\nFix only issues of type, can be comma-separated or repeated.\n\nMore info about fixable types at [issue types][12]\n\n### `--allow-remove-files`\n\nAllow Knip to remove files (with `--fix`).\n\n### `--format`\n\nShortcut: `-F`\n\nFormat modified files after `--fix` using the local formatter.\n\n## Output\n\n### `--preprocessor [preprocessor]`\n\nPreprocess the results before providing it to the [reporter(s)][15].\n\nCan be repeated. Examples:\n\n```sh\nknip --preprocessor ./my-preprocessor.ts\n```\n\n```sh\nknip --preprocessor preprocessor-package\n```\n\nPreprocessors can also be configured in the Knip configuration file.\n\nAlso see [Reporters & Preprocessors][16].\n\n### `--preprocessor-options [json]`\n\nPass extra options to the preprocessor as JSON string.\n\n```sh\nknip --preprocessor ./preproc.ts --preprocessor-options '{\"key\":\"value\"}'\n```\n\n### `--reporter [reporter]`\n\nAvailable reporters:\n\n- `symbols` (default)\n- `compact`\n- `codeowners`\n- `json`\n- `codeclimate`\n- `markdown`\n- `disclosure`\n- `github-actions`\n- `sarif`\n\nCan be repeated. Example:\n\n```sh\nknip --reporter compact\n```\n\nAlso see [Reporters & Preprocessors][16].\n\n### `--reporter-options [json]`\n\nPass extra options to the reporter (as JSON string):\n\nExample:\n\n```sh\nknip --reporter codeowners --reporter-options '{\"path\":\".github/CODEOWNERS\"}'\n```\n\n### `--no-config-hints`\n\nSuppress configuration hints.\n\n### `--no-tag-hints`\n\nSuppress tag hints.\n\n### `--treat-config-hints-as-errors`\n\nExit with non-zero exit code (`1`) if there are any configuration hints.\n\n### `--treat-tag-hints-as-errors`\n\nExit with non-zero exit code (`1`) if there are any tag hints.\n\n### `--max-issues`\n\nMaximum number of issues before non-zero exit code. Default: `0`\n\n### `--max-show-issues`\n\nMaximum number of issues per type to display (does not affect exit code).\n\n### `--no-exit-code`\n\nExit with code zero (`0`) even when there are lint issues. Config load failures\nand internal errors still exit with code `2`.\n\nThe default exit codes:\n\n| Code | Description                                                                                     |\n| :--: | :---------------------------------------------------------------------------------------------- |\n| `0`  | Knip ran successfully, no lint issues                                                           |\n| `1`  | Knip ran successfully, but there is at least one lint issue                                     |\n| `2`  | Knip did not run successfully due to bad input, a plugin config load error or an internal error |\n\n## Troubleshooting\n\n### `--debug`\n\nShortcut: `-d`\n\nShow [debug output][17].\n\n### `--memory`\n\n```txt frame=terminal\nknip --memory\n\n(results)\n\n # heapUsed  heapTotal  freemem\n-- --------  ---------  -------\n 0    42.09      70.91  2251.00\n 1   927.04    1042.58  1166.47\n 2   973.29    1047.33  1160.92\n 3   971.54    1079.83  1121.66\n 4   997.80    1080.33  1120.34\n 5  1001.88    1098.08  1100.72\n 6  1038.69    1116.58  1100.72\n 7  1082.12    1166.33  1100.72\n 8  1145.46    1224.50  1100.72\n 9  1115.82    1240.25  1100.72\n10  1182.35    1249.75   973.05\n11   637.32    1029.17   943.63\n12   674.30    1029.33   943.39\n13   682.24    1029.33   941.63\n14   707.70    1029.33   937.48\n\nTotal running time: 4.3s\n```\n\n### `--memory-realtime`\n\nUse this if Knip crashes to still see memory usage info over time:\n\n```txt frame=terminal\nknip --memory-realtime\n\n#  heapUsed  heapTotal  freemem\n-  --------  ---------  -------\n0     42.09      70.91  2251.00\n1    927.04    1042.58  1166.47\n...mem info keeps being logged...\n\n(results)\n```\n\n### `--performance`\n\nUse this flag to get the count and execution time of potentially expensive\nfunctions in a table. Example:\n\n```txt frame=terminal\n$ knip --performance\n\n(results)\n\nName                           size  min       max       median    sum\n-----------------------------  ----  --------  --------  --------  --------\nfindReferences                  648     84.98   7698.61     96.41  70941.70\ncreateProgram                     2   6295.84   7064.68   6680.26  13360.52\nglob                              6      0.05    995.78    513.82   3150.87\nfindESLintDependencies            2      0.01     74.41     37.21     74.41\nfindGithubActionsDependencies     6      0.16     12.71      0.65     23.45\nfindBabelDependencies             2      0.00     38.75     19.37     38.75\n...\n\nTotal running time: 5s\n```\n\n- `name`: the internal Knip function name\n- `size`: number of function invocations\n- `min`: the fastest invocation\n- `max`: the slowest invocation\n- `median`: the median invocation\n- `sum` the accumulated time of all invocations\n\nThis is not yet available in Bun, since it does not support\n`performance.timerify` ([GitHub issue][18]).\n\n### `--duration`\n\nShortcut: `-u`\n\nPrint total running time. Zero overhead — no `timerify` instrumentation, unlike\n`--performance`.\n\n### `--performance-fn`\n\nLimit the output of `--performance` to a single function to minimize the\noverhead of the `timerify` Node.js built-in and focus on that function alone:\n\n```txt frame=terminal\n$ knip --performance-fn resolveSync\n\n(results)\n\nName         size   min   max   median   sum\n-----------  -----  ----  ----  ------  ------\nresolveSync  66176  0.00  5.69    0.00  204.85\n\nTotal running time: 12.9s\n```\n\n### `--trace`\n\nTrace exports to see where they are imported.\n\nAlso see [Trace][19].\n\n### `--trace-dependency [name]`\n\nTrace package or binary name to see where it's referenced. Implies\n[--trace][20].\n\n### `--trace-export [name]`\n\nTrace export name to see where it's imported. Implies [--trace][20].\n\n### `--trace-file [path]`\n\nTrace file to see where its exports are imported. Implies [--trace][20].\n\n[1]: ./integrations.md\n[2]: https://bun.sh\n[3]: ../reference/known-issues.md\n[4]: https://no-color.org/\n[5]: https://www.npmx.dev/package/picocolors\n[6]: ./known-issues.md#stale-cache-results\n[7]: ./configuration.md#includeentryexports\n[8]: ../features/production-mode.md\n[9]: #--production\n[10]: ../features/monorepos-and-workspaces.md#filter-workspaces\n[11]: ../guides/namespace-imports.md\n[12]: ./issue-types.md\n[13]: ../features/reporters.md#cycles\n[14]: ../features/auto-fix.mdx\n[15]: #--reporter-reporter\n[16]: ../features/reporters.md\n[17]: ../guides/troubleshooting.md#debug\n[18]: https://github.com/oven-sh/bun/issues/9271\n[19]: ../guides/troubleshooting.md#trace\n[20]: #--trace\n","frontmatter":{"title":"CLI Arguments","description":"Every Knip command-line flag, grouped by mode, scope, fix, output and troubleshooting, with shortcuts and exit codes."},"isInternal":false,"tokens":3292,"sizeBytes":12026},{"name":"configuration-hints.md","path":"packages/docs/src/content/docs/reference/configuration-hints.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/reference/configuration-hints.md","title":"Reference Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Configuration Hints\ndescription: The configuration hints Knip emits to keep your config tidy, what each one means, and how to resolve it.\n---\n\nKnip emits configuration hints to help keep your configuration file tidy and\nreduce drift.\n\nThey're warnings by default, not lint findings. But addressing the hints might\nimprove results significantly. The hints on this page are sorted by\nimpact/importance (most impactful first).\n\nUse [`--treat-config-hints-as-errors`][1] or [`treatConfigHintsAsErrors`][2] to\nmake any configuration hint an error and result in a non-zero exit code to fail\nCI.\n\n## Unconfigured projects\n\nToo many unused files in a single workspace-codebase, caused by a missing\nconfiguration file or incomplete configuration:\n\n```\nCreate knip.json configuration file, and add entry and/or refine project files (42 unused files)\n```\n\nOr if you have a config file:\n\n```\nAdd entry and/or refine project files (42 unused files)\n```\n\n**Solution**: Add and refine `entry` and/or `project` patterns.\n\nRelated resources:\n\n- [Configuration][3]\n- [Monorepos & Workspaces][4]\n\n## Unconfigured workspaces\n\nToo many unused files in a monorepo, caused by a missing configuration file or\nincomplete configuration:\n\n```\nCreate knip.json configuration file with workspaces[\"packages/app\"] object (42 unused files)\n```\n\nOr if you have a config file:\n\n```\nAdd entry and/or refine project files in workspaces[\"packages/app\"] (42 unused files)\n```\n\n**Solution**: add a `workspaces` object to configuration. Add and refine `entry`\nand/or `project` patterns. For instance, the example message translates to\nconfiguration like this:\n\n```json\n{\n  \"workspaces\": {\n    \"packages/app\": {\n      \"entry\": [\"src/App.tsx\"],\n      \"project\": [\"src/**/*.ts\"]\n    }\n  }\n}\n```\n\nRelated resources:\n\n- [Configuring Project Files][5]\n- [Monorepos & Workspaces][4]\n\n## Top-level entry/project\n\nIn monorepos, Knip uses only `entry` and `project` under `workspaces`. The\ntop-level keys with the same name are ignored.\n\n```\nRemove, or move unused top-level entry to one of \"workspaces\"\nRemove, or move unused top-level project to one of \"workspaces\"\n```\n\n**Solution**: Remove top-level `entry` and `project` keys, use these options in\n`workspaces` instead.\n\n```jsonc\n{\n  \"entry\": [\"src/App.tsx\"], // move entry/project from here... ↴\n  \"project\": [\"src/**/*.ts\"],\n  \"workspaces\": {\n    \".\": {\n      \"entry\": [\"src/App.tsx\"], // ...to the correct workspace(s) ↲\n      \"project\": [\"src/**/*.ts\"],\n    },\n  },\n}\n```\n\n## Stale workspace configuration\n\nA key in the `workspaces` configuration matches no workspace in the project, for\ninstance after the workspace was removed or renamed.\n\n```\nRemove from workspaces\n```\n\n**Solution**: Remove the stale key from `workspaces`, or correct its path.\n\n## Unused entry in ignore group\n\nAn entry of an ignore list is no longer needed, remove it.\n\n```\nRemove from ignoreWorkspaces\nRemove from ignoreDependencies\nRemove from ignoreBinaries\nRemove from ignoreUnresolved\n```\n\n**Solution**: Remove the entry from the array.\n\n## Useless patterns\n\nA glob pattern in `entry` or `project` does not match any files.\n\n```\nRefine entry pattern (no matches)\nRefine project pattern (no matches)\n```\n\n**Solution**: Refine or remove the `entry` or `project` entry.\n\n## Redundant patterns\n\nA glob/pattern is redundant, because it's already covered by defaults or added\nby an enabled plugin.\n\n```\nRemove redundant entry pattern\nRemove redundant project pattern\n```\n\n**Solution**: Remove the `entry` or `project` entry.\n\n## Missing package entry file\n\n```\nPackage entry file not found\n```\n\n**Solution**: Refine or remove the entry in `package.json`.\n\n[1]: ./cli.md#--treat-config-hints-as-errors\n[2]: ./configuration.md#treatconfighintsaserrors\n[3]: ../overview/configuration.md\n[4]: ../features/monorepos-and-workspaces.md\n[5]: ../guides/configuring-project-files.md\n","frontmatter":{"title":"Configuration Hints","description":"The configuration hints Knip emits to keep your config tidy, what each one means, and how to resolve it."},"isInternal":false,"tokens":938,"sizeBytes":3870},{"name":"configuration.md","path":"packages/docs/src/content/docs/reference/configuration.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/reference/configuration.md","title":"Reference Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Configuration\ndescription: Every knip.json option, including entry, project, paths, workspaces, plugins, rules, tags, ignores and compilers.\n---\n\nThis page lists all configuration file options.\n\n## File Types\n\n### JSON Schema\n\nA `$schema` field is a URL that you put at the top of your JSON file. This\nallows you to get red squiggly lines inside of your IDE when you make a typo or\nprovide an otherwise invalid configuration option.\n\nIn JSON, use the provided JSON schema:\n\n```json title=\"knip.json\"\n{\n  \"$schema\": \"https://unpkg.com/knip@6/schema.json\"\n}\n```\n\n### JSONC\n\nIn JSONC, use the provided JSONC schema:\n\n```json title=\"knip.jsonc\"\n{\n  \"$schema\": \"https://unpkg.com/knip@6/schema-jsonc.json\"\n}\n```\n\nUse JSONC if you want to use comments and/or trailing commas.\n\n### TypeScript\n\nSee [dynamic configuration][1] about dynamic and typed configuration files.\n\n## Project\n\n### `entry`\n\nArray of glob patterns to find entry files. Prefix with `!` for negation.\nExample:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts\", \"scripts/*.ts\", \"!scripts/except-this-one.ts\"]\n}\n```\n\nAlso see [configuration][2] and [entry files][3].\n\n### `project`\n\nArray of glob patterns to find project files. Example:\n\n```json title=\"knip.json\"\n{\n  \"project\": [\"src/**/*.ts\", \"scripts/**/*.ts\"]\n}\n```\n\nAlso see [configuration][2] and [entry files][3].\n\n### `paths`\n\nTools like TypeScript, webpack and Babel support import aliases in various ways.\nKnip automatically includes `compilerOptions.paths` from the TypeScript\nconfiguration, but does not automatically use other types of import aliases.\nThey can be configured manually:\n\n```json title=\"knip.json\"\n{\n  \"paths\": {\n    \"@lib\": [\"./lib/index.ts\"],\n    \"@lib/*\": [\"./lib/*\"]\n  }\n}\n```\n\nEach workspace can have its own `paths` configured. Knip `paths` follow the\nTypeScript semantics:\n\n- Path values are an array of relative paths.\n- Paths without an `*` are exact matches.\n\n## Workspaces\n\n### `workspaces`\n\nConfigure `entry`, `project`, plugins and most other options per workspace. Keys\nare workspace directories (globs allowed); the root workspace is `\".\"`.\n\n```json title=\"knip.json\"\n{\n  \"workspaces\": {\n    \".\": {\n      \"entry\": [\"scripts/*.ts\"],\n      \"project\": [\"scripts/**/*.ts\"]\n    },\n    \"packages/*\": {\n      \"entry\": [\"src/index.ts\"],\n      \"project\": [\"src/**/*.ts\"]\n    }\n  }\n}\n```\n\nWorkspaces configured here that aren't already defined in the root\n`package.json` (or `pnpm-workspace.yaml`) are added to the analysis. Also see\n[Monorepos & Workspaces][4].\n\nIndividual workspace configurations may contain all other options listed on this\npage, except for the following root-only options:\n\n- `exclude` / `include`\n- `ignoreWorkspaces`\n- `workspaces`\n\nWorkspaces can't be nested in a Knip configuration, but they can be nested in a\nmonorepo folder structure.\n\nAlso see [Monorepos and workspaces][4].\n\n## Plugins\n\nThere are a few options to modify the behavior of a plugin:\n\n- Override a plugin's `config` or `entry` location\n- Force-enable a plugin by setting its value to `true`\n- Disable a plugin by setting its value to `false`\n\n```json title=\"knip.json\"\n{\n  \"mocha\": {\n    \"config\": \"config/mocha.config.js\",\n    \"entry\": [\"**/*.spec.js\"]\n  },\n  \"playwright\": true,\n  \"webpack\": false\n}\n```\n\nIt should be rarely necessary to override the `entry` patterns, since plugins\nalso read custom entry file patterns from the tooling configuration (see\n[Plugins → entry files][5]).\n\nPlugin configuration can be set on root and on a per-workspace level. If enabled\non root level, it can be disabled on workspace level by setting it to `false`\nthere, and vice versa.\n\nAlso see [Plugins][6].\n\n## Rules & Filters\n\n### `rules`\n\nSee [Rules & Filters][7].\n\n### `include`\n\nSee [Rules & Filters][7].\n\n### `exclude`\n\nSee [Rules & Filters][7].\n\n### `tags`\n\nExports can be tagged with known or arbitrary JSDoc/TSDoc tags:\n\n```ts\n/**\n * Description of my exported value\n *\n * @type number\n * @internal Important matters\n * @lintignore\n */\nexport const myExport = 1;\n```\n\nAnd then include (`+`) or exclude (`-`) these tagged exports from the report\nlike so:\n\n```json\n{\n  \"tags\": [\"-lintignore\"]\n}\n```\n\nThis way, you can either focus on or ignore specific tagged exports with tags\nyou define yourself. This also works for individual enum and namespace members.\n\nThe default directive is `+` (include) and the `@` prefix is ignored, so the\nnotation below is valid and will report only exports tagged `@lintignore` or\n`@internal`:\n\n```json\n{\n  \"tags\": [\"@lintignore\", \"@internal\"]\n}\n```\n\n:::caution\n\nTags must not contain hyphens or plus symbols, so it is recommended to stick to\nletters and avoid snake-case.\n\n:::\n\nAlso see [JSDoc & TSDoc Tags][8].\n\n### `preprocessor`\n\nPreprocess the results before providing them to the reporter(s). Can be a single\npreprocessor or an array of preprocessors. Each value is a path to a local file\nor an npm package name.\n\n```json title=\"knip.json\"\n{\n  \"preprocessor\": [\"./first.ts\", \"./second.ts\"]\n}\n```\n\nAlso see [Preprocessors][9].\n\n### `preprocessorOptions`\n\nExtra options to pass to the preprocessor.\n\n```json title=\"knip.json\"\n{\n  \"preprocessor\": \"./my-preprocessor.ts\",\n  \"preprocessorOptions\": { \"key\": \"value\" }\n}\n```\n\n### `treatConfigHintsAsErrors`\n\nExit with non-zero code (1) if there are any configuration hints.\n\n```json title=\"knip.json\"\n{\n  \"treatConfigHintsAsErrors\": true\n}\n```\n\n### `treatTagHintsAsErrors`\n\nExit with non-zero code (1) if there are any tag hints.\n\n```json title=\"knip.json\"\n{\n  \"treatTagHintsAsErrors\": true\n}\n```\n\n## Ignore Issues\n\n### `ignore`\n\n:::tip\n\nPlease read [configuring project files][10] before using the `ignore` option.\n\n:::\n\nAvoid `ignore` patterns. There is almost always a better solution:\n\n- Follow up on configuration hints (if there are any).\n- Fine-tune `entry` and `project` patterns.\n- Use [production mode][11].\n- Other `ignore*` options.\n\n**NOTE**: An exception to the rule: to _temporarily_ report only issues in files\nthat match the negated `ignore` pattern:\n\n```json title=\"knip.json\"\n{\n  \"ignore\": [\"!src/dir/**\"]\n}\n```\n\n### `ignoreFiles`\n\nArray of glob patterns of files to exclude from the \"Unused files\" section only.\n\nUnlike `ignore`, which suppresses all issue types for matching files,\n`ignoreFiles` only affects the `files` issue type. Use this when a file should\nremain analyzed for other issues (exports, dependencies, unresolved) but should\nnot be considered for unused file detection.\n\n```json title=\"knip.json\"\n{\n  \"ignoreFiles\": [\"src/generated/**\", \"fixtures/**\"]\n}\n```\n\nSuffix an item with `!` to enable it only in production mode.\n\n### `ignoreBinaries`\n\nExclude binaries that are used but not provided by any dependency from the\nreport. Value is an array of binary names or regular expressions. Example:\n\n```json title=\"knip.json\"\n{\n  \"ignoreBinaries\": [\"zip\", \"docker-compose\", \"pm2-.+\"]\n}\n```\n\nActual regular expressions can be used in dynamic configurations:\n\n```ts title=\"knip.ts\"\nexport default {\n  ignoreBinaries: [/^pm2-.+/],\n};\n```\n\nSuffix an item with `!` to enable it only in production mode.\n\n### `ignoreGlobalBinaries`\n\nDefaults to `true`, suppressing missing-binary reports for common global commands such as `git` and `docker`. Set it to `false` to report these commands where a project dependency is expected:\n\n```json title=\"knip.json\"\n{\n  \"ignoreGlobalBinaries\": false,\n  \"ignoreBinaries\": [\"git\"]\n}\n```\n\nDependencies that provide a referenced binary still count as used, and `ignoreBinaries` still applies. Optional commands, including bare CI/hook commands and commands installed on demand, produce no missing-binary reports. Workspaces inherit the top-level value unless they override it.\n\n### `ignoreDependencies`\n\nArray of package names to exclude from the report. Regular expressions allowed.\nExample:\n\n```json title=\"knip.json\"\n{\n  \"ignoreDependencies\": [\"hidden-package\", \"@org/.+\"]\n}\n```\n\nActual regular expressions can be used in dynamic configurations:\n\n```ts title=\"knip.ts\"\nexport default {\n  ignoreDependencies: [/@org\\/.*/, /^lib-.+/],\n};\n```\n\nSuffix an item with `!` to enable it only in production mode.\n\nAlso see [Unused dependencies][12].\n\n### `ignoreMembers`\n\nArray of enum and namespace members to exclude from the report. Regular\nexpressions allowed. Example:\n\n```json title=\"knip.json\"\n{\n  \"ignoreMembers\": [\"render\", \"on.+\"]\n}\n```\n\nActual regular expressions can be used in dynamic configurations.\n\n### `ignoreUnresolved`\n\nArray of specifiers to exclude from the report. Regular expressions allowed.\nExample:\n\n```json title=\"knip.json\"\n{\n  \"ignoreUnresolved\": [\"ignore-unresolved-import\", \"#virtual/.+\"]\n}\n```\n\nActual regular expressions can be used in dynamic configurations:\n\n```ts title=\"knip.ts\"\nexport default {\n  ignoreUnresolved: [/^#virtual\\/.+/],\n};\n```\n\n### `ignoreWorkspaces`\n\nArray of workspaces to ignore, globs allowed. Example:\n\n```json title=\"knip.json\"\n{\n  \"ignoreWorkspaces\": [\n    \"packages/go-server\",\n    \"packages/flat/*\",\n    \"packages/deep/**\"\n  ]\n}\n```\n\nSuffix an item with `!` to enable it only in production mode.\n\nPrefix an item with `!` to override an earlier wildcard.\n\n### `ignoreIssues`\n\nIgnore specific issue types for specific file patterns. Keys are glob patterns\nand values are arrays of issue types to ignore for matching files. This allows\nignoring specific issues (like unused exports) in generated files while still\nreporting other issues in those same files.\n\n```json title=\"knip.json\"\n{\n  \"ignoreIssues\": {\n    \"src/generated/**\": [\"exports\", \"types\"],\n    \"**/*.generated.ts\": [\"exports\", \"enumMembers\", \"namespaceMembers\"]\n  }\n}\n```\n\n### `cycles`\n\nConfigure circular dependency (`cycles`) detection.\n\nSet `dynamicImports` to include dynamic `import()` edges, which are excluded by\ndefault (a dynamic import defers evaluation, so it does not cause the\ninitialization hazard cycles are meant to catch).\n\nUse `allow` to accept specific cycles by exact path while keeping other `cycles`\nissues enabled. Path entries are relative to the project root and omit the\nclosing repeat of the first file.\n\n```json title=\"knip.json\"\n{\n  \"cycles\": {\n    \"dynamicImports\": true,\n    \"allow\": [[\"src/i18n/index.ts\", \"src/i18n/middleware.ts\"]]\n  }\n}\n```\n\n## Exports\n\n### `ignoreExportsUsedInFile`\n\nIn files with multiple exports, some of them might be used only internally. If\nthese exports should not be reported, there is a `ignoreExportsUsedInFile`\noption available. With this option enabled, when something is also no longer\nused internally, it will be reported as unused.\n\n```json title=\"knip.json\"\n{\n  \"ignoreExportsUsedInFile\": true\n}\n```\n\nIn a more fine-grained manner, to ignore only specific issue types:\n\n```json title=\"knip.json\"\n{\n  \"ignoreExportsUsedInFile\": {\n    \"interface\": true,\n    \"type\": true\n  }\n}\n```\n\nValid keys are the symbol types Knip distinguishes: `class`, `enum`, `function`,\n`interface`, `member`, `namespace`, `type` and `variable`.\n\nSet this option at root level to enable this globally, or within workspace\nconfigurations individually.\n\n### `includeEntryExports`\n\nBy default, Knip does not report unused exports in entry files. When a\nrepository (or workspace) is self-contained or private, you may want to include\nentry files when reporting unused exports:\n\n```json title=\"knip.json\"\n{\n  \"includeEntryExports\": true\n}\n```\n\nIf enabled, Knip will report unused exports in entry source files. But not in\nentry and configuration files as configured by plugins, such as `next.config.js`\nor `src/routes/+page.svelte`. Entry files discovered only through `package.json`\nscripts are also excluded; add them to `entry` to include their exports.\n\nThis will also enable reporting unused members of exported enums and namespaces.\n\nSet this option at root level to enable this globally, or within workspace\nconfigurations individually.\n\n## Compilers\n\nKnip supports custom compilers to transform files before analysis.\n\n:::note\n\nSince compilers are functions, they can only be used in dynamic configuration\nfiles (`.js` or `.ts`), not in JSON configuration files.\n\n:::\n\n### `compilers`\n\nOverride built-in compilers or add custom compilers for additional file types.\n\nAlso see [Compilers][13].\n\n[1]: ../reference/dynamic-configuration.mdx\n[2]: ../overview/configuration.md\n[3]: ../explanations/entry-files.md\n[4]: ../features/monorepos-and-workspaces.md\n[5]: ../explanations/plugins.md#entry-files\n[6]: ../explanations/plugins.md\n[7]: ../features/rules-and-filters.md#filters\n[8]: ./jsdoc-tsdoc-tags.md\n[9]: ../features/reporters.md#preprocessors\n[10]: ../guides/configuring-project-files.md\n[11]: ../features/production-mode.md\n[12]: ../guides/handling-issues.mdx#unused-dependencies\n[13]: ../features/compilers.md\n","frontmatter":{"title":"Configuration","description":"Every knip.json option, including entry, project, paths, workspaces, plugins, rules, tags, ignores and compilers."},"isInternal":false,"tokens":3109,"sizeBytes":12661},{"name":"faq.md","path":"packages/docs/src/content/docs/reference/faq.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/reference/faq.md","title":"Reference Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: FAQ\ndescription: Design decisions behind Knip, common pitfalls, how it compares to ESLint and tree-shaking, and how the module graph works.\ndate: 2024-08-20\n---\n\n## Introduction\n\nKnip finds and fixes unused dependencies, exports and files. As a \"kitchen sink\"\nin the npm ecosystem, it creates a comprehensive module graph of your project.\n\n:::note[Rationale]\n\nThe JavaScript/TypeScript ecosystem has a vast amount of frameworks and tools.\nAdditionally, file locations, configuration semantics, command-line arguments\nand so on vary wildly. Files and dependencies are referenced in many ways. Knip\ntries harder than you think to cover it all.\n\n:::\n\nThis FAQ explains a few design decisions and why certain things work the way\nthey do, here and there in more depth than the rest of the docs.\n\n:::tip\n\nTry the [Knip MCP Server][1] or the [Knip Editor Extension][2]. Let your coding\nagent use the built-in MCP Server and create a custom `knip.json` for you, so\nyou don't have to.\n\n:::\n\n## Common Pitfalls\n\n### Why shouldn't I ignore or disable configuration hints?\n\nConfiguration hints are critical for building a healthy and accurate module\ngraph. They usually indicate that Knip cannot resolve a dependency, plugin, or\nentry file. If you ignore or disable these hints, Knip's understanding of your\nproject will be incomplete, which inevitably leads to false positives (reporting\nused code as unused). Always address configuration hints first before looking at\nother reported issues.\n\n### Why is it a bad idea to use `ignore` patterns like I do in ESLint?\n\nKnip is not a regular file-based linter like ESLint. It works by analyzing the\nentire interconnected module graph of your project. Using `ignore` patterns does\nnot exclude files from the analysis, it only suppresses the reporting of issues\nin those files. This hides real issues and creates blind spots. Instead of\nignoring files, ensure your entry points and plugins are configured correctly,\nand use `project` patterns to define the boundaries of your codebase. Read more:\n[Configuring Project Files][3].\n\nIf you have specific exports (such as types) that are only used within the file\nthey are defined, use the [ignoreExportsUsedInFile][4] configuration option\nrather than ignoring the file entirely.\n\n### How should I exclude tests and development tools from the analysis?\n\nA common mistake is trying to exclude test files, storybooks, or development\ntools using `project` or `ignore` patterns. The correct approach is to use\n[production mode][5]. This mode is specifically designed to strictly analyze\nonly your production source code and `dependencies`, automatically excluding\ntests and `devDependencies` without requiring complex ignore rules.\n\n### Why shouldn't I run `knip --fix` immediately?\n\nRunning `knip --fix` before your configuration is fully settled is dangerous. If\nyour configuration is missing entry points or has unresolved hints, Knip might\nthink perfectly valid, actively used code is unused. Auto-fixing in this state\ncan lead to deleting code that your application relies on. Always verify the\nreported issues manually and ensure your configuration is solid before using the\n`--fix` flag.\n\n## Comparison\n\n### Why isn't Knip an ESLint plugin?\n\nLinters like ESLint analyze files separately, while Knip lints projects as a\nwhole.\n\nKnip requires a full module and dependency graph to find clutter across the\nproject. Building the graph is substantial work, especially in monorepos.\n\nFile-oriented linters like ESLint are complementary to Knip.\n\n### Isn't tree-shaking enough?\n\nNo. They share a goal: improving UX by removing unused code. But tree-shaking\nand Knip are different, complementary tools.\n\nTree-shaking is a build-time optimization to reduce production bundle size. It\noperates on bundled production code, which might include external code, and runs\nautomatically (out of your hands).\n\nOn the other hand, Knip is a project linter for the development and QA phase. It\nreports and fixes only your own source code, and leaves the changes for you to\nreview. It focuses on inter-file dependencies, so dead code within a single file\nmay slip through.\n\nBesides those differences, Knip has a broader scope:\n\n- Improve DX (see [less is more][6]).\n- Unless using [production mode][5], also lint all source code like tests,\n  scripts and Storybook stories.\n- Handle more [types of issues][7] (such as unlisted dependencies).\n\nFor how Knip compares to other unused-code tools and how to migrate from them,\nsee [Comparison & Migration][8].\n\n## Synergy\n\n### Why does Knip have plugins?\n\nPlugins are an essential part of Knip. They save you a lot of configuration out\nof the box, by adding entry files as accurately as possible and only for the\ntools actually installed. More powerful still are their custom parsers for\nconfiguration files and command-line argument definitions.\n\nFor instance, Vitest has the `environment` configuration option. The Vitest\nplugin knows `\"node\"` is the default value for `environment` which does not\nrequire an extra package, but will translate `\"edge-runtime\"` to the\n`@edge-runtime/vm` package. This allows Knip to report it if this package is not\nlisted in `package.json`, or when it is no longer used after changes in the\nVitest configuration.\n\nConfiguration files may also contain references to entry files. For instance,\nJest has `setupFilesAfterEnv: \"<rootDir>/jest.setup.js\"` or a reference may\npoint to a file in another workspace in the same monorepo, e.g. `setupFiles:\n['@org/shared/jest-setup.ts']`. Those entry files may also contain imports of\ninternal modules or external dependencies, and so on.\n\n### Why is Knip so heavily engineered?\n\nEven though a modular approach has its merits, for Knip it makes sense to have\nall the pieces in a single tool.\n\nBuilding up the module and dependency graph takes more than standard module\nresolution. It needs dynamic analysis, not just static: plugin parsers actually\nload and execute dynamic tooling configuration files to read their exported\nvalue. On top of that, [exports consumed by external libraries][9] require type\ninformation. And shell script parsing is needed to find the right entry files,\nconfiguration files and dependencies accurately.\n\nThe rippling effect of plugins recursively pulling in more entry files and\ndependencies is exactly what [\"comprehensive\"][10] refers to.\n\n## Design decisions\n\n### Why isn't production mode the default?\n\nThe default mode of Knip includes all source files, tests, dependencies, dev\ndependencies and tooling configuration.\n\nOn the other hand, production mode considers only source files and production\ndependencies. Plugins add only production entry files.\n\nWhich mode should've been the default? They both have their merits:\n\n- Production mode catches dead production code and dependencies. This mode has\n  the most impact on UX, since less code tends to be faster and safer.\n- Default mode potentially catches more issues, e.g. lots of unused plugins of\n  tooling, including most issues found in production mode. This mode has the\n  most impact on DX, for the same reason.\n\nAlso see [production mode][5].\n\n### Why doesn't Knip just read the lockfile?\n\nKnip reads the `package.json` file of each dependency. Most of the information\nrequired is in the lockfile as well, which would be more efficient. However,\nlockfiles lack some data, including:\n\n- It requires lockfile parsing for each lockfile format and version of each\n  package manager.\n- The lockfile doesn't contain whether the package [has types included][11].\n- The lockfile doesn't contain entry point fields (`main`, `module`, `exports`)\n  needed to resolve what a dependency actually exposes.\n- The lockfile doesn't contain `bin` entries to determine installed binaries.\n\n### Why doesn't Knip use an existing module resolver?\n\nIt does: Knip uses [oxc-resolver][12]. A runtime or bundler resolver can't be\nused as-is, because Knip resolves imports to your source across every workspace\nin a (mono)repo. It has to:\n\n- Resolve to source (`src/module.ts`), not type definitions (`module.d.ts`) or\n  the build artifact a `package.json#main` like `dist/module.js` points to\n- Resolve non-standard extensions like `.svelte`, `.astro` and `.css` so those\n  files enter the module graph\n\noxc-resolver is configurable enough for this. Combined with a thin layer for\nKnip-configured `paths` and plugin aliases. This covers resolution across all\nworkspaces and[script parsing][13] and references to files in other workspaces.\n\n### Why doesn't Knip match my TypeScript project structure?\n\nRepositories and workspaces in a monorepo aren't necessarily structured like\nTypeScript projects. Put simply, the location of `package.json` files isn't\nalways adjacent to `tsconfig.json` files. Knip follows the structure of\nworkspaces in a monorepo.\n\nAn additional layering of TypeScript projects would complicate things. The\ndownside is that a `tsconfig.json` file not used by Knip may have conflicting\nmodule resolution settings, potentially resulting in missed files.\n\nIn practice, this is rarely an issue. Knip sticks to the workspaces structure\nand installs a single \"kitchen sink\" module resolver function per workspace.\nDifferent strategies might add more complexity and performance penalties, while\nthe current strategy is simple, fast and good enough.\n\nNote that any directory with a `package.json` not listed in the root\n`package.json#workspaces` can be added to the Knip configuration manually to\nhave it handled as a separate workspace.\n\nIf you do want Knip to take its project files from `tsconfig.json` rather than\nits own `project` patterns, see [`--use-tsconfig-files`][14].\n\n### Why doesn't Knip just use `ts.findReferences`?\n\nTypeScript has a very good \"Find references\" feature, that you might be using in\nyour IDE as well. There are a few reasons Knip doesn't use it:\n\n- It requires the full TypeScript language service, which is heavy to\n  initialize.\n- It must be called per symbol. A project with thousands of exports would need\n  thousands of calls, each scanning potentially all files. Knip parses each file\n  once and resolves all export usages from the resulting graph.\n- It operates within a single TypeScript program. Monorepos with multiple\n  `tsconfig.json` files would need separate language service instances.\n- It cannot see into non-standard files like `.vue`, `.svelte` and `.astro`.\n\nKnip's module graph is also serializable and cacheable, and usable for other\ntools to build upon.\n\n### Why doesn't Knip have...?\n\nExamples of features that have been requested include:\n\n- Expose programmatic API\n- Add local/custom plugins\n- Expose the module and dependency graph\n- Custom AST visitors, e.g. to find and return:\n  - Unused interface/type members\n  - Unused object members (and e.g. React component props)\n  - Unused object props in function return values\n- Analyze workspaces in parallel\n- Support Deno\n\nThese are all interesting ideas, but most increase the API surface area, and all\nrequire more development efforts and maintenance. Time is limited and\n[sponsorships][15] currently don't cover - this can change though!\n\n## Under the hood\n\n### Where does Knip look for entry files?\n\nKnip discovers them from defaults, `package.json`, enabled plugins, source-code\nimports and resolution calls (`require.resolve`, `import.meta.resolve`, `new\nURL`, `new Worker`, `module.register`), and parsed scripts. See [Entry\nFiles][16] for the complete list. Entry files are added to the module graph, and\n[module resolution][17] may result in more entry files recursively until none\nremain.\n\n### What does Knip look for in source files?\n\nKnip uses oxc-parser to parse source files, it's powerful and fault-tolerant.\nKnip visits all nodes of the generated AST to find:\n\n- Imports and dynamic imports of internal modules and external dependencies\n- Exports\n- Accessed properties on namespace imports and re-exports to track individual\n  export usage\n- Entry files from `require.resolve`, `import.meta.resolve`, `new URL(specifier,\nimport.meta.url)`, `new Worker(…)`, `child_process` `fork`/`spawn`/`execFile`,\n  and `module.register()`\n- Scripts passed to the [script parser][13]: tagged `$` templates (`bun`,\n  `execa`, `zx`) and `node:child_process`, `execa` and `nano-spawn` calls\n\n### What's in the graph?\n\nOnce built, the graph holds everything needed to produce the report: every\n[issue type][7], from unused files and dependencies to unused exports, types and\nenum members.\n\nThe graph also surfaces more interesting details, such as:\n\n- Circular references\n- Usage numbers per export\n- Export usage across workspaces in a monorepo\n- List of all binaries used\n- List of all used (OS) binaries not installed in `node_modules`\n\n### How does Knip handle non-standard import syntax?\n\nKnip tries to be resilient against import syntax like what's used by e.g.\nwebpack loaders or Vite asset imports. Knip strips off the prefixes and suffixes\nin import specifiers like this:\n\n```ts title=\"component.ts\"\nimport Icon from './icon.svg?raw';\nimport Styles from '-!style-loader!css-loader?modules!./styles.css';\n```\n\nIn this example, the `style-loader` and `css-loader` dependencies should be\ndependencies found in webpack configuration, handled by Knip's webpack plugin.\n\n## TypeScript\n\n### What's the difference between workspaces, projects and programs?\n\nA workspace is a directory with a `package.json` file. They're configured in\n`package.json#workspaces` (or `pnpm-workspaces.yml`). In case a directory has a\n`package.json` file, but is not a workspace (from a package manager\nperspective), it can be added as a workspace to the Knip configuration.\n\nProjects - in the context of TypeScript - are directories with a `tsconfig.json`\nfile. They're not a concept in Knip.\n\nKnip analyzes all workspaces using a single module graph with a shared module\nresolver.\n\n### What's up with that configurable `tsconfig.json` location?\n\nTwo settings point Knip at a `tsconfig.json`, and they do different things:\n\n- [`--tsConfig [file]`][18] (CLI, root only) sets an alternative location for\n  the root `tsconfig.json`. Knip reads its `compilerOptions`, notably `paths`\n  and `moduleResolution`.\n- [`typescript.config`][19] (plugin, per workspace) sets the location the\n  TypeScript plugin reads to extract referenced dependencies from `extends`,\n  `compilerOptions.types` and JSX settings:\n\n```json title=\"tsconfig.json\"\n{\n  \"extends\": \"@tsconfig/node20/tsconfig.json\",\n  \"compilerOptions\": {\n    \"jsxImportSource\": \"hastscript/svg\"\n  }\n}\n```\n\nFrom this example, Knip can tell whether `@tsconfig/node20` and `hastscript` are\nlisted in `package.json`.\n\nNote that the TypeScript plugin doesn't add TypeScript support to Knip (that's\nbuilt-in); like other plugins, it extracts dependencies from `tsconfig.json`. If\npath aliases from `compilerOptions.paths` aren't picked up, either point\n`--tsConfig` at the right `tsconfig.json` or add [paths][20] to the Knip config\n(per workspace).\n\n### What does `--use-tsconfig-files` do?\n\nBy default Knip discovers project files with its own `project` patterns. The\n[`--use-tsconfig-files`][14] flag instead takes them from `tsconfig.json` per\nworkspace. Those become TypeScript program files, so Knip analyzes their exports\nand dependencies but does not report them as unused files: delegating project\ndefinition to `tsconfig.json` declares them intentional, including empty files.\nThis is by design: use the default `project` patterns (discovery mode) to flag\ndangling files. Implicitly enabled in the [editor extension, MCP server and\nlanguage server][21] without a Knip configuration file.\n\n## Compilers\n\n### How does Knip handle Svelte or Astro files?\n\nTo further increase the coverage of the module graph, non-standard files other\nthan JavaScript and TypeScript modules should be included as well. For instance,\n`.mdx` and `.astro` files can import each other, internal modules and external\ndependencies.\n\nKnip includes basic \"compilers\" for a few common file types (Astro, MDX, Svelte,\nVue). These are lightweight regex-based extractors, not actual compilers. You\ncan override the built-in compilers with your project's actual compiler, and add\nadditional ones for other file types.\n\n### Why are the exports of my `.vue` files not used?\n\nThe built-in compilers extract `import` statements only, so the exports declared\nin a `.vue` or `.svelte` file aren't analyzed and may be reported as unused.\nOverride the built-in with a real compiler. See [Compilers][22].\n\n[1]: ../reference/integrations.md#mcp-server\n[2]: ../reference/integrations.md#vs-code-extension\n[3]: ../guides/configuring-project-files.md\n[4]: ../reference/configuration.md#ignoreexportsusedinfile\n[5]: ../features/production-mode.md\n[6]: ../explanations/why-use-knip.md#less-is-more\n[7]: ./issue-types.md\n[8]: ../explanations/comparison-and-migration.md\n[9]: ../guides/handling-issues.mdx#external-libraries\n[10]: ../explanations/why-use-knip.md#comprehensive\n[11]: ../guides/handling-issues.mdx#type-definition-packages\n[12]: https://oxc.rs/docs/guide/usage/resolver.html\n[13]: ../features/script-parser.md\n[14]: ../reference/cli.md#--use-tsconfig-files\n[15]: /sponsors\n[16]: ../explanations/entry-files.md#where-knip-looks-for-entry-files\n[17]: #why-doesnt-knip-use-an-existing-module-resolver\n[18]: ../reference/cli.md#--tsconfig-file\n[19]: ../explanations/plugins.md#configuration-files\n[20]: ../reference/configuration.md#paths\n[21]: ../reference/integrations.md\n[22]: ../features/compilers.md\n","frontmatter":{"title":"FAQ","description":"Design decisions behind Knip, common pitfalls, how it compares to ESLint and tree-shaking, and how the module graph works.","date":"2024-08-20"},"isInternal":false,"tokens":3980,"sizeBytes":17477},{"name":"integrations.md","path":"packages/docs/src/content/docs/reference/integrations.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/reference/integrations.md","title":"Reference Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Integrations\ndescription: Knip's VS Code extension, JetBrains plugin, MCP server and language server for editor diagnostics and coding agents.\n---\n\n- [VS Code/VSX Extension][1]\n- [JetBrains Plugin][2]\n- [MCP Server][3]\n- [Language Server][4]\n\n## VS Code Extension\n\nThe official VS Code extension provides a rich integration with the [Knip\nLanguage Server][4]:\n\n- **Diagnostics**: Inline warnings for unused dependencies, exports and files\n- **Hover Information**: Hover over exports to see import and usage locations\n- **Imports Tree View**: Direct links to implementations\n- **Exports Tree View**: Direct links to import and usage locations\n- **Contention Detection**: Warnings for circular dependencies, ambiguous,\n  shadowed and diamond-shaped import chains\n- **Built-in MCP Server**: Automated configuration support for coding agents\n\nFind [Knip on the VS Code Marketplace][5] and find [Knip in the Open VSX\nRegistry][6].\n\nSee below for [screenshots][7].\n\n## JetBrains Plugin\n\nA community plugin is available for JetBrains IDEs including WebStorm, IntelliJ\nIDEA, and others. The plugin is powered by the [Knip Language Server][4] and\nprovides diagnostics. Find [Knip on the JetBrains Marketplace][8].\n\n## MCP Server\n\nThe standalone MCP Server enables coding agents to configure Knip automatically.\nTell your agent to \"configure knip\" and it will use the available tools to\ncreate, analyze and optimize your `knip.json` configuration.\n\nThe [Knip MCP Server][9] is available separately and built into the [Knip VS\nCode Extension][1].\n\nStart:\n\n```sh\nnpx @knip/mcp\n```\n\nNote: The VS Code extension has this MCP Server built-in.\n\n## Language Server\n\nThe IDE integrations are powered by the Knip Language Server. It builds the full\nmodule graph of your project and provides a session with a graph explorer. See\nthe [Knip Language Server documentation][10] for more details and information on\nintegrating Knip.\n\n## VS Code Extension Screenshots\n\n### Lint Findings\n\n![Lint Findings][11]\n\n### Imports & Exports\n\n![Hover over imports and exports][12]\n\n### Contention\n\nThe extension shows circular dependencies and three kinds of export contention:\nambiguous, shadowed, and converged.\n\n#### Circular Dependencies\n\n![Circular Dependencies][13]\n\n#### Ambiguous\n\nDifferent bindings compete for the same name, with no winner. Knip lists the\ncompeting bindings:\n\n![Ambiguous][14]\n\n#### Shadowed\n\nAn explicit export hides bindings from `export *`. Knip labels the site as\n\"shadowing\" and lists the winning and hidden bindings:\n\n![Shadowed][15]\n\n#### Converged\n\nThe same binding arrives through multiple re-export paths. Knip shows where\nthose paths meet and the binding they share.\n\n![Converged][16]\n\n### Settings\n\n![VS Code Extension Settings][17]\n\n[1]: #vs-code-extension\n[2]: #jetbrains-plugin\n[3]: #mcp-server\n[4]: #language-server\n[5]: https://marketplace.visualstudio.com/items?itemName=webpro.vscode-knip\n[6]: https://open-vsx.org/extension/webpro/vscode-knip\n[7]: #vs-code-extension-screenshots\n[8]: https://plugins.jetbrains.com/plugin/29765-knip\n[9]: https://www.npmx.dev/package/@knip/mcp\n[10]: https://github.com/webpro-nl/knip/blob/main/packages/language-server/README.md\n[11]: /screenshots/editors-and-agents/diagnostics.webp\n[12]: /screenshots/editors-and-agents/imports-exports.webp\n[13]: /screenshots/editors-and-agents/circular-dependency.webp\n[14]: /screenshots/editors-and-agents/ambiguous.webp\n[15]: /screenshots/editors-and-agents/shadow.webp\n[16]: /screenshots/editors-and-agents/branch.webp\n[17]: /screenshots/editors-and-agents/vscode-extension-settings.webp\n","frontmatter":{"title":"Integrations","description":"Knip's VS Code extension, JetBrains plugin, MCP server and language server for editor diagnostics and coding agents."},"isInternal":false,"tokens":877,"sizeBytes":3582},{"name":"issue-types.md","path":"packages/docs/src/content/docs/reference/issue-types.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/reference/issue-types.md","title":"Reference Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Issue Types\ndescription: Every issue type Knip reports, from unused files and dependencies to unused exports, enum and namespace members, with their filter keys.\ntableOfContents: false\n---\n\nKnip reports the following types of issues:\n\n| Title                                | Description                                                |       | Key                 |\n| :----------------------------------- | :--------------------------------------------------------- | ----- | :------------------ |\n| Unused files                         | Unable to find a reference to this file                    | 🔧    | `files`             |\n| Unused dependencies                  | Unable to find a reference to this dependency              | 🔧    | `dependencies`      |\n| Unused devDependencies               | Unable to find a reference to this devDependency           | 🔧    | `dependencies`²     |\n| Referenced optional peerDependencies | Optional peer dependency is referenced                     |       | `dependencies`²     |\n| Unlisted dependencies                | Used dependencies not listed in package.json               |       | `unlisted`          |\n| Unlisted binaries                    | Binaries from dependencies not listed in package.json      |       | `binaries`          |\n| Unused catalog entries               | Unable to find a reference to this catalog entry           | 🔧    | `catalog`           |\n| Unresolved catalog references        | Catalog does not contain the referenced package            |       | `catalogReferences` |\n| Unresolved imports                   | Unable to resolve this (import) specifier                  |       | `unresolved`        |\n| Unused exports                       | Unable to find a reference to this export                  | 🔧    | `exports`           |\n| Unused exported types                | Unable to find a reference to this exported type           | 🔧    | `types`             |\n| Exports in used namespace            | Namespace with export is referenced, but not export itself | 🔧 🟠 | `nsExports`         |\n| Exported types in used namespace     | Namespace with type is referenced, but not type itself     | 🔧 🟠 | `nsTypes`           |\n| Unused exported enum members         | Unable to find a reference to this enum member             | 🔧    | `enumMembers`       |\n| Unused exported namespace members    | Unable to find a reference to this namespace member        | 🔧    | `namespaceMembers`  |\n| Duplicate exports                    | This is exported more than once                            |       | `duplicates`        |\n| Circular dependencies                | These files (in)directly import each other at runtime      | 🟠    | `cycles`            |\n\n## Legend\n\n|     | Description                                         |\n| --- | :-------------------------------------------------- |\n| 🔧  | [Auto-fixable][1] issue types                       |\n| 🟠  | Not included by default (include with [filters][2]) |\n\n## Notes\n\n1. When an issue type has zero issues, it is not shown.\n2. Including or excluding `dependencies` (via CLI or configuration)\n   automatically includes or excludes `devDependencies` and\n   `optionalPeerDependencies`. In [rules][3], each key can be set individually.\n3. In [strict production mode][4], `devDependencies` are not included.\n4. The `types` issue type includes `enum`, `interface` and `type` exports.\n5. `cycles` defaults to the `warn` [rule][3] (reported, but not counted as an\n   error). Set `rules.cycles` to `error` to fail on circular dependencies.\n\n[1]: ../features/auto-fix.mdx\n[2]: ../features/rules-and-filters.md#filters\n[3]: ../features/rules-and-filters.md#rules\n[4]: ../features/production-mode.md#strict-mode\n","frontmatter":{"title":"Issue Types","description":"Every issue type Knip reports, from unused files and dependencies to unused exports, enum and namespace members, with their filter keys.","tableOfContents":false},"isInternal":false,"tokens":760,"sizeBytes":3789},{"name":"jsdoc-tsdoc-tags.md","path":"packages/docs/src/content/docs/reference/jsdoc-tsdoc-tags.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/reference/jsdoc-tsdoc-tags.md","title":"Reference Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: JSDoc & TSDoc Tags\ndescription: Use JSDoc and TSDoc tags like `@public`, `@internal`, `@alias` and custom tags to include or exclude exports from Knip's report.\n---\n\nJSDoc or TSDoc tags can be used to make exceptions for unused or duplicate\nexports.\n\nKnip tries to minimize configuration and introduces no new syntax. That's why it\nhooks into JSDoc and TSDoc tags.\n\n:::caution\n\nAdding tags or excluding a certain type of issues from the report is usually not\nrecommended. It hides issues, which is often a sign of code smell or ambiguity\nand ends up harder to maintain. It's usually better to refactor the code (or\nreport an issue with Knip for false positives).\n\n:::\n\nTags also work in regular block comments (`/* ... */`) and standalone line\ncomments (`// ...`) before a declaration. These comments keep suppression tags\nout of JSDoc hover information.\n\nTags in consecutive comments are combined. Trailing `//` comments are ignored.\n\n## Tags\n\nUse arbitrary [tags][1] to exclude or include tagged exports from the report.\nExample:\n\n```ts\n/** @lintignore */\nexport const myUnusedExport = 1;\n\n// @lintignore\nimport Unresolved from './generated/lib.js';\n```\n\nAnd then include (`+`) or exclude (`-`) these tagged exports from the report\nlike so:\n\n```shell\nknip --tags=-lintignore,-internal\n```\n\nTags can also be [configured in `knip.json`][2].\n\nWhen an excluded tag is no longer necessary because the export is actually used,\nKnip reports a **tag hint**:\n\n```sh\nTag hints (1)\nignored  unimported.ts  Unused tag in unimported.ts: ignored → @custom\n```\n\nThis helps you clean up tags that were added to suppress issues that have since\nbeen resolved.\n\n## `@public`\n\nBy default, Knip reports unused exports in non-entry files.\n\nTag the export as `@public` and Knip will not report it.\n\nExample:\n\n```ts\n/**\n * @public\n */\nexport const unusedFunction = () => {};\n```\n\nThis tag can also be used to make exceptions in entry files when using\n[--include-entry-exports][3].\n\n[JSDoc: @public][4] and [TSDoc: @public][5]\n\n## `@internal`\n\nInternal exports are not meant for public consumption, but only for internal\nusage such as tests. This means they would be reported in [production mode][6].\n\nMark the export with `@internal` and Knip will not report the export in\nproduction mode.\n\nExample:\n\n```ts\n/** @internal */\nexport const internalTestedFunction = () => {};\n```\n\nIn general it's not recommended to expose and test implementation details, but\nexceptions are possible. Those should not be reported as false positives, so\nwhen using production mode you'll need to help Knip out by tagging them as\n`@internal`.\n\n[TSDoc: @internal][7]\n\n## `@alias`\n\nKnip reports duplicate exports. To prevent this, tag one of the exports as\n`@alias`.\n\nExample:\n\n```ts\nexport const Component = () => {};\n\n/** @alias */\nexport default Component;\n```\n\nAn alternative solution is to use `--exclude duplicates` and exclude all\nduplicates from being reported.\n\n[JSDoc: @alias][8]\n\n## `@beta`\n\nWorks identical to [`@public`][9]. Knip ignores other tags like `@alpha` and\n`@experimental`.\n\n[TSDoc: @beta][10]\n\n[1]: ../reference/cli.md#--tags\n[2]: ./configuration.md#tags\n[3]: ./cli.md#--include-entry-exports\n[4]: https://jsdoc.app/tags-public.html\n[5]: https://tsdoc.org/pages/tags/public/\n[6]: ../features/production-mode.md\n[7]: https://tsdoc.org/pages/tags/internal/\n[8]: https://jsdoc.app/tags-alias.html\n[9]: #public\n[10]: https://tsdoc.org/pages/tags/beta/\n","frontmatter":{"title":"JSDoc & TSDoc Tags","description":"Use JSDoc and TSDoc tags like `@public`, `@internal`, `@alias` and custom tags to include or exclude exports from Knip's report."},"isInternal":false,"tokens":868,"sizeBytes":3439},{"name":"known-issues.md","path":"packages/docs/src/content/docs/reference/known-issues.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/reference/known-issues.md","title":"Reference Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Known Issues\ndescription: Known limitations and workarounds for caching, config file errors, path aliases in config files, and the Nx daemon.\n---\n\nKnown limitations and workarounds for errors during a Knip run.\n\nSee [handling issues][1] to learn more about dealing with lint issues.\n\n## Exceptions from config files\n\nKnip plugins may fail to load a JavaScript or TypeScript configuration file such\nas `webpack.config.js` or `vite.config.ts`:\n\n```sh\n$ knip\nERROR: Error loading vite.config.ts\n```\n\nKnip exits with code `2` when a plugin config file fails to load.\n`--no-exit-code` does not suppress this error.\n\nKnip may load such files differently, in a different environment, with missing\nenvironment variables, missing path aliases, etcetera. Use `--debug` to locate\nthe cause of the issue with more details.\n\nPotential workarounds:\n\n- For \"Cannot find module\" and \"ENOENT: no such file/dir, open './file'\" errors:\n  - Install dependencies\n  - Use absolute paths, e.g. with `path.join()` or `path.resolve()`\n  - [Set path aliases][2]\n- Set missing environment variable(s), potential solutions:\n  - Use a helper package like [dotenvx][3]\n  - `KEY=VAL knip`\n  - `node --env-file .env $(which knip)`\n- Run the build script to generate required files.\n- Disable loading the file by overriding the default `config` for that plugin.\n  - Example: `vite: { config: [] }`\n  - In a monorepo, be more specific like so: `workspaces: { \"packages/lib\": {\nvite: { config: [] } } }`\n  - If this helps, add the file as an `entry` file for static analysis.\n- Disable the related plugin.\n  - Example: `eslint: false`\n  - In a monorepo, be more specific like so: `workspaces: { \"packages/lib\": {\neslint: false } }`\n  - If this helps, add the file as an `entry` file for static analysis.\n- As a last resort, ignore the workspace: `ignoreWorkspaces: [\"packages/lib\"]`.\n\n## Path aliases in config files\n\nLoading the configuration file (e.g. `cypress.config.ts`) for one of Knip's\nplugins may give an error:\n\n```sh\n$ knip\nAnalyzing workspace ....\nError loading .../cypress.config.ts\nReason: Cannot find module '@alias/name'\nRequire stack:\n- .../cypress.config.ts\n```\n\nSome tools (such as Cypress and Jest) support using TypeScript path aliases in\nthe configuration file.\n\nPotential workarounds:\n\n- Rewrite the import in the configuration file to a relative import.\n- Inject support with a module like `tsx`: `NODE_OPTIONS=\"--import tsx\" knip`\n- Or `tsconfig-paths`: `NODE_OPTIONS=\"--import tsconfig-paths/register.js\" knip`\n- Use Bun with [knip-bun][4].\n- See [exceptions from config files][5] for more potential workarounds.\n\n## Nx Daemon\n\nIn Nx projects you might encounter this error:\n\n```sh\nNX   Daemon process terminated and closed the connection\n```\n\nThe solution is to [disable the Nx Daemon][6]:\n\n```sh\nNX_DAEMON=false knip\n```\n\n## Raw transfer memory errors\n\nOn machines with low RAM or Windows with Node.js >=22, oxc-parser raw transfer\nmay fail under memory pressure:\n\n```sh\nRangeError: Array buffer allocation failed\n```\n\nDisable raw transfer to use the normal parser path:\n\n```sh\nKNIP_DISABLE_RAW_TRANSFER=1 knip\n```\n\n## Stale cache results\n\nWith `--cache`, configuration or path alias changes may leave results stale. An\nimport may still be reported as unresolved after the missing file is added.\nNewly added `.gitignore` files are also not detected automatically.\n\nRun without `--cache` for fresh results, or delete the cache directory\n(`node_modules/.cache/knip` by default, configurable with `--cache-location`)\nbefore running with `--cache` again.\n\n[1]: ../guides/handling-issues.mdx\n[2]: #path-aliases-in-config-files\n[3]: https://dotenvx.com/\n[4]: ./cli.md#knip-bun\n[5]: #exceptions-from-config-files\n[6]: https://nx.dev/concepts/nx-daemon#turning-it-off\n","frontmatter":{"title":"Known Issues","description":"Known limitations and workarounds for caching, config file errors, path aliases in config files, and the Nx daemon."},"isInternal":false,"tokens":952,"sizeBytes":3764},{"name":"plugins.md","path":"packages/docs/src/content/docs/reference/plugins.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/reference/plugins.md","title":"Reference Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Plugins (177)\ndescription: 'The full list of Knip plugins for frameworks, build tools, test runners and linters, each linking to its reference page.'\ntableOfContents: false\n---\n\n:::section{.columns.min200}\n\n- [Angular][1]\n- [Astro][2]\n- [Astro DB][3]\n- [Astro Markdoc][4]\n- [astro-og-canvas][5]\n- [Ava][6]\n- [Babel][7]\n- [Biome][8]\n- [bumpp][9]\n- [Bun][10]\n- [c8][11]\n- [Capacitor][12]\n- [Catalyst][13]\n- [Changelogen][14]\n- [Changelogithub][15]\n- [Changesets][16]\n- [Commitizen][17]\n- [commitlint][18]\n- [Convex][19]\n- [create-typescript-app][20]\n- [CSpell][21]\n- [Cucumber][22]\n- [Cypress][23]\n- [Danger][24]\n- [dependency-cruiser][25]\n- [Docusaurus][26]\n- [dotenv][27]\n- [Drizzle][28]\n- [electron-vite][29]\n- [Eleventy][30]\n- [esbuild][31]\n- [ESLint][32]\n- [eve][33]\n- [execa][34]\n- [Expo][35]\n- [Expressive Code][36]\n- [FAST][37]\n- [Fumadocs][38]\n- [Gatsby][39]\n- [GitHub Action][40]\n- [GitHub Actions][41]\n- [glob][42]\n- [GraphQL Codegen][43]\n- [Hardhat][44]\n- [husky][45]\n- [i18next Parser][46]\n- [Jest][47]\n- [Karma][48]\n- [Knex][49]\n- [Ladle][50]\n- [laravel-vite-plugin][51]\n- [Lefthook][52]\n- [lint-staged][53]\n- [LintHTML][54]\n- [Lit][55]\n- [lockfile-lint][56]\n- [Lost Pixel][57]\n- [Lunaria][58]\n- [markdownlint][59]\n- [MDX][60]\n- [mdxlint][61]\n- [Metro][62]\n- [Mocha][63]\n- [moonrepo][64]\n- [Mock Service Worker][65]\n- [nano-spawn][66]\n- [Nano Staged][67]\n- [Nest][68]\n- [Netlify][69]\n- [Next.js][70]\n- [next-intl][71]\n- [Next.js MDX][72]\n- [Nitro][73]\n- [Node.js][74]\n- [node-modules-inspector][75]\n- [nodemon][76]\n- [npm-package-json-lint][77]\n- [Nuxt][78]\n- [@nuxtjs/i18n][79]\n- [Nx][80]\n- [nyc][81]\n- [oclif][82]\n- [openapi-ts][83]\n- [orval][84]\n- [Oxfmt][85]\n- [Oxlint][86]\n- [Panda CSS][87]\n- [Parcel][88]\n- [Payload CMS][89]\n- [pino][90]\n- [Playwright][91]\n- [Playwright for components][92]\n- [playwright-test][93]\n- [Plop][94]\n- [pm2][95]\n- [pnpm][96]\n- [PostCSS][97]\n- [Preconstruct][98]\n- [Prettier][99]\n- [Prisma][100]\n- [Quasar][101]\n- [Qwik][102]\n- [Raycast][103]\n- [React Cosmos][104]\n- [React Email][105]\n- [React Native][106]\n- [React Router][107]\n- [Relay][108]\n- [Release It!][109]\n- [Remark][110]\n- [Remix][111]\n- [Rolldown][112]\n- [Rollup][113]\n- [Rsbuild][114]\n- [Rslib][115]\n- [Rspack][116]\n- [Rstest][117]\n- [Sanity][118]\n- [Semantic Release][119]\n- [Sentry][120]\n- [Serverless Framework][121]\n- [simple-git-hooks][122]\n- [size-limit][123]\n- [SST][124]\n- [Starlight][125]\n- [Stencil][126]\n- [Storybook][127]\n- [Stryker][128]\n- [Stylelint][129]\n- [Svelte][130]\n- [@sveltejs/package][131]\n- [SvelteKit][132]\n- [SVGO][133]\n- [SVGR][134]\n- [SWC][135]\n- [Syncpack][136]\n- [Tailwind][137]\n- [TanStack Router][138]\n- [Taskfile][139]\n- [Tauri][140]\n- [Temporal.io][141]\n- [Travis CI][142]\n- [ts-node][143]\n- [tsdown][144]\n- [tsup][145]\n- [tsx][146]\n- [TypeDoc][147]\n- [TypeScript][148]\n- [unbuild][149]\n- [UnoCSS][150]\n- [unplugin-auto-import][151]\n- [unplugin-icons][152]\n- [unplugin-vue-components][153]\n- [@intlify/unplugin-vue-i18n][154]\n- [unplugin-vue-markdown][155]\n- [unplugin-vue-router][156]\n- [Vercel][157]\n- [Vercel OG][158]\n- [Vike][159]\n- [Vite][160]\n- [vite-plugin-pages][161]\n- [vite-plugin-pwa][162]\n- [vite-plugin-vue-layouts-next][163]\n- [vite-plus][164]\n- [@vite-pwa/assets-generator][165]\n- [VitePress][166]\n- [Vitest][167]\n- [Vue][168]\n- [WebdriverIO][169]\n- [webpack][170]\n- [Wireit][171]\n- [Wrangler][172]\n- [WXT][173]\n- [xo][174]\n- [Yarn][175]\n- [yorkie][176]\n- [zx][177]\n\n:::\n\n[1]: /reference/plugins/angular\n[2]: /reference/plugins/astro\n[3]: /reference/plugins/astro-db\n[4]: /reference/plugins/astro-markdoc\n[5]: /reference/plugins/astro-og-canvas\n[6]: /reference/plugins/ava\n[7]: /reference/plugins/babel\n[8]: /reference/plugins/biome\n[9]: /reference/plugins/bumpp\n[10]: /reference/plugins/bun\n[11]: /reference/plugins/c8\n[12]: /reference/plugins/capacitor\n[13]: /reference/plugins/catalyst\n[14]: /reference/plugins/changelogen\n[15]: /reference/plugins/changelogithub\n[16]: /reference/plugins/changesets\n[17]: /reference/plugins/commitizen\n[18]: /reference/plugins/commitlint\n[19]: /reference/plugins/convex\n[20]: /reference/plugins/create-typescript-app\n[21]: /reference/plugins/cspell\n[22]: /reference/plugins/cucumber\n[23]: /reference/plugins/cypress\n[24]: /reference/plugins/danger\n[25]: /reference/plugins/dependency-cruiser\n[26]: /reference/plugins/docusaurus\n[27]: /reference/plugins/dotenv\n[28]: /reference/plugins/drizzle\n[29]: /reference/plugins/electron-vite\n[30]: /reference/plugins/eleventy\n[31]: /reference/plugins/esbuild\n[32]: /reference/plugins/eslint\n[33]: /reference/plugins/eve\n[34]: /reference/plugins/execa\n[35]: /reference/plugins/expo\n[36]: /reference/plugins/expressive-code\n[37]: /reference/plugins/fast\n[38]: /reference/plugins/fumadocs\n[39]: /reference/plugins/gatsby\n[40]: /reference/plugins/github-action\n[41]: /reference/plugins/github-actions\n[42]: /reference/plugins/glob\n[43]: /reference/plugins/graphql-codegen\n[44]: /reference/plugins/hardhat\n[45]: /reference/plugins/husky\n[46]: /reference/plugins/i18next-parser\n[47]: /reference/plugins/jest\n[48]: /reference/plugins/karma\n[49]: /reference/plugins/knex\n[50]: /reference/plugins/ladle\n[51]: /reference/plugins/laravel-vite-plugin\n[52]: /reference/plugins/lefthook\n[53]: /reference/plugins/lint-staged\n[54]: /reference/plugins/linthtml\n[55]: /reference/plugins/lit\n[56]: /reference/plugins/lockfile-lint\n[57]: /reference/plugins/lost-pixel\n[58]: /reference/plugins/lunaria\n[59]: /reference/plugins/markdownlint\n[60]: /reference/plugins/mdx\n[61]: /reference/plugins/mdxlint\n[62]: /reference/plugins/metro\n[63]: /reference/plugins/mocha\n[64]: /reference/plugins/moonrepo\n[65]: /reference/plugins/msw\n[66]: /reference/plugins/nano-spawn\n[67]: /reference/plugins/nano-staged\n[68]: /reference/plugins/nest\n[69]: /reference/plugins/netlify\n[70]: /reference/plugins/next\n[71]: /reference/plugins/next-intl\n[72]: /reference/plugins/next-mdx\n[73]: /reference/plugins/nitro\n[74]: /reference/plugins/node\n[75]: /reference/plugins/node-modules-inspector\n[76]: /reference/plugins/nodemon\n[77]: /reference/plugins/npm-package-json-lint\n[78]: /reference/plugins/nuxt\n[79]: /reference/plugins/nuxtjs-i18n\n[80]: /reference/plugins/nx\n[81]: /reference/plugins/nyc\n[82]: /reference/plugins/oclif\n[83]: /reference/plugins/openapi-ts\n[84]: /reference/plugins/orval\n[85]: /reference/plugins/oxfmt\n[86]: /reference/plugins/oxlint\n[87]: /reference/plugins/panda-css\n[88]: /reference/plugins/parcel\n[89]: /reference/plugins/payload\n[90]: /reference/plugins/pino\n[91]: /reference/plugins/playwright\n[92]: /reference/plugins/playwright-ct\n[93]: /reference/plugins/playwright-test\n[94]: /reference/plugins/plop\n[95]: /reference/plugins/pm2\n[96]: /reference/plugins/pnpm\n[97]: /reference/plugins/postcss\n[98]: /reference/plugins/preconstruct\n[99]: /reference/plugins/prettier\n[100]: /reference/plugins/prisma\n[101]: /reference/plugins/quasar\n[102]: /reference/plugins/qwik\n[103]: /reference/plugins/raycast\n[104]: /reference/plugins/react-cosmos\n[105]: /reference/plugins/react-email\n[106]: /reference/plugins/react-native\n[107]: /reference/plugins/react-router\n[108]: /reference/plugins/relay\n[109]: /reference/plugins/release-it\n[110]: /reference/plugins/remark\n[111]: /reference/plugins/remix\n[112]: /reference/plugins/rolldown\n[113]: /reference/plugins/rollup\n[114]: /reference/plugins/rsbuild\n[115]: /reference/plugins/rslib\n[116]: /reference/plugins/rspack\n[117]: /reference/plugins/rstest\n[118]: /reference/plugins/sanity\n[119]: /reference/plugins/semantic-release\n[120]: /reference/plugins/sentry\n[121]: /reference/plugins/serverless-framework\n[122]: /reference/plugins/simple-git-hooks\n[123]: /reference/plugins/size-limit\n[124]: /reference/plugins/sst\n[125]: /reference/plugins/starlight\n[126]: /reference/plugins/stencil\n[127]: /reference/plugins/storybook\n[128]: /reference/plugins/stryker\n[129]: /reference/plugins/stylelint\n[130]: /reference/plugins/svelte\n[131]: /reference/plugins/sveltejs-package\n[132]: /reference/plugins/sveltekit\n[133]: /reference/plugins/svgo\n[134]: /reference/plugins/svgr\n[135]: /reference/plugins/swc\n[136]: /reference/plugins/syncpack\n[137]: /reference/plugins/tailwind\n[138]: /reference/plugins/tanstack-router\n[139]: /reference/plugins/taskfile\n[140]: /reference/plugins/tauri\n[141]: /reference/plugins/temporal\n[142]: /reference/plugins/travis\n[143]: /reference/plugins/ts-node\n[144]: /reference/plugins/tsdown\n[145]: /reference/plugins/tsup\n[146]: /reference/plugins/tsx\n[147]: /reference/plugins/typedoc\n[148]: /reference/plugins/typescript\n[149]: /reference/plugins/unbuild\n[150]: /reference/plugins/unocss\n[151]: /reference/plugins/unplugin-auto-import\n[152]: /reference/plugins/unplugin-icons\n[153]: /reference/plugins/unplugin-vue-components\n[154]: /reference/plugins/unplugin-vue-i18n\n[155]: /reference/plugins/unplugin-vue-markdown\n[156]: /reference/plugins/unplugin-vue-router\n[157]: /reference/plugins/vercel\n[158]: /reference/plugins/vercel-og\n[159]: /reference/plugins/vike\n[160]: /reference/plugins/vite\n[161]: /reference/plugins/vite-plugin-pages\n[162]: /reference/plugins/vite-plugin-pwa\n[163]: /reference/plugins/vite-plugin-vue-layouts-next\n[164]: /reference/plugins/vite-plus\n[165]: /reference/plugins/vite-pwa-assets-generator\n[166]: /reference/plugins/vitepress\n[167]: /reference/plugins/vitest\n[168]: /reference/plugins/vue\n[169]: /reference/plugins/webdriver-io\n[170]: /reference/plugins/webpack\n[171]: /reference/plugins/wireit\n[172]: /reference/plugins/wrangler\n[173]: /reference/plugins/wxt\n[174]: /reference/plugins/xo\n[175]: /reference/plugins/yarn\n[176]: /reference/plugins/yorkie\n[177]: /reference/plugins/zx\n","frontmatter":{"title":"Plugins (177)","description":"The full list of Knip plugins for frameworks, build tools, test runners and linters, each linking to its reference page.","tableOfContents":false},"isInternal":false,"tokens":3127,"sizeBytes":9606},{"name":"related-tooling.md","path":"packages/docs/src/content/docs/reference/related-tooling.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/reference/related-tooling.md","title":"Reference Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Related Tooling\ndescription: Tools that complement Knip for things it does not cover, like unused imports and variables, and unused properties of objects and types.\n---\n\nThis is an overview of related tooling for features Knip does not support.\n\n## Unused imports & variables\n\nKnip doesn't look for unused imports and variables within a file. The focus is\non exported values and types across files.\n\nUse [ESLint][1], [Biome][2] or [oxlint][3] to find unused variables within\nfiles.\n\nUse [remove-unused-vars][4] to remove unused code within files, but in a more\nvaliant way. Using input from any of the above linters, it actually removes a\nlot more unused code. This pairs great with Knip.\n\n## Unused properties\n\nKnip does not yet support finding unused members of types, interfaces and\nobjects. This includes returned objects from exported functions and objects\npassed as React component props.\n\nKnip does support finding unused members of enums and classes, and exported\nvalues and types on imported namespaces.\n\n## Circular dependencies\n\nKnip reports circular dependencies as an opt-in [`cycles`][5] issue type. The\n[editor integrations][6] show cyclic paths directly in IDE.\n\nOther dedicated tools include [DPDM][7], [Madge][8] and [skott][9]. Linters such\nas ESLint have similar plugins and rules, e.g. the `eslint-plugin-import-x`\nplugin has the [import-x/no-cycle][10] and oxlint has the [import/no-cycle][11]\nrule.\n\n## Cleanup\n\nThe [e18e.dev][12] website and in particular the [Cleanup][13] section is a\ngreat resource when dealing with technical debt.\n\n[1]: https://eslint.org\n[2]: https://biomejs.dev/linter/\n[3]: https://oxc.rs/docs/guide/usage/linter.html\n[4]: https://github.com/webpro-nl/remove-unused-vars\n[5]: ./issue-types.md\n[6]: ./integrations.md#circular-dependencies\n[7]: https://github.com/acrazing/dpdm\n[8]: https://github.com/pahen/madge\n[9]: https://github.com/antoine-coulon/skott\n[10]: https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-cycle.md\n[11]: https://oxc.rs/docs/guide/usage/linter/rules/import/no-cycle.html\n[12]: https://e18e.dev\n[13]: https://e18e.dev/guide/cleanup.html\n","frontmatter":{"title":"Related Tooling","description":"Tools that complement Knip for things it does not cover, like unused imports and variables, and unused properties of objects and types."},"isInternal":false,"tokens":549,"sizeBytes":2143},{"name":"unused-dependencies.md","path":"packages/docs/src/content/docs/typescript/unused-dependencies.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/typescript/unused-dependencies.md","title":"Typescript Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Unused dependencies\ndescription: Find and remove unused dependencies with Knip\nprev: false\nnext: false\n---\n\nOne of Knip's core features is finding unused dependencies in your JavaScript\nand TypeScript projects. And it comes with many more features to remove clutter\nand keep your projects in great shape.\n\n## Why are unused dependencies a problem?\n\nHaving unused dependencies in your `package.json` is an issue for various\nreasons:\n\n- They might end up in the final production bundle, increasing size and load\n  times for end users.\n- They waste space in `node_modules` and add to the installation time of the\n  project.\n- They slow down tooling such as linters and bundlers that analyze dependencies.\n- They are confusing and noisy in `package.json`.\n- They cause unnecessary extra work when managing and upgrading dependencies.\n- They can cause version conflicts with other dependencies in use.\n- They can cause false security alerts.\n- They might have restrictive licenses and make your project subject to theirs.\n- They usually come with transitive dependencies that have the same issues.\n\n## How do I find unused dependencies?\n\nUse Knip to find and remove unused dependencies. It also finds dependencies that\nare missing in `package.json` and has a lot more features to keep your\nJavaScript and TypeScript projects tidy.\n\nIt's easy to [get started][1] and make package management easier and more fun!\n\n<div style=\"display: flex; justify-content: center; margin: 4rem auto;\">\n  <img src=\"/logo.svg\" alt=\"Logo of Knip, to find unused dependencies, exports and files\" class=\"logo-border\" />\n</div>\n\n## How does Knip identify unused dependencies?\n\nKnip works by analyzing `package.json` files, source code and configuration\nfiles for other tooling in the project to find unused and missing dependencies.\nKnip has many heuristics, [plugins][2] and [compilers][3] to fully automate the\nprocess.\n\n## Can Knip remove unused dependencies?\n\nYes, Knip can automatically remove unused dependencies installed by a package\nmanager like npm or pnpm for you. Add the `--fix` argument to [auto-fix][4] and\nremove unused dependencies from `package.json`.\n\n## Can Knip detect missing dependencies?\n\nYes, Knip detects missing dependencies. It analyzes `package.json` files, and\nreports packages that are missing. They should be added to `package.json` to\navoid relying on transitive dependencies that can cause version mismatches and\nbreakage.\n\n## Does Knip work with monorepos?\n\nYes, Knip has first-class support for [monorepos and workspaces][5]. It analyzes\nall workspaces in the project and understands their relationship.\n\nFor instance, if a dependency is listed in the root `package.json` it does not\nneed to be listed in other workspaces. Except if you enable `--strict` checking.\n\n## Does Knip separate dependencies and devDependencies?\n\nYes, Knip understands the difference between dependencies and devDependencies.\nIt has a [production mode][6] to focus on production code only and find dead\ncode and dependencies that would otherwise only be referenced by tests and other\ntooling. This allows you to remove both unused exported code and their tests.\n\n## Does Knip work with my package manager?\n\nYes, Knip works with any package manager: npm, pnpm, Bun and Yarn are all\nsupported. It's easy to [get started][1] with any package manager.\n\n[1]: ../overview/getting-started.mdx\n[2]: ../reference/plugins.md\n[3]: ../features/compilers.md\n[4]: ../features/auto-fix.mdx\n[5]: ../features/monorepos-and-workspaces.md\n[6]: ../features/production-mode.md\n","frontmatter":{"title":"Unused dependencies","description":"Find and remove unused dependencies with Knip","prev":false,"next":false},"isInternal":false,"tokens":787,"sizeBytes":3551},{"name":"unused-exports.md","path":"packages/docs/src/content/docs/typescript/unused-exports.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/typescript/unused-exports.md","title":"Typescript Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Unused exports\ndescription: Find and remove unused exports with Knip\nprev: false\nnext: false\n---\n\nFinding unused exports in your JavaScript and TypeScript projects is one of\nKnip's core features. And it comes with even more features to identify and\nremove clutter to keep your projects in great shape.\n\n## Why are unused exports a problem?\n\nHaving unused exports in your codebase is problematic for several reasons:\n\n- They increase bundle sizes if not properly eliminated by tree-shaking.\n- They clutter the codebase and make it harder to navigate and understand.\n- They mislead developers into thinking certain code is used when it's not.\n- They make refactoring and maintaining the codebase more difficult.\n- They slow down tooling that analyze the codebase, such as bundlers, linters\n  and type checkers.\n- They may represent dead code that is no longer needed but hasn't been cleaned\n  up.\n\n## How do I find unused exports?\n\nKnip is a powerful tool that can help you find and remove unused exports in your\nJavaScript and TypeScript projects. It analyzes the codebase, identifies exports\nthat are not imported anywhere, and reports them.\n\n[Get started and install Knip][1] to run it on your project. Knip will scan your\nfiles and provide a detailed report of unused exports, and much more.\n\n<div style=\"display: flex; justify-content: center; margin: 4rem auto;\">\n  <img src=\"/logo.svg\" alt=\"Logo of Knip, to find unused dependencies, exports and files\" class=\"logo-border\" />\n</div>\n\n## How does Knip identify unused exports?\n\nKnip performs both static and dynamic analysis to determine which exports are\nactually being used in your codebase. It looks at import statements, export\nusage, and [a lot more code patterns][2] to identify unused exports.\n\nKnip supports JavaScript and TypeScript projects, and handles both [CommonJS][3]\nand ES Modules syntax.\n\n## Can Knip remove unused exports?\n\nYes, Knip not only finds unused exports but can also remove them for you. Run\nKnip with the `--fix` flag to enable [the auto-fix feature][4], and it will\nmodify your source code and remove the unused exports.\n\nIt's always recommended to review the changes made by Knip before committing\nthem to ensure no unintended modifications were made.\n\n## Can Knip handle large codebases?\n\nAbsolutely. Knip supports [monorepos with workspaces][5] to efficiently analyze\nlarge monorepos. This makes it easier and more fun to manage and optimize large\nmulti-package projects.\n\n## Does Knip work with my favorite editor or IDE?\n\nKnip is a command-line tool that runs independently of your editor or IDE.\nHowever, if you run Knip inside an integrated IDE terminal, the report contains\nfile names and positions in a format IDEs like VS Code and WebStorm understand\nto easily navigate around.\n\n## How is Knip different from ESLint for finding unused exports?\n\nWhile linters like ESLint can find unused imports and variables within\nindividual files, Knip analyzes the entire project to determine which exports\nare actually unused. By building [a comprehensive module graph][6], Knip\nidentifies exports that are not imported or used anywhere in the codebase. This\nallows Knip to catch unused exports and dead code that ESLint and other linters\nwould miss.\n\nAlso see [Why isn't Knip an ESLint plugin?][7]\n\n[1]: ../overview/getting-started.mdx\n[2]: ../reference/faq.md#what-does-knip-look-for-in-source-files\n[3]: ../guides/working-with-commonjs.md\n[4]: ../features/auto-fix.mdx\n[5]: ../features/monorepos-and-workspaces.md\n[6]: ../reference/faq.md#whats-in-the-graph\n[7]: ../reference/faq.md#why-isnt-knip-an-eslint-plugin\n","frontmatter":{"title":"Unused exports","description":"Find and remove unused exports with Knip","prev":false,"next":false},"isInternal":false,"tokens":825,"sizeBytes":3611},{"name":"argument-parsing.md","path":"packages/docs/src/content/docs/writing-a-plugin/argument-parsing.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/writing-a-plugin/argument-parsing.md","title":"Writing-a-plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Argument Parsing\ndescription: Reference for a Knip plugin `arg` object to parse a tool's command-line arguments and find dependencies and entry files in scripts.\n---\n\nSome plugins have an `arg` object in their implementation. It's a way for\nplugins to customize how command-line arguments are parsed for their tool's\nexecutables. Argument parsing in plugins help Knip identify dependencies and\nentry files from scripts.\n\nKnip parses these arguments with a built-in parser. The options below customize\nhow a tool's scripts are parsed. Here's an example:\n\n```ts\nconst args = {\n  args: (args) => args  // modify/filter the array of raw args\n  config: true,         // shorthand to add `--config [config file]` (and shortcut `-c`) as a `config` file\n  fromArgs: ['exec'],   // re-parse what's behind `exec` as a new script\n};\n\nexport default {\n  title: 'my-plugin',\n  args\n}\n```\n\nAlso see [type definitions][1] and [examples in existing plugins][2].\n\n- [alias][3]\n- [args][4]\n- [binaries][5]\n- [boolean][6]\n- [config][7]\n- [fromArgs][8]\n- [nodeImportArgs][9]\n- [positional][10]\n- [resolve][11]\n- [resolveInputs][12]\n- [string][13]\n\n## alias\n\nDefine aliases.\n\nExample:\n\n```ts\n{\n  require: ['r'];\n}\n```\n\nAlso see [nodeImportArgs][9].\n\n## args\n\nModify or filter arguments before parsing. For edge cases preprocessing is\nuseful, e.g. if the parser has trouble parsing or to modify/discard arguments.\n\nExample:\n\n```ts\n{\n  args: (args: string[]) => args.filter(arg => arg !== 'omit');\n}\n```\n\n## binaries\n\nExecutables for the dependency.\n\nExample:\n\n```ts\n{\n  binaries: ['tsc'];\n}\n```\n\nDefault: plugin name, e.g. for the ESLint plugin the value is `[\"eslint\"]`\n\n## boolean\n\nMark arguments as boolean. By default, arguments are expected to have string\nvalues.\n\n## config\n\nDefine arguments that contain the configuration file path. Usually you'll want\nto set aliases too. Use `true` for shorthand to set `alias` + `string` +\n`config`.\n\nExample:\n\n```ts\n{\n  config: true;\n}\n```\n\nThe `tsup` plugin has this. Now `tsup --config tsup.client.json` will have\n`tsup.client.json` go through `resolveConfig` (also `-c` alias).\n\nExample:\n\n```ts\n{\n  config: ['p'];\n}\n```\n\nThis will mark e.g. `tsc -p tsconfig.lib.json` as a configuration file and it\nwill be handled by `resolveConfig` of the (typescript) plugin.\n\n## fromArgs\n\nParse return value as a new script. Can be a an array of strings, or function\nthat returns an array of strings and those values will be parsed separately.\n\nExample:\n\n```ts\n{\n  fromArgs: ['exec'];\n}\n```\n\nThen this script:\n\n```sh\nnodemon --exec \"node index.js\"\n```\n\nWill have `\"node index.js\"` being parsed as a new script.\n\n## nodeImportArgs\n\nSet to `true` as a shorthand for this [alias][3]:\n\n```ts\n{\n  import: ['r', 'experimental-loader', 'require', 'loader']\n}\n```\n\nExample:\n\n```ts\n{\n  nodeImportArgs: true;\n}\n```\n\n## positional\n\nSet to `true` to use the first positional argument as an entry point.\n\nExample:\n\n```ts\n{\n  positional: true;\n}\n```\n\nThe `tsx` plugin has this and `\"tsx script.ts\"` as a script will result in the\n`script.ts` file being an entry point.\n\n## resolve\n\nList of arguments to resolve to a dependency or entry file path.\n\nExample:\n\n```ts\n{\n  resolve: ['plugin'];\n}\n```\n\nNow for a script like `\"program --plugin package\"` this will result in\n`\"package\"` being resolved as a dependency.\n\n## resolveInputs\n\nReturn inputs from parsed arguments\n\n```ts\n{\n  resolveInputs: (parsed: ParsedArgs) =>\n    parsed['flag'] ? [toDependency('package')] : [];\n}\n```\n\n## string\n\nMark arguments as string. This is the default, but number-looking arguments are\nreturned as numbers.\n\n[1]: https://github.com/webpro-nl/knip/blob/main/packages/knip/src/types/args.ts\n[2]: https://github.com/search?q=repo%3Awebpro-nl%2Fknip++path%3Apackages%2Fknip%2Fsrc%2Fplugins+%22const+args+%3D%22&type=code\n[3]: #alias\n[4]: #args\n[5]: #binaries\n[6]: #boolean\n[7]: #config\n[8]: #fromargs\n[9]: #nodeimportargs\n[10]: #positional\n[11]: #resolve\n[12]: #resolveinputs\n[13]: #string\n","frontmatter":{"title":"Argument Parsing","description":"Reference for a Knip plugin `arg` object to parse a tool's command-line arguments and find dependencies and entry files in scripts."},"isInternal":false,"tokens":1093,"sizeBytes":3976},{"name":"index.md","path":"packages/docs/src/content/docs/writing-a-plugin/index.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/writing-a-plugin/index.md","title":"Writing-a-plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Writing A Plugin\ndescription: Tutorial for writing a Knip plugin with entry, config, resolveConfig, resolveFromAST and resolve to find entry files and dependencies.\n---\n\nPlugins provide Knip with entry files and dependencies it would be unable to\nfind otherwise. Plugins always do at least one of the following:\n\n1. Define entry file patterns\n2. Find dependencies in configuration files\n\nKnip v5.1.0 introduced a new plugin API, which makes them a breeze to write and\nmaintain.\n\n:::tip[The new plugin API]\n\nEasy things should be easy, and complex things possible.\n\n:::\n\nThis tutorial walks through example plugins so you'll be ready to write your\nown! The following examples demonstrate the elements a plugin can implement.\n\nThere's a handy command available to easily [create a new plugin][1] and get\nstarted right away.\n\n## Example 1: entry\n\nLet's dive right in. Here's the entire source code of the Tailwind plugin:\n\n```ts\nimport type { IsPluginEnabled, Plugin } from '../../types/config.js';\nimport { hasDependency } from '../../util/plugin.js';\n\nconst title = 'Tailwind';\n\nconst enablers = ['tailwindcss'];\n\nconst isEnabled: IsPluginEnabled = ({ dependencies }) =>\n  hasDependency(dependencies, enablers);\n\nconst entry = ['tailwind.config.{js,cjs,mjs,ts}'];\n\nconst plugin: Plugin = {\n  title,\n  enablers,\n  isEnabled,\n  entry,\n};\n\nexport default plugin;\n```\n\nYes, that's the entire plugin! Let's go over each item one by one:\n\n### 1. `title`\n\nThe title of the plugin displayed in the [list of plugins][2] and in debug\noutput.\n\n### 2. `enablers`\n\nAn array of strings to match one or more dependencies in `package.json` so the\n`isEnabled` function can determine whether the plugin should be enabled or not.\nRegular expressions are allowed as well.\n\n### 3. `isEnabled`\n\nThis function checks whether a match is found in the `dependencies` or\n`devDependencies` in `package.json`. The plugin is enabled if the dependency is\nlisted in `package.json`.\n\nThis function can be kept straightforward with the `hasDependency` helper.\n\n### 4. `entry`\n\nThis plugin exports `entry` file patterns. This means that if the Tailwind\nplugin is enabled, then `tailwind.config.*` files are added as entry files. A\nTailwind configuration file does not contain anything particular, so adding it\nas an `entry` to treat it as a regular source file is enough.\n\nThe next example shows how to handle a tool that has its own particular\nconfiguration object.\n\n## Example 2: config\n\nHere's the full source code of the `nyc` plugin:\n\n```ts\nimport { toDeferResolve } from '../../util/input.js';\nimport { hasDependency } from '../../util/plugin.js';\nimport type { NycConfig } from './types.js';\nimport type {\n  IsPluginEnabled,\n  Plugin,\n  ResolveConfig,\n} from '../../types/config.js';\n\nconst title = 'nyc';\n\nconst enablers = ['nyc'];\n\nconst isEnabled: IsPluginEnabled = ({ dependencies }) =>\n  hasDependency(dependencies, enablers);\n\nconst config = [\n  '.nycrc',\n  '.nycrc.{json,yml,yaml}',\n  'nyc.config.js',\n  'package.json',\n];\n\nconst resolveConfig: ResolveConfig<NycConfig> = config => {\n  const extend = config?.extends ?? [];\n  const requires = config?.require ?? [];\n  return [extend, requires].flat().map(id => toDeferResolve(id));\n};\n\nconst plugin: Plugin = {\n  title,\n  enablers,\n  isEnabled,\n  config,\n  resolveConfig,\n};\n\nexport default plugin;\n```\n\nHere's an example `config` file that will be handled by this plugin:\n\n```json title=\".nycrc.json\"\n{\n  \"extends\": \"@istanbuljs/nyc-config-typescript\",\n  \"check-coverage\": true\n}\n```\n\nCompared to the first example, this plugin has two new variables:\n\n### 5. `config`\n\nThe `config` array contains all possible locations of the config file for the\ntool. Knip loads matching files and passes the results (i.e. its default export)\ninto the `resolveConfig` function:\n\n### 6. `resolveConfig`\n\nThis function receives the exported value of the `config` file, and executes the\n`resolveConfig` function with this object. The plugin should return the entry\npaths and dependencies referenced in this object.\n\nKnip supports JSON, YAML, TOML, JavaScript and TypeScript config files. Files\nwithout an extension are provided as plain text strings.\n\n:::tip[Should I implement resolveConfig?]\n\nYou should implement `resolveConfig` if any of these are true:\n\n- The `config` file contains one or more options that represent [entry\n  points][3]\n- The `config` file references dependencies by strings (not import statements)\n\n:::\n\n## Example 3: entry paths\n\n### 7. entry and production\n\nSome tools operate mostly on entry files, some examples:\n\n- Mocha looks for test files at `test/*.{js,cjs,mjs}`\n- Storybook looks for stories at `*.stories.@(mdx|js|jsx|tsx)`\n\nAnd some of those tools allow to configure those locations and patterns in\nconfiguration files, such as `next.config.js` or `vite.config.ts`. If that's the\ncase we can define `resolveConfig` in our plugin to take this from the\nconfiguration object and return it to Knip:\n\nHere's an example from the Mocha plugin:\n\n```ts\nconst entry = ['**/test/*.{js,cjs,mjs}'];\n\nconst resolveConfig: ResolveConfig<MochaConfig> = localConfig => {\n  const entryPatterns = localConfig.spec ? [localConfig.spec].flat() : entry;\n  return entryPatterns.map(id => toEntry(id));\n};\n\nexport default {\n  entry,\n  resolveConfig,\n};\n```\n\nWith Mocha, you can configure `spec` file patterns. The result of implementing\n`resolveConfig` is that users don't need to duplicate this configuration in both\nthe tool (e.g. Mocha) and Knip.\n\nUse `production` entries to target source files that represent production code.\n\n:::tip\n\nRegardless of the presence of `resolveConfig`, add `entry` and `production` to\nthe default export so they will be displayed in the plugin's documentation as\ndefault values.\n\n:::\n\n## Example 4: Use the AST directly\n\nIf the `resolveConfig` function is implemented, Knip loads the configuration\nfile and passes the default-exported object to this plugin function. However,\nthat object might then not contain the information we need.\n\nHere's an example `astro.config.ts` configuration file with a Starlight\nintegration:\n\n```ts\nimport starlight from '@astrojs/starlight';\nimport { defineConfig } from 'astro/config';\n\nexport default defineConfig({\n  integrations: [\n    starlight({\n      components: {\n        Head: './src/components/Head.astro',\n        Footer: './src/components/Footer.astro',\n      },\n    }),\n  ],\n});\n```\n\nWith Starlight, components can be defined to override the default internal ones.\nThey're not otherwise referenced in your source code, so you'd have to manually\nadd them as entry files ([Knip itself did this][4]).\n\nIn the Astro plugin, there's no way to access this object containing\n`components` to add the component files as entry files if we were to try:\n\n```ts\nconst resolveConfig: ResolveConfig<AstroConfig> = async config => {\n  console.log(config); //  ¯\\_(ツ)_/¯\n};\n```\n\nThis is why plugins can implement the `resolveFromAST` function.\n\n### 8. resolveFromAST\n\nLet's take a look at the Astro plugin implementation. This example assumes some\nfamiliarity with Abstract Syntax Trees (AST). Knip provides AST helpers to make\nimplementing plugins more fun and a little less tedious.\n\nAnyway, let's dive in. Here's how we're adding the Starlight `components` paths\nto the default `production` file patterns:\n\n```ts\nimport type { Program } from 'oxc-parser';\nimport {\n  findCallArg,\n  getDefaultImportName,\n  getImportMap,\n  getPropertyValues,\n} from '../../typescript/ast-helpers.ts';\n\nconst title = 'Astro';\n\nconst production = [\n  'src/pages/**/*.{astro,mdx,js,ts}',\n  'src/content/**/*.mdx',\n  'src/middleware.{js,ts}',\n  'src/actions/index.{js,ts}',\n];\n\nconst getComponentPaths = (program: Program) => {\n  const importMap = getImportMap(program);\n  const importName = getDefaultImportName(importMap, '@astrojs/starlight');\n  if (!importName) return new Set<string>();\n  const starlightConfig = findCallArg(program, importName);\n  return getPropertyValues(starlightConfig, 'components');\n};\n\nconst resolveFromAST: ResolveFromAST = (program: Program) => {\n  const componentPaths = getComponentPaths(program);\n  return [...production, ...componentPaths].map(id => toProductionEntry(id));\n};\n\nconst plugin: Plugin = {\n  title,\n  production,\n  resolveFromAST,\n};\n\nexport default plugin;\n```\n\n## None Of The Above\n\n### 9. `resolve`\n\nIf there is no configuration file to parse or there is a need for customization,\nuse `resolve`:\n\n```ts\nconst resolve: Resolve = async options => {\n  return toDependency('troublesome', { optional: true });\n};\n```\n\n## Inputs\n\nYou may have noticed functions like `toDeferResolve` and `toEntry`. They're a\nway for plugins to tell what they've found and how Knip should handle those. The\nmore precision a plugin can provide here, the better results and performance\nwill be.\n\nFind all the details over at [Writing A Plugin → Inputs][5].\n\n## Argument Parsing\n\nAs part of the [script parser][6], Knip parses command-line arguments. Plugins\ncan implement the `arg` object to add custom argument parsing tailored to the\ntool.\n\nRead more in [Writing A Plugin → Argument Parsing][7].\n\n## Create a new plugin\n\nThe easiest way to create a new plugin is to use the `create-plugin` script:\n\n```sh\ncd packages/knip\npnpm create-plugin --name tool\n```\n\nThis adds source and test files and fixtures to get you started. Keep fixtures\ntidy, remove clutter that isn't required to test the plugin properly. E.g. using\na starterkit, script or wizard often creates more than what we need here.\n\nThe script adds the plugin to the JSON Schema and type definitions.\n\nRun the test for your new plugin using one of the following commands:\n\n```sh\nnode --test test/plugins/tool.test.ts\nbun test test/plugins/tool.test.ts\n```\n\nYou're ready to implement and submit a new Knip plugin! 🆕 🎉\n\n## Wrapping Up\n\nFeel free to check out the implementation of other similar plugins, and borrow\nideas and code from those!\n\nThe documentation website takes care of generating the [plugin list and the\nindividual plugin pages][2] from the exported plugin values.\n\nThanks for reading. If you have been following this guide to create a new\nplugin, this might be the right time to open a pull request!\n\n[1]: #create-a-new-plugin\n[2]: ../reference/plugins.md\n[3]: ../explanations/plugins.md#entry-files-from-config-files\n[4]: https://github.com/webpro-nl/knip/blob/6a6954386b33ee8a2919005230a4bc094e11bc03/knip.json#L12\n[5]: ../writing-a-plugin/inputs.md\n[6]: ../features/script-parser.md\n[7]: ../writing-a-plugin/argument-parsing.md\n","frontmatter":{"title":"Writing A Plugin","description":"Tutorial for writing a Knip plugin with entry, config, resolveConfig, resolveFromAST and resolve to find entry files and dependencies."},"isInternal":false,"tokens":2524,"sizeBytes":10522},{"name":"inputs.md","path":"packages/docs/src/content/docs/writing-a-plugin/inputs.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/src/content/docs/writing-a-plugin/inputs.md","title":"Writing-a-plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Inputs\ndescription: Reference for Knip plugin input functions like toEntry, toDependency, toDeferResolve, toConfig, toBinary and toAlias, plus their options.\n---\n\nYou may have noticed functions like `toDeferResolve` and `toEntry`. They're a\nway for plugins to tell what they've found and how Knip should handle those. The\nmore precise a plugin can be, the better it is for results and performance.\nHere's an overview of all input type functions:\n\n- [toEntry][1]\n- [toProductionEntry][2]\n- [toProject][3]\n- [toDependency][4]\n- [toProductionDependency][5]\n- [toDeferResolve][6]\n- [toDeferResolveEntry][7]\n- [toConfig][8]\n- [toBinary][9]\n- [toAlias][10]\n- [Options][11]\n\n## toEntry\n\nAn `entry` input is just like an `entry` in the configuration. It should either\nbe an absolute or relative path, and glob patterns are allowed.\n\n## toProductionEntry\n\nA production `entry` input is just like an `production` in the configuration. It\nshould either be an absolute or relative path, and it can have glob patterns.\n\n## toProject\n\nA `project` input is the equivalent of `project` patterns in the configuration.\nIt should either be an absolute or relative path, and (negated) glob patterns\nare allowed.\n\n## toDependency\n\nThe `dependency` indicates the entry is a dependency, belonging in either the\n`\"dependencies\"` or `\"devDependencies\"` section of `package.json`. Use it for\npackage names referenced from configuration, such as a plugin or transformer a\ntool loads at build time.\n\nKnip marks the package as referenced, and reports it as an unlisted dependency\nif it isn't listed at all. Such a reference is development-only: in [production\nmode][12] the package is still marked as referenced, but an unlisted one is no\nlonger reported.\n\n## toProductionDependency\n\nThe production `dependency` indicates the entry is a production dependency,\nexpected to be listed in `\"dependencies\"`. Unlike [toDependency][4] it's also\nreported as unlisted in production mode.\n\n## toDeferResolve\n\nThe `deferResolve` input type is used to defer the resolution of a specifier.\nThis could be resolved to a dependency or an entry file. For instance, the\nspecifier `\"input\"` could be resolved to `\"input.js\"`, `\"input.tsx\"`,\n`\"input/index.js\"` or the `\"input\"` package name. Local files are added as entry\nfiles, package names are external dependencies.\n\nIf this does not lead to a resolution, the specifier will be reported under\n\"unresolved imports\".\n\n## toDeferResolveEntry\n\nThe `deferResolveEntry` input type is similar to `deferResolve`, but it's used\nfor entry files only (not dependencies) and unresolved inputs are ignored. It's\ndifferent from `toEntry` as glob patterns are not supported.\n\n## toConfig\n\nThe `config` input type is a way for plugins to reference a configuration file\nthat should be handled by a different plugin. The specifier is a path to that\nfile.\n\nFor instance, `angular.json` has `tsConfig` and `karmaConfig` options pointing\nto files the TypeScript and Karma plugins know how to handle, so the Angular\nplugin hands them over:\n\n```ts\ntoConfig('typescript', 'tsconfig.app.json');\ntoConfig('karma', 'karma.conf.js');\n```\n\n## toBinary\n\nThe `binary` input type isn't used by plugins directly, but by the shell script\nparser (through the `getInputsFromScripts` helper). Think of GitHub Actions\nworkflow YAML files or husky scripts. Using this input type, a binary is\n\"assigned\" to the dependency that has it as a `\"bin\"` in their `package.json`.\n\n## toAlias\n\nThe `alias` input type adds path aliases to the core module resolver. They're\nadded to `compilerOptions.paths` so the syntax is identical.\n\n## Options\n\nWhen creating inputs from specifiers, an extra `options` object as the second\nargument can be provided.\n\n### dir\n\nThe optional `dir` option assigns the input to a different workspace. For\ninstance, GitHub Action workflows are always stored in the root workspace, and\nsupport `working-directory` in job steps. For example:\n\n```yaml\njobs:\n  stylelint:\n    runs-on: ubuntu-latest\n    steps:\n      - run: npx esbuild\n        working-directory: packages/app\n```\n\nThe GitHub Action plugin understands `working-directory` and adds this `dir` to\nthe input:\n\n```ts\ntoDependency('esbuild', { dir: 'packages/app' });\n```\n\nKnip now understands `esbuild` is a dependency of the workspace in the\n`packages/app` directory.\n\n### optional\n\nUse the `optional` flag to indicate the dependency is optional. Then, a\ndependency won't be flagged as unlisted if it isn't.\n\n### isTypeOnly\n\nUse `isTypeOnly` when only the types of a package are used, such as the packages\nlisted in `compilerOptions.types`. A `@types/pkg` dependency then satisfies the\nreference on its own, without `pkg` itself being installed. Don't use it for\npackages the tool actually loads, even if it does so only at build time.\n\n### allowIncludeExports\n\nBy default, exports of entry files such as `src/index.ts` or the files in\n`package.json#exports` are not reported as unused. When using the\n`--include-entry-exports` flag or `isIncludeExports: true` option, unused\nexports on such entry files are also reported.\n\nExports of entry files coming from plugins are not included in the analysis,\neven with the option enabled. This is because certain tools and frameworks\nconsume named exports from entry files, causing false positives.\n\nThe `allowIncludeExports` option allows the exports of entry files to be\nreported as unused when using `--include-entry-exports`. This option is\ntypically used with the [toProductionEntry][2] input type.\n\nExample:\n\n```ts\ntoProductionEntry('./entry.ts', { allowIncludeExports: true });\n```\n\n[1]: #toentry\n[2]: #toproductionentry\n[3]: #toproject\n[4]: #todependency\n[5]: #toproductiondependency\n[6]: #todeferresolve\n[7]: #todeferresolveentry\n[8]: #toconfig\n[9]: #tobinary\n[10]: #toalias\n[11]: #options\n[12]: ../features/production-mode.md\n","frontmatter":{"title":"Inputs","description":"Reference for Knip plugin input functions like toEntry, toDependency, toDeferResolve, toConfig, toBinary and toAlias, plus their options."},"isInternal":false,"tokens":1416,"sizeBytes":5832},{"name":"tsconfig.json","path":"packages/docs/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/tsconfig.json","title":"Docs Skill","category":"anthropic-skill","format":"json","content":"{\n  \"extends\": \"astro/tsconfigs/strict\"\n}\n","frontmatter":{"extends":"astro/tsconfigs/strict"},"isInternal":false,"tokens":13,"sizeBytes":42},{"name":"README.md","path":"packages/create-config/README.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/create-config/README.md","title":"create-config Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fcreate-config%2FREADME.md -->","isInternal":false,"tokens":116,"sizeBytes":354},{"name":"README.md","path":"packages/docs/README.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/docs/README.md","title":"docs Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fdocs%2FREADME.md -->","isInternal":false,"tokens":24,"sizeBytes":64},{"name":"README.md","path":"packages/knip/README.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/knip/README.md","title":"knip Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fknip%2FREADME.md -->","isInternal":false,"tokens":876,"sizeBytes":2873},{"name":"README.md","path":"packages/language-server/README.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/language-server/README.md","title":"language-server Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Flanguage-server%2FREADME.md -->","isInternal":false,"tokens":1189,"sizeBytes":4707},{"name":"README.md","path":"packages/mcp-server/README.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/mcp-server/README.md","title":"mcp-server Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fmcp-server%2FREADME.md -->","isInternal":false,"tokens":391,"sizeBytes":1289},{"name":"README.md","path":"packages/vscode-knip/README.md","rawUrl":"https://raw.githubusercontent.com/webpro-nl/knip/HEAD/packages/vscode-knip/README.md","title":"vscode-knip Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/webpro-nl/knip?path=packages%2Fvscode-knip%2FREADME.md -->","isInternal":false,"tokens":916,"sizeBytes":3461}],"systemPromptSnippet":"<yakaai_skills repo=\"webpro-nl/knip\">\n<!-- File: AGENTS.md (Tokens: ~1330 | Category: root-instruction) -->\n# Knip\n\nKnip is a tool to find and fix unused dependencies, exports and files in\nJavaScript and TypeScript projects.\n\n## Project overview\n\n- Monorepo, managed with pnpm\n- Main package is core in `packages/knip` (TypeScript)\n- Language Server in `packages/language-server` (JS + JSDoc for types)\n- VS Code Extension in `packages/vscode-knip` (JS + JSDoc for types)\n- [Documentation][1] content in `packages/docs` (Astro + MD/MDX)\n- Tracked `.agents` guides live in the checkout; there might be shared lessons and tasks in the workspace's `.agents`.\n\n## Code style\n\n- Performance is key, both high level (design) and low level (impl).\n- Avoid redundant code and abstractions; avoid unnecessary complexity and nesting.\n- Concise one-liners are fine, but prioritize clarity over cleverness.\n- Don't add comments to code, unless explicitly asked for.\n- Prefer AST-based tools and codemods (jscodeshift) over manual or regex-based refactors — except for tiny edits.\n- JavaScript\n  - Prefer plain `for..in/of` loops over iterator methods like `map`/`reduce`.\n- TypeScript\n  - Avoid `any` and type casting (`as`).\n  - Avoid runtime overhead just to get the types right.\n- Lint and check formatting from root: `pnpm run ci`; format with `pnpm fmt`\n- Format Markdown/MDX with `pnpm remark` in `packages/docs` (auto-numbers link refs, validates links)\n\n## Domain Knowledge\n\n- Unused file → unused exports/dependencies is a chain, not a bug\n- Non-JS/TS files (.css, .mdx, .vue) enter the graph via (usually plugin-registered) compilers (`registerCompilers`)\n- Library-specific AST patterns are caught by plugin-registered visitors (`registerVisitors`)\n- Use `--performance` or `--performance-fn [name]` to profile (→ [timerify][2])\n- If creating, modifying, or reviewing a plugin, read [PLUGINS.md][3] first.\n- If modifying core module graph, AST traversal, or CLI sequence, read [MODULE-GRAPH.md][4] first.\n- For issues re. exported identifiers (following refs, shadowing, `ignoreExportsUsedInFile`), see [EXPORTS.md][5].\n- Before any significant performance tuning, consult [PERFORMANCE.md][6].\n- When modifying or reviewing built-in compilers, read [COMPILERS.md][10].\n- For test/fixture structure, conventions, and where a new test goes, see [TESTS.md][7].\n\n## Issues and Pull Requests\n\n- Use `gh` for PR metadata, diffs, comments, and checks. Reuse retrieved evidence; browse upstream documentation separately.\n- When given a bug report, first confirm the behavior is actually wrong. Reproduce, then check if the reported behavior is correct-by-design before writing any fix.\n- Find repositories/CodeSandbox/StackBlitz source files and local fixtures to actually reproduce the issue at hand.\n- To fetch a stackblitz.com reproduction: `pnpx stackblitz-zip https://stackblitz.com/edit/{name} {filename}.zip`\n- For a fix, revert the source change and confirm the new test fails for the reported reason.\n- For a new plugin or a change in how a tool finds files, verify against the tool's source, not only its docs, and run Knip on the tool's examples or starters when available.\n- Follow the [AI contribution policy][11]: before opening an issue or PR, make sure the person you work for understands and stands behind it. Keep descriptions concise.\n\n## Run & Debug\n\nImportant: debug, don't guess.\n\nRun the CLI directly using `node` or `bun`. This document shows `knip` in\ncommands for consistency. Replace it with `node (path/to/)src/cli.ts` or\n`bun (path/to/)src/cli.ts` and keep using what works.\n\n- Run `knip` directly in a fixture or temp directory (over creating test scripts that import the `main` function).\n- Knip requires `package.json` in root dir.\n- Enable [debug & helpers][8] with `--debug` (not `DEBUG=`). Warning: noisy.\n- Use [trace][9] to debug\n  - exported identifiers (`knip --trace-export [name] --trace-file [file]`)\n  - external dependencies (`knip --trace-dependency [name] --workspace [dir]`)\n\n## Test\n\nPrefer TDD: add or update tests (and fixtures) before implementing.\n\nPrefer `bun` over `node` for speed. Don't run all tests at once (slow & noisy).\nStart out with running the relevant test(s) first:\n\n```sh\ncd packages/knip\nbun test test/util/get-inputs-from-scripts.test.ts\nnode --test test/commonjs.test.ts\n```\n\nRun smoke tests with Bun:\n\n```sh\ncd packages/knip\npnpm test --runtime bun --smoke\n```\n\nRun smoke tests with Node.js:\n\n```sh\ncd packages/knip\nnode --test test/commonjs.test.ts\npnpm test --runtime node --smoke\n```\n\nBuild core package and run all tests only if there are changes in auto-fix,\nformatting and reporter related functionality:\n\n```sh\ncd packages/knip\npnpm build\npnpm test\n```\n\nSee [TESTS.md][7] for test and fixture conventions and placements.\n\n## Build\n\nTo type-check `knip` with `tsc`:\n\n```sh\ncd packages/knip\npnpm build\n```\n\n[1]: https://knip.dev\n[2]: ./packages/knip/src/util/Performance.ts\n[3]: ./.agents/PLUGINS.md\n[4]: ./.agents/MODULE-GRAPH.md\n[5]: ./.agents/EXPORTS.md\n[6]: ./.agents/PERFORMANCE.md\n[7]: ./.agents/TESTS.md\n[8]: ./packages/knip/src/util/debug.ts\n[9]: ./packages/docs/src/content/docs/guides/troubleshooting.md#trace\n[10]: ./.agents/COMPILERS.md\n[11]: ./AI_POLICY.md\n\n<!-- File: CLAUDE.md (Tokens: ~3 | Category: claude-rule) -->\nAGENTS.md\n\n<!-- File: .github/copilot-instructions.md (Tokens: ~16 | Category: copilot-instructions) -->\nSee [AGENTS.md][1].\n\n[1]: ../AGENTS.md\n\n<!-- File: packages/docs/mock/contributors.json (Tokens: ~291 | Category: anthropic-skill) -->\n[\n  {\n    \"login\": \"webpro\",\n    \"id\": 456426,\n    \"node_id\": \"MDQ6VXNlcjQ1NjQyNg==\",\n    \"avatar_url\": \"https://avatars.githubusercontent.com/u/456426?v=4\",\n    \"gravatar_id\": \"\",\n    \"url\": \"https://api.github.com/users/webpro\",\n    \"html_url\": \"https://github.com/webpro\",\n    \"followers_url\": \"https://api.github.com/users/webpro/followers\",\n    \"following_url\": \"https://api.github.com/users/webpro/following{/other_user}\",\n    \"gists_url\": \"https://api.github.com/users/webpro/gists{/gist_id}\",\n    \"starred_url\": \"https://api.github.com/users/webpro/starred{/owner}{/repo}\",\n    \"subscriptions_url\": \"https://api.github.com/users/webpro/subscriptions\",\n    \"organizations_url\": \"https://api.github.com/users/webpro/orgs\",\n    \"repos_url\": \"https://api.github.com/users/webpro/repos\",\n    \"events_url\": \"https://api.github.com/users/webpro/events{/privacy}\",\n    \"received_events_url\": \"https://api.github.com/users/webpro/received_events\",\n    \"type\": \"User\",\n    \"site_admin\": false,\n    \"contributions\": 1282\n  }\n]\n\n<!-- File: packages/docs/package.json (Tokens: ~454 | Category: anthropic-skill) -->\n{\n  \"name\": \"@knip/docs\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"description\": \"Documentation for Knip, hosted at knip.dev\",\n  \"homepage\": \"https://knip.dev\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"github:webpro-nl/knip\",\n    \"directory\": \"packages/docs\"\n  },\n  \"type\": \"module\",\n  \"scripts\": {\n    \"prebuild\": \"node ./scripts/generate-plugin-docs.ts\",\n    \"build\": \"astro check && astro build\",\n    \"postbuild\": \"[ \\\"$CF_PAGES\\\" = \\\"1\\\" ] && find dist -mindepth 2 -type f -name 'index.html' -exec bash -c 'f=\\\"$1\\\"; d=$(dirname \\\"$f\\\"); bn=$(basename \\\"$d\\\"); mv -v \\\"$f\\\" \\\"$d/../$bn.html\\\"' _ {} \\\\; && find dist -mindepth 1 -type d -empty -print -delete || true\",\n    \"dev\": \"astro dev\",\n    \"remark\": \"remark README.md 'src/content/docs/**/*.md' --verbose -o && mdxlint 'src/content/docs/**/*.mdx' --verbose -o\"\n  },\n  \"dependencies\": {\n    \"@astro-community/astro-embed-youtube\": \"0.5.10\",\n    \"@astrojs/starlight\": \"0.42.6\",\n    \"@octokit/graphql\": \"^9.0.5\",\n    \"astro\": \"7.3.8\",\n    \"sharp\": \"0.35.5\"\n  },\n  \"devDependencies\": {\n    \"@astrojs/check\": \"0.9.10\",\n    \"@astrojs/markdown-satteri\": \"0.4.3\",\n    \"picocolors\": \"^1.1.1\",\n    \"satteri\": \"0.10.5\",\n    \"starlight-blog\": \"^0.30.2\",\n    \"typescript\": \"6.0.3\"\n  },\n  \"engines\": {\n    \"node\": \">=22.12.0\"\n  }\n}\n\n<!-- File: packages/docs/public/manifest.json (Tokens: ~170 | Category: anthropic-skill) -->\n{\n  \"name\": \"Knip\",\n  \"short_name\": \"Knip\",\n  \"icons\": [\n    {\n      \"src\": \"/favicon.svg\",\n      \"type\": \"image/svg+xml\",\n      \"sizes\": \"512x512\"\n    },\n    {\n      \"src\": \"/icon-192x192.png\",\n      \"sizes\": \"192x192\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icon-512x512.png\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/png\"\n    }\n  ],\n  \"theme_color\": \"#fbfbfb\",\n  \"background_color\": \"#f56e0f\",\n  \"display\": \"standalone\",\n  \"scope\": \"/\",\n  \"start_url\": \"/overview/getting-started/\"\n}\n\n<!-- File: packages/docs/src/assets/testimonials.json (Tokens: ~11389 | Category: anthropic-skill) -->\n{\n  \"data\": [\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"2061954856638967917\",\n      \"author_id\": \"5\",\n      \"created_at\": \"2026-06-02T23:35:21.000Z\",\n      \"text\": \"Knip is still my all time favorite piece of software.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"2061775207518343569\",\n      \"author_id\": \"20\",\n      \"created_at\": \"2026-06-02T11:41:30.000Z\",\n      \"text\": \"adding knip to our CI after deleting like 100k LOC of dead code was a game changer\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3mn5ccucpvk2z\",\n      \"author_id\": \"13\",\n      \"created_at\": \"2026-05-31T09:54:50.000Z\",\n      \"text\": \"Knip is essential tooling.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"2059921462891622770\",\n      \"author_id\": \"21\",\n      \"created_at\": \"2026-05-28T08:55:22.000Z\",\n      \"text\": \"Please dont ask your ai agent to find unused, dead code and remove them. Instead for js/ts projects install knip and see the magic it does. Save tokens🙏😂\"\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webpro.nl\"\n          }\n        ],\n        \"urls\": []\n      },\n      \"id\": \"3mgkwe4digs2l\",\n      \"author_id\": \"19\",\n      \"created_at\": \"2026-03-25T12:00:00.000Z\",\n      \"text\": \"Two things about knip.dev I don't get:\\n- how did we live without it for so long\\n- how did @webpro.nl NAIL the timing? Gave it to us right when AI started to produce left-overs in our codes faster than we ever could.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"cdn.bsky.app/img/dummy-02\",\n            \"display_url\": \"cdn.bsky.app/img/julien.deniau.me\",\n            \"media_key\": \"4\"\n          }\n        ]\n      },\n      \"id\": \"3mdrubg3y5c2z\",\n      \"author_id\": \"11\",\n      \"created_at\": \"2026-02-01T07:57:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Done on a mono-repo in two times.\\nWhat's impressive is that there were no false positive!\\ncdn.bsky.app/img/dummy-02\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/EwIeRiHaXf\",\n            \"display_url\": \"pic.x.com/EwIeRiHaXf\",\n            \"media_key\": \"6\"\n          }\n        ]\n      },\n      \"id\": \"2017122504914161979\",\n      \"author_id\": \"16\",\n      \"created_at\": \"2026-01-30T06:27:00.000Z\",\n      \"text\": \"Good morning 🌄\\nA tool I discovered lately.\\nIf you care about clean codebases, this one's a gem 💎\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3mcky5ps3r22p\",\n      \"author_id\": \"12\",\n      \"created_at\": \"2026-01-16T20:53:09.000Z\",\n      \"text\": \"Knip is a cracking-looking open source tool for trimming unused JavaScript.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"cdn.bsky.app/img/dummy-03\",\n            \"display_url\": \"cdn.bsky.app/img/patak.dev\",\n            \"media_key\": \"5\"\n          }\n        ]\n      },\n      \"id\": \"3mcjtmv35wc2y\",\n      \"author_id\": \"15\",\n      \"created_at\": \"2026-01-16T09:59:29.000Z\",\n      \"attachments\": {},\n      \"text\": \"From the report, we could improve the situation if we stop sending unused JavaScript. @webpro.nl is doing an incredible job growing the usage of knip.dev, and that should hopefully make a dent in the future.\\ncdn.bsky.app/img/dummy-03\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://knip.dev/blog/for-editors-and-agents\",\n            \"expanded_url\": \"https://knip.dev/blog/for-editors-and-agents\",\n            \"display_url\": \"knip.dev/blog/for-edi...\"\n          }\n        ]\n      },\n      \"id\": \"3mby3zkzhfs2t\",\n      \"author_id\": \"13\",\n      \"created_at\": \"2026-01-09T08:41:49.000Z\",\n      \"text\": \"The VSCode/Cursor extension is ace!\\nAnd you can use the Knip MCP to create the config file.\\nIt works for Svelte as well.\\nKnip is really really good 🙏\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/6rcslWBqIV\",\n            \"display_url\": \"pic.x.com/6rcslWBqIV\",\n            \"media_key\": \"6\"\n          }\n        ]\n      },\n      \"id\": \"2007481125610914217\",\n      \"author_id\": \"17\",\n      \"created_at\": \"2026-01-03T15:56:00.000Z\",\n      \"attachments\": { \"media_keys\": [\"6\"] },\n      \"text\": \"This is both embarrassing and satisfying after running @Knip https://t.co/6rcslWBqIV\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/hneEWMqdnm\",\n            \"expanded_url\": \"https://knip.dev\",\n            \"display_url\": \"Knip.dev\"\n          }\n        ]\n      },\n      \"id\": \"2007221517562904675\",\n      \"author_id\": \"18\",\n      \"created_at\": \"2026-01-02T23:44:00.000Z\",\n      \"text\": \"You can't spell Opus without https://t.co/hneEWMqdnm\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3mbggqrihuk2r\",\n      \"author_id\": \"14\",\n      \"created_at\": \"2026-01-02T08:05:50.000Z\",\n      \"text\": \"Knip is amazing and you should be using it.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3lvwax6bemc22\",\n      \"author_id\": \"22\",\n      \"created_at\": \"2025-08-08T22:02:18.000Z\",\n      \"text\": \"Just used `npx knip` to find my unused files, components, and packages and 😱! So cool. \\n\\nHow have I not come across it before?\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1932778410691949034\",\n      \"author_id\": \"10\",\n      \"created_at\": \"2025-06-11T14:34:00.000Z\",\n      \"text\": \"\\\"Thanks Knip!\\\"\\neveryday,\\nevery team member,\\nliterally..\\nknip.dev 🏅\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"url\": \"https://github.com/webpro-nl/knip/issues/1120#issuecomment-2943978262\",\n      \"author_id\": \"9\",\n      \"created_at\": \"2025-06-05T14:00:00.000Z\",\n      \"text\": \"Thank you so much for this incredible piece of software! Knip is one of the most impressive tools I've seen in my career.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://github.com/webpro-nl/knip/pull/1022\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip/pull/1022\",\n            \"display_url\": \"https://github.com/webpro-nl/knip/pull/1022\",\n            \"title\": \"feat: add create-typescript-app plugin\",\n            \"description\": \"feat: add create-typescript-app plugin\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip/pull/1022\"\n          }\n        ]\n      },\n      \"id\": \"3lmhgsj2n622o\",\n      \"author_id\": \"7\",\n      \"created_at\": \"2025-04-10T13:50:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Got my first plugin merged into Knip by @webpro.nl today! ☺️\\n\\nThe contribution experience was fantastic: the docs were super clear, the code was straightforward to navigate, and the helper script to generate a new plugin got me 90% of the way there. Awesome. Thanks Lars!\\n\\nhttps://github.com/webpro-nl/knip/pull/1022\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1904580358307250634\",\n      \"author_id\": \"6\",\n      \"created_at\": \"2025-03-25T18:05:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"All of the TanStack monorepos make use of knip.dev\\n\\nIt's like eslint for detecting unused dependencies or even your own files/modules.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"cdn.bsky.app/img/dummy-01\",\n            \"display_url\": \"cdn.bsky.app/img/opw3iapscc55nlgrx6q2yjah\",\n            \"media_key\": \"2\"\n          }\n        ]\n      },\n      \"id\": \"3ll5ioywml223\",\n      \"author_id\": \"8\",\n      \"created_at\": \"2025-03-24T20:32:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"The joy of adding knip.dev (by @webpro.nl) on a codebase! Right in time for spring cleaning 🧹🍃\\ncdn.bsky.app/img/dummy-01\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1874692207472726401\",\n      \"author_id\": \"5\",\n      \"created_at\": \"2025-01-02T06:40:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Knip helped us delete ~300k lines of unused code at Vercel.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/kA81p5gkmP\",\n            \"expanded_url\": \"https://www.npmx.dev/package/knip\",\n            \"display_url\": \"npmx.dev/package/knip\",\n            \"title\": \"Knip\",\n            \"description\": \"Find unused dependencies, exports and files in your TypeScript and JavaScript projects.\",\n            \"unwound_url\": \"https://www.npmx.dev/package/knip\"\n          }\n        ]\n      },\n      \"id\": \"1850975288362221628\",\n      \"author_id\": \"5\",\n      \"created_at\": \"2024-10-28T19:57:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Knip may be the greatest tool ever conceived.\\nhttps://t.co/kA81p5gkmP\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"3k3obqi65oy2p\",\n      \"author_id\": \"4\",\n      \"created_at\": \"2023-07-29T17:33:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"`knip` is the best code maintenance tool I've used in my 20 years of development, just an absolute work of art\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1808672067900092505\",\n      \"author_id\": \"3\",\n      \"created_at\": \"2024-07-04T03:19:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"knip is great.\\n\\nA great example of stuff just working. It detects your environment so well and its defaults are almost too good because I didn’t realise it was doing everything automatically.\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1808808208229707835\",\n      \"author_id\": \"3\",\n      \"created_at\": \"2024-07-04T12:20:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Then was like “this is how tooling should be, this has taken me an hour not a day and it’s faster and more accurate and more future proof”\\n\\nFive stars ⭐️⭐️⭐️⭐️⭐️\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1803013555907698921\",\n      \"author_id\": \"2\",\n      \"created_at\": \"2024-06-18T12:35:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Crazy useful tool. Thought it would be a nightmare to setup in my Next.js+Workers repo but it has crazy good automatic detection for code dependencies. In short, Knip creates a graph of code use and highlights dead code for you to snip (knip).\"\n    },\n    {\n      \"entities\": {\n        \"urls\": []\n      },\n      \"id\": \"1793913676896031033\",\n      \"author_id\": \"44217212\",\n      \"created_at\": \"2024-05-24T09:55:00.000Z\",\n      \"attachments\": {},\n      \"text\": \"Lars is singlehandedly building the best tool to keep your code clean and your dependencies minimal. And he's so engaging and helpful. Can't imagine going back to not using knip 👏\"\n    },\n    {\n      \"entities\": {\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/dummy-01\",\n            \"display_url\": \"pic.twitter.com/uOuO1ch5ij\",\n            \"media_key\": \"1\"\n          }\n        ]\n      },\n      \"id\": \"1745972825490604506\",\n      \"author_id\": \"1\",\n      \"created_at\": \"2024-01-13T01:55:00.000Z\",\n      \"attachments\": { \"media_keys\": [\"1\"] },\n      \"text\": \"warning: do not use a tool like knip.dev + code search to delete a ton of unused code. It works too well.\\n\\nI just did this in https://github.com/sourcegraph/cody/pull/2705, and my boss said if I end the week with net negative lines of code committed, I'm in deep trouble. https://t.co/dummy-01\"\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"argos_ci\",\n            \"id\": \"1554000987022663681\"\n          },\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"annotations\": [\n          {\n            \"probability\": 0.6699,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Prettier\"\n          },\n          {\n            \"probability\": 0.7586,\n            \"type\": \"Other\",\n            \"normalized_text\": \"ESLint\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/uOuO1ch5ij\",\n            \"expanded_url\": \"https://twitter.com/gregberge_/status/1730180003453927560/photo/1\",\n            \"display_url\": \"pic.twitter.com/uOuO1ch5ij\",\n            \"media_key\": \"3_1730179997682552832\"\n          }\n        ]\n      },\n      \"author_id\": \"22918124\",\n      \"text\": \"Ran knip.dev in @argos_ci, and boom 💥! Dead code detected instantly. With a good config, it can run on CI to keep projects clean. Installing this tool should be a no-brainer, like Prettier or ESLint.\\n\\nKudos, @webprolific! 👏 https://t.co/uOuO1ch5ij\",\n\n      \"id\": \"1730180003453927560\",\n      \"created_at\": \"2023-11-30T11:00:32.000Z\",\n      \"edit_history_tweet_ids\": [\"1730180003453927560\"],\n      \"attachments\": { \"media_keys\": [\"3_1730179997682552832\"] }\n    },\n    {\n      \"note_tweet\": {\n        \"text\": \"Problem: \\n🚫 Your project has unused files.\\n🚫 It has unused npm dependencies.\\n🚫 It has unused TypeScript exports.\\n\\nBut you haven't noticed, because these things are hard to spot.\\n\\nSolution: knip\\n\\nI just used knip to find and resolve dozens of issues.\\n\\nhttps://t.co/QmN3sNlmbm\",\n        \"entities\": {\n          \"urls\": [\n            {\n              \"url\": \"https://t.co/QmN3sNlmbm\",\n              \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n              \"display_url\": \"github.com/webpro-nl/knip\"\n            }\n          ]\n        }\n      },\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.8569,\n            \"type\": \"Other\",\n            \"normalized_text\": \"TypeScript\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/grbeTqMtt6\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n            \"display_url\": \"github.com/webpro-nl/knip\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig\",\n                \"width\": 1280,\n                \"height\": 640\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!\",\n            \"description\": \"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip\"\n          },\n          {\n            \"url\": \"https://t.co/qaOXBlD3eo\",\n            \"expanded_url\": \"https://twitter.com/i/web/status/1691460974518353920\",\n            \"display_url\": \"twitter.com/i/web/status/1…\"\n          }\n        ]\n      },\n      \"author_id\": \"19268321\",\n      \"text\": \"Problem: \\n🚫 Your project has unused files.\\n🚫 It has unused npm dependencies.\\n🚫 It has unused TypeScript exports.\\n\\nBut you haven't noticed, because these things are hard to spot.\\n\\nSolution: knip\\n\\nI just used knip to find and resolve dozens of issues.\\n\\nhttps://t.co/grbeTqMtt6 https://t.co/qaOXBlD3eo\",\n\n      \"id\": \"1691460974518353920\",\n      \"created_at\": \"2023-08-15T14:44:56.000Z\",\n      \"edit_history_tweet_ids\": [\"1691460974518353920\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"annotations\": [\n          {\n            \"probability\": 0.6322,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ]\n      },\n      \"author_id\": \"3126044440\",\n      \"text\": \"@webprolific Knip helped me get rid of over 41k lines of code in legacy codebase 🥺🥺💕\",\n\n      \"id\": \"1729181106715632088\",\n      \"created_at\": \"2023-11-27T16:51:17.000Z\",\n      \"edit_history_tweet_ids\": [\"1729181106715632088\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"contra\",\n            \"id\": \"973313523790082053\"\n          }\n        ],\n        \"annotations\": [\n          {\n            \"probability\": 0.8474,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/UgCunYQWzu\",\n            \"expanded_url\": \"https://twitter.com/webprolific/status/1729105865683435542\",\n            \"display_url\": \"twitter.com/webprolific/st…\"\n          }\n        ]\n      },\n      \"author_id\": \"95668959\",\n      \"text\": \"Big fans of Knip at @Contra. Such an extremely well developed and maintained project https://t.co/UgCunYQWzu\",\n\n      \"id\": \"1729157761215369264\",\n      \"created_at\": \"2023-11-27T15:18:31.000Z\",\n      \"edit_history_tweet_ids\": [\"1729157761215369264\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/ZUYYdvkBJc\",\n            \"expanded_url\": \"https://github.com/getsentry/sentry/\",\n            \"display_url\": \"github.com/getsentry/sent…\",\n            \"title\": \"GitHub - getsentry/sentry: Developer-first error tracking and performance monitoring\",\n            \"description\": \"Developer-first error tracking and performance monitoring - GitHub - getsentry/sentry: Developer-first error tracking and performance monitoring\",\n            \"unwound_url\": \"https://github.com/getsentry/sentry/\"\n          }\n        ]\n      },\n      \"author_id\": \"1632752318994153472\",\n      \"text\": \"@webprolific Just tried this on https://t.co/ZUYYdvkBJc - got some super useful results! Nice work.\",\n\n      \"id\": \"1727040036334424406\",\n      \"created_at\": \"2023-11-21T19:03:26.000Z\",\n      \"edit_history_tweet_ids\": [\"1727040036334424406\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          { \"username\": \"TkDodo\", \"id\": \"44217212\" },\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          },\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ]\n      },\n      \"author_id\": \"1513218780167655427\",\n      \"text\": \"@TkDodo @webprolific I've manage to delete 6k LOC in the last 30 minutes 🫣\\n\\nGreat job here @webprolific 👍🏽\",\n\n      \"id\": \"1726807293583609935\",\n      \"created_at\": \"2023-11-21T03:38:35.000Z\",\n      \"edit_history_tweet_ids\": [\"1726807293583609935\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"webprolific\",\n            \"id\": \"218833730\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/Tg5E6C7gqa\",\n            \"expanded_url\": \"https://twitter.com/housecor/status/1713975785273303286\",\n            \"display_url\": \"twitter.com/housecor/statu…\"\n          }\n        ]\n      },\n      \"author_id\": \"44217212\",\n      \"text\": \"knip is an amazing tool. Shoutout to @webprolific for building it 🙌.\\n\\nNot cleaning up correctly has a real maintenance cost. I've deleted lots of dead code - functions that were only used in tests and components that were only used in stories - all thanks to knip 🚀. https://t.co/Tg5E6C7gqa\",\n\n      \"id\": \"1714023231689031941\",\n      \"created_at\": \"2023-10-16T20:59:18.000Z\",\n      \"edit_history_tweet_ids\": [\"1714023231689031941\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9562,\n            \"type\": \"Other\",\n            \"normalized_text\": \"JavaScript\"\n          },\n          {\n            \"probability\": 0.8666,\n            \"type\": \"Other\",\n            \"normalized_text\": \"TypeScript\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/f3fzC5UPtR\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n            \"display_url\": \"github.com/webpro-nl/knip\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig\",\n                \"width\": 1280,\n                \"height\": 640\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!\",\n            \"description\": \"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip\"\n          }\n        ]\n      },\n      \"author_id\": \"481186762\",\n      \"text\": \"🛠️ Knip\\n\\n👉🏻 Knip finds unused dependencies, exports and files in your JavaScript and TypeScript projects.\\n👉🏻 Less code and dependencies lead to improved performance, less maintenance and easier refactorings. \\n\\nhttps://t.co/f3fzC5UPtR\",\n      \"id\": \"1696221274039595363\",\n      \"created_at\": \"2023-08-28T18:00:40.000Z\",\n      \"edit_history_tweet_ids\": [\"1696221274039595363\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9354,\n            \"type\": \"Other\",\n            \"normalized_text\": \"JavaScript\"\n          },\n          {\n            \"probability\": 0.7027,\n            \"type\": \"Other\",\n            \"normalized_text\": \"TypeScript\"\n          },\n          {\n            \"probability\": 0.7208,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Josh\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/nKtvr2wEg6\",\n            \"expanded_url\": \"https://twitter.com/JoshuaKGoldberg/status/1693713311836115286\",\n            \"display_url\": \"twitter.com/JoshuaKGoldberg\"\n          }\n        ]\n      },\n      \"author_id\": \"416394303\",\n      \"text\": \"Knip is wonderful at finding out unused code/dependencies in a legacy JavaScript/TypeScript application\\n\\nRecommend 💯\\n\\nHere's how Josh used it to remove code bloat in Centered: https://t.co/nKtvr2wEg6\",\n      \"id\": \"1693944495472046382\",\n      \"created_at\": \"2023-08-22T11:13:34.000Z\",\n      \"edit_history_tweet_ids\": [\"1693944495472046382\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.5513,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/L8w9V11PRL\",\n            \"expanded_url\": \"https://www.smashingmagazine.com/2023/08/knip-automated-tool-find-unused-files-exports-dependencies/\",\n            \"display_url\": \"smashingmagazine.com/2023/08/knip-a…\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1727384011872366592/W-M5klkJ?format=jpg&name=orig\",\n                \"width\": 1200,\n                \"height\": 675\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1727384011872366592/W-M5klkJ?format=jpg&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"Knip: An Automated Tool For Finding Unused Files, Exports, And Dependencies — Smashing Magazine\",\n            \"description\": \"Most of the projects have at least a few unused files, exports, and dependencies lying around, often because it’s difficult knowing when one thing relies on another and scary removing something you’re not sure is in use. Lars Kappert shares a tool he’s been working on that offers a solution.\",\n            \"unwound_url\": \"https://www.smashingmagazine.com/2023/08/knip-automated-tool-find-unused-files-exports-dependencies/\"\n          }\n        ]\n      },\n      \"author_id\": \"15736190\",\n      \"text\": \"Unused files, exports, and dependencies often clutter projects, as it’s difficult knowing when one thing relies on another and scary to remove something you’re not sure is in use. 👀\\n\\n↬ Meet Knip, which scours projects for these unused artifacts: https://t.co/L8w9V11PRL\",\n      \"id\": \"1691120132901240832\",\n      \"created_at\": \"2023-08-14T16:10:33.000Z\",\n      \"edit_history_tweet_ids\": [\"1691120132901240832\"]\n    },\n    {\n      \"entities\": {\n        \"mentions\": [\n          {\n            \"username\": \"typescript\",\n            \"id\": \"809233214\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/1mRMwvjIpw\",\n            \"expanded_url\": \"https://effectivetypescript.com/2023/07/29/knip/\",\n            \"display_url\": \"effectivetypescript.com/2023/07/29/kni…\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1696204795353219085/ZjmFlTVW?format=jpg&name=orig\",\n                \"width\": 560,\n                \"height\": 735\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1696204795353219085/ZjmFlTVW?format=jpg&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"Effective TypeScript › Recommendation Update: ✂️ Use knip to detect dead code and types\",\n            \"description\": \"TL;DR: Use ts-prune is in maintenance mode. Use knip to find dead code instead. It's great!\",\n            \"unwound_url\": \"https://effectivetypescript.com/2023/07/29/knip/\"\n          }\n        ]\n      },\n      \"author_id\": \"21046936\",\n      \"text\": \"Recommendation update: use knip to find dead code, types and dependencies in your @typescript ✂️https://t.co/1mRMwvjIpw\",\n      \"id\": \"1685298103094554625\",\n      \"created_at\": \"2023-07-29T14:35:53.000Z\",\n      \"edit_history_tweet_ids\": [\"1685298103094554625\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9661,\n            \"type\": \"Other\",\n            \"normalized_text\": \"GitHub\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/vnxNbiJs1I\",\n            \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n            \"display_url\": \"github.com/webpro-nl/knip\",\n            \"images\": [\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig\",\n                \"width\": 1280,\n                \"height\": 640\n              },\n              {\n                \"url\": \"https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150\",\n                \"width\": 150,\n                \"height\": 150\n              }\n            ],\n            \"title\": \"GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!\",\n            \"description\": \"✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...\",\n            \"unwound_url\": \"https://github.com/webpro-nl/knip\"\n          }\n        ]\n      },\n      \"author_id\": \"380616577\",\n      \"text\": \"This is worth checking out on GitHub. 👍 https://t.co/vnxNbiJs1I\",\n      \"id\": \"1581910299846012928\",\n      \"created_at\": \"2022-10-17T07:29:40.000Z\",\n      \"edit_history_tweet_ids\": [\"1581910299846012928\"]\n    },\n    {\n      \"note_tweet\": {\n        \"text\": \"Streamlining React projects with Knip:\\n\\nRecently, I employed Knip for a project, and it worked wonders! \\n\\nIt efficiently resolved issues with removing\\n✅ Unused files, \\n✅ Unused npm dependencies, \\n✅ Unneeded TypeScript exports.\\n\\n A real time-saver for maintaining a clean and efficient codebase. 🛠️ #ReactDevelopment \\n\\nhttps://t.co/IbJH2fIzsE\",\n        \"entities\": {\n          \"urls\": [\n            {\n              \"url\": \"https://t.co/IbJH2fIzsE\",\n              \"expanded_url\": \"https://github.com/webpro-nl/knip\",\n              \"display_url\": \"github.com/webpro-nl/knip\"\n            }\n          ],\n          \"hashtags\": [{ \"tag\": \"ReactDevelopment\" }]\n        }\n      },\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.743,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          },\n          {\n            \"probability\": 0.7667,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ],\n        \"urls\": [\n          {\n            \"url\": \"https://t.co/P39xg0qCrT\",\n            \"expanded_url\": \"https://twitter.com/i/web/status/1693502146128281657\",\n            \"display_url\": \"twitter.com/i/web/status/1…\"\n          }\n        ]\n      },\n      \"author_id\": \"827145937030148097\",\n      \"text\": \"Streamlining React projects with Knip:\\n\\nRecently, I employed Knip for a project, and it worked wonders! \\n\\nIt efficiently resolved issues with removing\\n✅ Unused files, \\n✅ Unused npm dependencies, \\n✅ Unneeded TypeScript exports.\\n\\n A real time-saver for maintaining a clean and… https://t.co/P39xg0qCrT\",\n      \"id\": \"1693502146128281657\",\n      \"created_at\": \"2023-08-21T05:55:50.000Z\",\n      \"edit_history_tweet_ids\": [\"1693502146128281657\"]\n    },\n    {\n      \"entities\": {\n        \"annotations\": [\n          {\n            \"probability\": 0.9331,\n            \"type\": \"Other\",\n            \"normalized_text\": \"JavaScript\"\n          },\n          {\n            \"probability\": 0.5907,\n            \"type\": \"Other\",\n            \"normalized_text\": \"Knip\"\n          }\n        ]\n      },\n      \"author_id\": \"18191376\",\n      \"text\": \"Found a bunch of unused code, -dependencies, and unnecessary exports. Had just one false positive but overall pretty good. 10/10 would recommend.\\n\\nIf you’ve got a JavaScript package/project use Knip and remove unnecessary code. ✂️\",\n      \"id\": \"1692942539614028086\",\n      \"created_at\": \"2023-08-19T16:52:09.000Z\",\n      \"edit_history_tweet_ids\": [\"1692942539614028086\"]\n    }\n  ],\n  \"includes\": {\n    \"media\": [\n      {\n        \"media_key\": \"1\",\n        \"url\": \"https://pbs.twimg.com/media/GDrwdB3aYAAu4am?format=png&name=orig\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"2\",\n        \"url\": \"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:opw3iapscc55nlgrx6q2yjah/bafkreihzszb56agbe6dtuf6xfutl65mjg5ethnrvw264d5bljbm377jora@jpeg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"3_1730179997682552832\",\n        \"url\": \"https://pbs.twimg.com/media/GALVin9a0AAsn0-.jpg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"4\",\n        \"url\": \"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:4dsclu5hjmht3shxutxtge6h/bafkreid63o3hwvwpk6emgzj64vywusztofhz2yihuvwkywuuajn4eekvom@jpeg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"5\",\n        \"url\": \"https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:2gkh62xvzokhlf6li4ol3b3d/bafkreiahk2jbsb2stw276lkrkxrkvialqs25zrpgo2n3cigzfb7qvgfsmq@jpeg\",\n        \"type\": \"photo\"\n      },\n      {\n        \"media_key\": \"6\",\n        \"url\": \"https://pbs.twimg.com/media/G9wBaMFWoAAkgv5.png\",\n        \"type\": \"photo\"\n      }\n    ],\n    \"users\": [\n      {\n        \"id\": \"22\",\n        \"username\": \"molliboyle.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:uwwm2qtpni4gvzzhujhh56ps/bafkreib5w76mmc6lxazhkymadd3oj5skped63b6ugvswiikrss7ljgcfi4@jpeg\",\n        \"name\": \"Molly Boyle\"\n      },\n      {\n        \"id\": \"20\",\n        \"username\": \"RozenMD\",\n        \"profile_image_url\": \"https://unavatar.io/x/RozenMD\",\n        \"name\": \"Max Rozen\"\n      },\n      {\n        \"id\": \"21\",\n        \"username\": \"06_Shreehari\",\n        \"profile_image_url\": \"https://unavatar.io/x/06_Shreehari\",\n        \"name\": \"Shreehari\"\n      },\n      {\n        \"id\": \"19\",\n        \"username\": \"janis.me\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:kmekwulhn26kgfwjzrry76d7/bafkreihtzvhhk7oz6cjbgnsbaravu46zhai3zwogkcg7hxv3dlhvecrqw4@jpeg\",\n        \"name\": \"Janis Jansen\"\n      },\n      {\n        \"id\": \"11\",\n        \"username\": \"julien.deniau.me\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:4dsclu5hjmht3shxutxtge6h/bafkreiht3iqxcmelwe7oysawrdpynzevf4dt2ndzeln4f5c2izf62zm57q@jpeg\",\n        \"name\": \"Julien Deniau\"\n      },\n      {\n        \"id\": \"12\",\n        \"username\": \"alexharfordseo.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:y3arowkhgiexpyvmmxvquavg/bafkreiazlcx5fdxylsqtsdng3beq3ayuoc7nzyqcddeequhi7uploqcjny@jpeg\",\n        \"name\": \"AlexHarford-TechSEO\"\n      },\n      {\n        \"id\": \"13\",\n        \"username\": \"fubits.dev\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:6aglx53tojyuwxwueap5og3h/bafkreiclnob3mnfvo74an6ugrnbdikrkxcskndjojrdtkwf5vwjuu77z5u@jpeg\",\n        \"name\": \"Ilja\"\n      },\n      {\n        \"id\": \"14\",\n        \"username\": \"alexanderkaran.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:3n4fccuhdomkkebojjdurnco/bafkreiggltcvdoh4igf5yxvrxggysmasv5efn6hffyav2o6swxslbc3lp4@jpeg\",\n        \"name\": \"Alexander Karan\"\n      },\n      {\n        \"id\": \"15\",\n        \"username\": \"patak.dev\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:2gkh62xvzokhlf6li4ol3b3d/bafkreibi7rw745tbcea7ljrpbkkkoragy2xa5a2lrxhdb3m23s7n3wkv3q@jpeg\",\n        \"name\": \"patak\"\n      },\n      {\n        \"id\": \"16\",\n        \"username\": \"psparwez\",\n        \"profile_image_url\": \"https://unavatar.io/x/psparwez\",\n        \"name\": \"PS\"\n      },\n      {\n        \"id\": \"17\",\n        \"username\": \"k_shehadeh\",\n        \"profile_image_url\": \"https://unavatar.io/x/k_shehadeh\",\n        \"name\": \"Karim Shehadeh\"\n      },\n      {\n        \"id\": \"18\",\n        \"username\": \"cramforce\",\n        \"profile_image_url\": \"https://unavatar.io/x/cramforce\",\n        \"name\": \"Malte Ubl\"\n      },\n      {\n        \"id\": \"1\",\n        \"username\": \"sqs\",\n        \"profile_image_url\": \"https://unavatar.io/x/sqs\",\n        \"name\": \"Quinn Slack\"\n      },\n      {\n        \"id\": \"2\",\n        \"username\": \"jokull\",\n        \"profile_image_url\": \"https://unavatar.io/x/jokull\",\n        \"name\": \"Jökull Solberg\"\n      },\n      {\n        \"id\": \"3\",\n        \"username\": \"Hicksyfern\",\n        \"profile_image_url\": \"https://unavatar.io/x/Hicksyfern\",\n        \"name\": \"Tom Hicks\"\n      },\n      {\n        \"id\": \"4\",\n        \"username\": \"daviduzumeri.bsky.social\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:6ykajndqngy2kxozo37mpsgc/bafkreif2xu6bini3tpv2hfauw53ng43zbefgqol36yt4baehcbdfxahihu@jpeg\",\n        \"name\": \"Old Man Uzi\"\n      },\n      {\n        \"id\": \"5\",\n        \"username\": \"gary__tyr\",\n        \"profile_image_url\": \"https://unavatar.io/x/gary__tyr\",\n        \"name\": \"Gary Tyr\"\n      },\n      {\n        \"id\": \"6\",\n        \"username\": \"KevinVanCott\",\n        \"profile_image_url\": \"https://unavatar.io/x/KevinVanCott\",\n        \"name\": \"Kevin Thomas Van Cott\"\n      },\n      {\n        \"id\": \"7\",\n        \"username\": \"joshuakgoldberg.com\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:hwtki3j7oghodc7h6gqnrtro/bafkreicvkrpjmc7yoviwf5vhkecgcgyn23x24ix4aqdwiikcl226c64k2q@jpeg\",\n        \"name\": \"Josh Goldberg 💖\"\n      },\n      {\n        \"id\": \"8\",\n        \"username\": \"beaussan.io\",\n        \"profile_image_url\": \"https://cdn.bsky.app/img/avatar/plain/did:plc:opw3iapscc55nlgrx6q2yjah/bafkreiaj72657msogojjdk4wr76fe3umimydon3pzzrquuj7opcftntrqa@jpeg\",\n        \"name\": \"Nicolas Beaussart\"\n      },\n      {\n        \"id\": \"9\",\n        \"username\": \"MidnightDesign\",\n        \"name\": \"Rudolph Gottesheim\",\n        \"profile_image_url\": \"https://avatars.githubusercontent.com/u/743172?v=4\"\n      },\n      {\n        \"id\": \"10\",\n        \"username\": \"stephaneledorze\",\n        \"name\": \"stephane le dorze\",\n        \"profile_image_url\": \"https://unavatar.io/x/stephaneledorze\"\n      },\n      {\n        \"id\": \"22918124\",\n        \"username\": \"gregberge_\",\n        \"profile_image_url\": \"https://unavatar.io/x/gregberge_\",\n        \"name\": \"Greg Bergé\"\n      },\n      {\n        \"id\": \"19268321\",\n        \"username\": \"housecor\",\n        \"profile_image_url\": \"https://unavatar.io/x/housecor\",\n        \"name\": \"Cory House\"\n      },\n      {\n        \"id\": \"3126044440\",\n        \"username\": \"pkgacek\",\n        \"profile_image_url\": \"https://unavatar.io/x/pkgacek\",\n        \"name\": \"Piotr Gacek 🐟\"\n      },\n      {\n        \"id\": \"95668959\",\n        \"username\": \"kuizinas\",\n        \"profile_image_url\": \"https://unavatar.io/x/kuizinas\",\n        \"name\": \"Gajus\"\n      },\n      {\n        \"id\": \"1632752318994153472\",\n        \"username\": \"imabhiprasad\",\n        \"profile_image_url\": \"https://unavatar.io/x/imabhiprasad\",\n        \"name\": \"Abhijeet Prasad\"\n      },\n      {\n        \"id\": \"1513218780167655427\",\n        \"username\": \"fernandoeeu_dev\",\n        \"profile_image_url\": \"https://unavatar.io/x/fernandoeeu_dev\",\n        \"name\": \"Fernando\"\n      },\n      {\n        \"id\": \"44217212\",\n        \"username\": \"TkDodo\",\n        \"profile_image_url\": \"https://unavatar.io/x/TkDodo\",\n        \"name\": \"Dominik 🔮\"\n      },\n      {\n        \"id\": \"481186762\",\n        \"username\": \"Mokkapps\",\n        \"profile_image_url\": \"https://unavatar.io/x/Mokkapps\",\n        \"name\": \"Michael Hoffmann\"\n      },\n      {\n        \"id\": \"416394303\",\n        \"username\": \"nicoespeon\",\n        \"profile_image_url\": \"https://unavatar.io/x/nicoespeon\",\n        \"name\": \"Nicolas Carlo\"\n      },\n      {\n        \"id\": \"15736190\",\n        \"username\": \"smashingmag\",\n        \"profile_image_url\": \"https://unavatar.io/x/smashingmag\",\n        \"name\": \"Smashing Magazine 🇺🇦 🏳️‍🌈\"\n      },\n      {\n        \"id\": \"21046936\",\n        \"username\": \"danvdk\",\n        \"profile_image_url\": \"https://unavatar.io/x/danvdk\",\n        \"name\": \"Dan Vanderkam\"\n      },\n      {\n        \"id\": \"380616577\",\n        \"username\": \"stefanjudis\",\n        \"profile_image_url\": \"https://unavatar.io/x/stefanjudis\",\n        \"name\": \"Stefan Judis\"\n      },\n      {\n        \"id\": \"827145937030148097\",\n        \"username\": \"BKailaash\",\n        \"profile_image_url\": \"https://unavatar.io/x/BKailaash\",\n        \"name\": \"Kailaash\"\n      },\n      {\n        \"id\": \"18191376\",\n        \"username\": \"waldekm\",\n        \"profile_image_url\": \"https://unavatar.io/x/waldekm\",\n        \"name\": \"Waldek Mastykarz\"\n      }\n    ]\n  }\n}\n\n<!-- File: packages/docs/src/content/docs/explanations/comparison-and-migration.md (Tokens: ~1056 | Category: anthropic-skill) -->\n---\ntitle: Comparison & Migration\ndescription: How Knip compares to depcheck, unimported, ts-prune, ts-unused-exports and tsr, and how to migrate from them.\n---\n\nFirst of all, Knip owes a lot to the projects on this page and they've all been\ninspirational in their own way. For best results, Knip has [a vision embracing\ncomprehensiveness][1] which is larger in scope than any of the alternatives. So\nif any of those tools has the right scope for your requirements, then by all\nmeans, use what suits you best. Note that most projects are no longer\nmaintained.\n\nAll tools have in common that they have less features and don't support the\nconcept of [monorepos/workspaces][2]. Feel free to send in projects that Knip\ndoes not handle better, Knip loves to be challenged!\n\n## Migration\n\nA migration consists of deleting the dependency and its configuration file and\n[getting started with Knip][3]. You should end up with less configuration.\n\n## Comparison\n\n### depcheck\n\n> [Depcheck][4] is a tool for analyzing the dependencies in a project to see:\n> how each dependency is used, which dependencies are useless, and which\n> dependencies are missing from package.json.\n\nThe project has plugins (specials), yet not as many as Knip has and they're not\nas advanced. It also supports compilers (parsers) for non-standard files.\n\nThe following commands are similar:\n\n```sh\ndepcheck\nknip --dependencies\n```\n\n**Project status**: The project is archived and recommends Knip.\n\n### unimported\n\n> Find and fix dangling files and unused dependencies in your JavaScript\n> projects.\n\n[unimported][5] is fast and works well. It works in what Knip calls \"production\nmode\" exclusively. If you're fine with a little bit of configuration and don't\nwant or need to deal with non-production items (such as `devDependencies` and\ntest files), then this might work well for you.\n\nThe following commands are similar:\n\n```sh\nunimported\nknip --production --dependencies --files\n```\n\n**Project status**: The project is archived and recommends Knip.\n\n### ts-prune\n\n> Find unused exports in a typescript project. 🛀\n\n[ts-prune][6] aims to find potentially unused exports in your TypeScript project\nwith zero configuration.\n\nThe following commands are similar:\n\n```sh\nts-prune\nknip --include exports,types,nsExports,nsTypes\n```\n\nUse `knip --exports` to also include enum and namespace members.\n\n**Project status**: The project is archived and recommends Knip.\n\n### ts-unused-exports\n\n> [ts-unused-exports][7] finds unused exported symbols in your Typescript\n> project\n\nThe following commands are similar:\n\n```sh\nts-unused-exports\nknip --include exports,types,nsExports,nsTypes\n```\n\nUse `knip --exports` to also include enum and namespace members.\n\n### tsr\n\n> Remove unused code from your TypeScript Project\n\n[tsr][8] (previously `ts-remove-unused`) removes unused exports, and works based\non a single `tsconfig.json` file (`includes` and `excludes`) and requires no\nconfiguration. It removes the `export` keyword or the whole export declaration.\n\n**Project status**: The project is archived and recommends Knip.\n\n## Related projects\n\nAdditional alternative and related projects include:\n\n- [deadfile][9]\n- [DepClean][10]\n- [dependency-check][11]\n- [find-unused-exports][12]\n- [next-unused][13]\n- [npm-check][14]\n- [renoma][15]\n\nIn general, the [e18e.dev][16] website and in particular the [Cleanup][17]\nsection is a great resource when dealing with technical debt.\n\n[1]: ./why-use-knip.md#comprehensive\n[2]: ../features/monorepos-and-workspaces.md\n[3]: ../overview/getting-started.mdx\n[4]: https://github.com/depcheck/depcheck\n[5]: https://github.com/smeijer/unimported\n[6]: https://github.com/nadeesha/ts-prune\n[7]: https://github.com/pzavolinsky/ts-unused-exports\n[8]: https://github.com/line/tsr\n[9]: https://github.com/M-Izadmehr/deadfile\n[10]: https://github.com/mysteryven/depclean\n[11]: https://github.com/dependency-check-team/dependency-check\n[12]: https://github.com/jaydenseric/find-unused-exports\n[13]: https://github.com/pacocoursey/next-unused\n[14]: https://github.com/dylang/npm-check\n[15]: https://github.com/bluwy/renoma\n[16]: https://e18e.dev\n[17]: https://e18e.dev/guide/cleanup.html\n\n<!-- File: packages/docs/src/content/docs/explanations/entry-files.md (Tokens: ~838 | Category: anthropic-skill) -->\n---\ntitle: Entry Files\ndescription: What entry files are and how Knip and its plugins find them automatically from defaults, `package.json`, plugins and dynamic imports.\n---\n\nEntry files are the starting point for Knip to determine what files are used in\nthe codebase. More entry files lead to increased coverage of the codebase. This\nalso leads to more dependencies to be discovered. This page explains how Knip\nand its plugins try to find entry files so you don't need to configure them\nyourself.\n\n## Default entry file patterns\n\nFor brevity, the [default configuration][1] on the previous page mentions only\n`index.js` and `index.ts`, but the default set of file names and extensions is\nactually a bit larger:\n\n- `index`, `main` and `cli`\n- `js`, `mjs`, `cjs`, `jsx`, `ts`, `mts`, `cts` and `tsx`\n\nThis means files like `main.cjs` and `src/cli.ts` are automatically added as\nentry files. Here's the default configuration in full:\n\n```json\n{\n  \"entry\": [\n    \"{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\",\n    \"src/{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\"\n  ],\n  \"project\": [\"**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}!\"]\n}\n```\n\nNext to the default locations, Knip looks for `entry` files in other places. In\na monorepo, this is done for each workspace separately.\n\nThe values you set override the default values, they are not merged.\n\n## Plugins\n\nPlugins often add entry files. For instance, the Remix, Storybook and Vitest\nplugins add additional entry files. See [the next page about plugins][2] for\nmore details about this.\n\n## Scripts in package.json\n\nThe `package.json` is scanned for entry files. The `main`, `bin`, and `exports`\nfields may contain entry files. The `scripts` are also parsed to find entry\nfiles and dependencies. See [Script Parser][3] for more details.\n\n## Ignored files\n\nKnip respects `.gitignore` files. By default, ignored files are not added as\nentry files. This behavior can be disabled by using the [`--no-gitignore`][4]\nflag on the CLI.\n\n## Configuring project files\n\nSee [configuring project files][5] for guidance on tuning `entry` and `project`\nand when to use `ignore`.\n\n## Where Knip looks for entry files\n\nPutting it together, Knip discovers entry files from:\n\n- Default locations such as `index.js` and `src/index.ts`\n- The `main`, `bin` and `exports` fields in `package.json`\n- Entry and config files added by enabled plugins (the config files are entry\n  files too)\n- Dynamic imports: `require()` and `import()`\n- `require.resolve()` and `import.meta.resolve()`\n- `new URL('./file.js', import.meta.url)`\n- `new Worker(…)` and `child_process` `fork`/`spawn`/`execFile` when the target\n  is `path.join(__dirname, …)`\n- `module.register('./loader.js')` loader registration\n- Scripts the [script parser][3] extracts: `package.json` scripts, CI workflow\n  `run` commands, and source-code calls (tagged `$` templates,\n  `node:child_process`, `execa`, `nano-spawn`)\n\nEntry files are added to the module graph, and module resolution may pull in\nfurther entry files recursively until none remain.\n\n[1]: ../overview/configuration.md#defaults\n[2]: ./plugins.md\n[3]: ../features/script-parser.md\n[4]: ../reference/cli.md#--no-gitignore\n[5]: ../guides/configuring-project-files.md\n\n<!-- File: packages/docs/src/content/docs/explanations/how-knip-works.md (Tokens: ~931 | Category: anthropic-skill) -->\n---\ntitle: How Knip works\ndescription: The mental model behind Knip. How entry files, the module graph and reachability decide what counts as unused, and why surprising results trace back to them.\n---\n\nKnip finds and removes unused code and dependencies. It starts at your entry\nfiles, follows every import to the files they reach, and builds a graph of\neverything connected. Anything left out is reported as unused: a file no entry\nreaches, an export no file imports, a dependency no file uses.\n\nThis page explains how Knip produces its results.\n\n## Build and analyze\n\nKnip runs in two phases.\n\nThe build phase starts from the entry files. Knip reads a file, parses it,\ncollects its imports and exports, resolves each import to another file, and\nrepeats for every newly reached file. The result is a graph of the project:\nevery reachable file, what it imports, and what imports it.\n\nResolution is broad by design. Knip follows custom path aliases and extensions,\nreads references out of config files and [shell scripts][1], and \"[compiles][2]\"\nnon-standard files like `.vue` and `.svelte` so their imports are in the graph\ntoo.\n\nThe analysis phase queries that graph. It never re-parses anything. It walks the\nedges already recorded:\n\n- a **file** is unused when no entry reaches it\n- an **export** is unused when no other file imports it\n- a **dependency** is unused when no file imports it (and _unlisted_ when a file\n  imports it but `package.json` doesn't list it)\n\nAnalysis happens by quering the graph. Your results are only as accurate as the\ngraph is complete. And the graph depends on your entry files.\n\n## Entry files decide what Knip can see\n\nThe graph contains only what's reachable from an entry file. Miss one entry, and\neverything reachable _only_ from it looks unused.\n\nIdeally you don't need to list entries by hand. Knip starts from sensible\n[defaults][3] like `src/index.ts`, and [plugins][4] automatically add the entry\npoints specific to your frameworks and libraries. The Vitest plugin adds your\ntest files, the Astro plugin adds your pages, and so on. This is why plugins are\nimportant: each one tells Knip about a whole class of files it might otherwise\nnever reach.\n\n## Findings come in chains\n\nUnused results cascade. They don't appear in isolation. Say a tool generates an\nentry file Knip doesn't know about:\n\n- that file looks unused, because nothing reaches it\n- every file it imports looks unused too, because nothing else reaches them\n- every export in those files looks unused\n- every dependency only those files used looks unused\n\nOne unreached entry can turn into dozens of findings. The chain also runs in\nreverse: add the entry, and the whole cascade collapses at once.\n\nSo read the output from the root down: **unused files first, then exports, then\ndependencies.** A single unused file usually explains a long list of results\nbelow it. Fix causes at the root and the rest disappears.\n\nSome chains only show up one run at a time. An export counts as used when\nanother file imports it, even if the importing code is unused. Remove that code,\nand the next run may report the export. Unused exports that import each other\nacross files are never reported.\n\n## A surprising result might be a gap, not a bug\n\nWhen Knip flags something you're sure is used, it's based on the graph: it\ncouldn't reach that code from an entry. The cause is usually one of:\n\n- a missing entry for a tool or convention Knip doesn't know yet\n- a dynamic import Knip can't follow statically, or a path it can't resolve\n- a transitive dependency of a package that resolves only because something else\n  installs it\n\nIn each case the fix is to teach Knip: add the entry, configure the plugin, list\nthe dependency. Don't hide the result. [Configuring project files][5] and\n[resolving reported issues][6] cover how, issue type by issue type.\n\n[1]: ../features/script-parser.md\n[2]: ../features/compilers.md\n[3]: ./entry-files.md\n[4]: ./plugins.md\n[5]: ../guides/configuring-project-files.md\n[6]: ../guides/handling-issues.mdx\n\n<!-- File: packages/docs/src/content/docs/explanations/plugins.md (Tokens: ~2404 | Category: anthropic-skill) -->\n---\ntitle: Plugins\ndescription: How Knip plugins work and the difference between `config` files (parsed for dependencies) and `entry` files (added to the module graph).\n---\n\nThis page describes why Knip uses plugins and the difference between `config`\nand `entry` files.\n\nKnip has an extensive and growing [list of built-in plugins][1]. Feel free to\n[write a plugin][2] so others can benefit too!\n\n## What does a plugin do?\n\nPlugins are enabled if the related package is listed in the list of dependencies\nin `package.json`. For instance, if `astro` is listed in `dependencies` or\n`devDependencies`, then the Astro plugin is enabled. And this means that this\nplugin will:\n\n- Handle [configuration files][3] like `astro.config.mjs`\n- Add [entry files][4] such as `src/pages/**/*.astro`\n- Define [command-line arguments][5]\n\n## Configuration files\n\nKnip uses [entry files][6] as starting points to scan your source code and\nresolve other internal files and external dependencies. The module graph can be\nstatically resolved through the `require` and `import` statements in those\nsource files. However, configuration files reference external dependencies in\nvarious ways. Knip uses a plugin for each tool to parse configuration files and\nfind those dependencies.\n\n### Example: ESLint\n\nIn the first example we look at [the ESLint plugin][7]. The default `config`\nfile patterns include `.eslintrc.json`. Here's a minimal example:\n\n```json title=\".eslintrc.json\"\n{\n  \"extends\": [\"airbnb\", \"prettier\"],\n  \"plugins\": [\"@typescript-eslint\"]\n}\n```\n\nConfiguration files like this don't `import` or `require` anything, but they do\nrequire the referenced dependencies to be installed.\n\nIn this case, the plugin will return three dependencies:\n\n- `eslint-config-airbnb`\n- `eslint-config-prettier`\n- `@typescript-eslint/eslint-plugin`\n\nKnip will then look for missing dependencies in `package.json` and report those\nas unlisted. And vice versa, if there are any ESLint plugins listed in\n`package.json`, but unused, those will be reported as well.\n\n### Example: Vitest\n\nThe second example uses [the Vitest plugin][8]. Here's a minimal example of a\nVitest configuration file:\n\n```ts title=\"vitest.config.ts\"\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    coverage: {\n      provider: 'istanbul',\n    },\n    environment: 'happy-dom',\n  },\n});\n```\n\nThe Vitest plugin reads this configuration and returns two dependencies:\n\n- `@vitest/coverage-istanbul`\n- `vitest-environment-happy-dom`\n\nKnip will look for missing and unused dependencies in `package.json` and report\naccordingly.\n\nSome tools allow configuration to be stored in `package.json`, that's why some\nplugins contain `package.json` in the list of `config` files.\n\n:::tip[Summary]\n\nPlugins load configuration files to find referenced dependencies, and determine\nunused and unlisted dependencies.\n\n:::\n\n## Entry files\n\nMany plugins have default `entry` files configured. When the plugin is enabled,\nKnip will add entry files as configured by the plugin to resolve used files and\ndependencies.\n\nFor example, if `next` is listed as a dependency in `package.json`, the Next.js\nplugin will automatically add multiple patterns as entry files, such as\n`pages/**/*.{js,jsx,ts,tsx}`. If `vitest` is listed, the Vitest plugin adds\n`**/*.{test,test-d,spec,spec-d}.ts` as entry file patterns. Most plugins have\nentry files configured, so you don't have to.\n\nIt's mostly plugins for meta frameworks and test runners that have `entry` files\nconfigured.\n\n:::tip[Plugins result in less configuration]\n\nPlugins use entry file patterns as defined in your configuration file of these\ntools. So you don't need to repeat this in your Knip configuration.\n\n:::\n\nFor example, let's say your Playwright configuration contains the following:\n\n```ts title=\"playwright.config.ts\"\nimport type { PlaywrightTestConfig } from '@playwright/test';\n\nconst config: PlaywrightTestConfig = {\n  testDir: 'integration',\n  testMatch: ['**/*-test.ts'],\n};\n\nexport default config;\n```\n\nThe Playwright plugin will read this configuration file and return those entry\npatterns (`integration/**/*-test.ts`). Knip will then not use the default entry\npatterns.\n\nYou can still override this behavior in your Knip configuration:\n\n```json title=\"knip.json\"\n{\n  \"playwright\": {\n    \"entry\": \"src/**/*.integration.ts\"\n  }\n}\n```\n\nThis should not be necessary though. Please consider opening a pull request or a\nbug report if any plugin is not behaving as expected.\n\n:::tip[Summary]\n\nPlugins try hard to automatically add the correct entry files.\n\n:::\n\n## Entry files from config files\n\nEntry files are part of plugin configuration (as described in the previous\nsection). Yet plugins can also return additional entry files after parsing\nconfiguration files. Below are some examples of configuration files parsed by\nplugins to return additional entry files. The goal of these examples is to give\nyou an idea about the various ways Knip and its plugins try to find entry files\nso you don't need to configure them yourself.\n\n### Angular\n\nThe Angular plugin parses the Angular configuration file. Here's a fragment:\n\n```json title=\"angular.json\"\n{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"projects\": {\n    \"knip-angular-example\": {\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit/build-angular:browser\",\n          \"options\": {\n            \"outputPath\": \"dist/knip-angular-example\",\n            \"main\": \"src/main.ts\",\n            \"tsConfig\": \"tsconfig.app.json\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nThis will result in `src/main.ts` being added as an entry file (and\n`@angular-devkit/build-angular` as a referenced dependency).\n\nAdditionally, the Angular plugin returns `tsconfig.app.json` as a configuration\nfile for the TypeScript plugin.\n\n### GitHub Actions\n\nThis plugin parses workflow YAML files. This fragment contains three `run`\nscripts:\n\n```yml title=\".github/workflows/deploy.yml\"\njobs:\n  integration:\n    runs-on: ubuntu-latest\n    steps:\n      - run: npm install\n      - run: node scripts/build.js\n      - run: node --loader tsx scripts/deploy.ts\n      - run: playwright test -c playwright.web.config.ts\n        working-directory: e2e\n```\n\nFrom these scripts, the `scripts/build.js` and `scripts/deploy.ts` files will be\nadded as entry files by the GitHub Actions plugin.\n\nAdditionally, the file `e2e/playwright.web.config.ts` is detected and will be\nhanded over as a Playwright configuration file.\n\nRead more about this in [command-line arguments][5].\n\n### webpack\n\nLet's take a look at this example webpack configuration file:\n\n```js title=\"webpack.config.js\"\nmodule.exports = env => {\n  return {\n    entry: {\n      main: './src/app.ts',\n      vendor: './src/vendor.ts',\n    },\n    module: {\n      rules: [\n        {\n          test: /\\.(woff|ttf|ico|woff2|jpg|jpeg|png|webp)$/i,\n          use: 'base64-inline-loader',\n        },\n      ],\n    },\n  };\n};\n```\n\nThe webpack plugin will parse this and add `./src/app.ts` and `./src/vendor.ts`\nas entry files. It will also add `base64-inline-loader` as a referenced\ndependency.\n\n:::tip[Summary]\n\nIn your config files, plugins can find additional entry files and also other\nconfig files recursively.\n\n:::\n\n## Bringing it all together\n\nSometimes a configuration file is a JavaScript or TypeScript file that imports\ndependencies, but also contains configuration that needs to be parsed by a\nplugin to find additional dependencies.\n\nLet's take a look at this example Vite configuration file:\n\n```ts title=\"vite.config.ts\"\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig(async ({ mode, command }) => {\n  return {\n    plugins: [react()],\n    test: {\n      setupFiles: ['./setup-tests.ts'],\n      environment: 'happy-dom',\n      coverage: {\n        provider: 'c8',\n      },\n    },\n  };\n});\n```\n\nThis file imports `vite` and `@vitejs/plugin-react` directly, but also\nindirectly references the `happy-dom` and `@vitest/coverage-c8` packages.\n\nThe Vite plugin of Knip will **dynamically** load this configuration file and\nparse the exported configuration. But it's not aware of the `vite` and\n`@vitejs/plugin-react` imports. This is why such `config` files are also\nautomatically added as `entry` files for Knip to **statically** resolve the\n`import` and `require` statements.\n\nAdditionally, `./setup-tests.ts` will be added as an `entry` file.\n\n:::note\n\nWhen plugins dynamically load configuration files, conditional dependencies may\nnot be detected if the condition evaluates differently during analysis. See\n[conditional or dynamic dependencies][9] for details and workarounds.\n\n:::\n\n## Command-Line Arguments\n\nPlugins may define the arguments where Knip should look for entry files,\nconfiguration files and dependencies. We've already seen some examples above:\n\n```sh\nnode --loader tsx scripts/deploy.ts\nplaywright test -c playwright.web.config.ts\n```\n\nPlease see [script parser][10] for more details.\n\n## Config File Location\n\nIf configuration files aren't in their default location and they are not\nreferenced through some script like `vite -c ./dir/vite.config.ts`, then make\nsure to tell Knip about it. Two examples:\n\n```json title=\"knip.jsonc\"\n{\n  \"playwright\": { \"config\": [\"e2e/playwright.config.ts\"] },\n  \"vite\": \"packages/*/vite.config.ts\" // shorthand without `config` and array notation\n}\n```\n\nThis is common in projects where a directory like `packages/lib` is not an\nactual workspace with a `package.json` file. Also see [integrated monorepos][11]\nfor similar cases.\n\n## Summary\n\n:::tip[Summary]\n\nPlugins are configured with two distinct types of files:\n\n- `config` files are dynamically loaded and parsed by the plugin\n- `entry` files are added to the module graph\n- Both can recursively lead to additional entry files, config files and\n  dependencies\n\n:::\n\n[1]: ../reference/plugins.md\n[2]: ../writing-a-plugin/index.md\n[3]: #configuration-files\n[4]: #entry-files\n[5]: #command-line-arguments\n[6]: ./entry-files.md\n[7]: ../reference/plugins/eslint.md\n[8]: ../reference/plugins/vitest.md\n[9]: ../guides/handling-issues.mdx#conditional-or-dynamic-dependencies\n[10]: ../features/script-parser.md\n[11]: ../features/integrated-monorepos.md\n\n<!-- File: packages/docs/src/content/docs/explanations/why-use-knip.md (Tokens: ~1237 | Category: anthropic-skill) -->\n---\ntitle: Why use Knip?\ndescription: Why remove unused files, exports and dependencies, and how Knip finds them comprehensively across greenfield and legacy (mono)repos.\n---\n\nThe value of removing clutter is clear, but finding it manually is tedious. Meet\nKnip: comprehensive and accurate results at any scale.\n\n:::tip[TL;DR]\n\nUnused files, exports and dependencies pile up as projects grow. Removing them\nimproves maintenance, performance, security and onboarding, and prevents\nregressions in CI. Knip automates finding (and fixing) all three,\ncomprehensively and at any scale.\n\n:::\n\n## Less is more\n\nThere are plenty of reasons to delete unused files, dependencies and \"dead\ncode\":\n\n- Easier maintenance: things are easier to manage when there's less of it.\n- Improved performance: startup time, build time and/or bundle size can be\n  negatively impacted when unused code, files and/or dependencies are included.\n  Relying on tree-shaking when bundling code helps, but it's not a silver\n  bullet.\n- Increased security: less code and dependencies means less room for weak spots.\n- Easier onboarding: there should be no doubts about whether files, dependencies\n  and exports are actually in use or not. Especially for people new to the\n  project and/or taking over responsibilities this is harder to grasp.\n- Prevent regressions: tools like TypeScript, ESLint and Prettier do all sorts\n  of checks and linting to report violations and prevent regressions. Knip does\n  the same for dependencies, exports and files that are obsolete.\n- Keeping dead code around has a negative value on readability, as it can be\n  misleading and distracting. Even if it serves no purpose it will need to be\n  maintained (source: [Safe dead code removal → YAGNI][1]).\n- Also see [Why are unused dependencies a problem?][2] and [Why are unused\n  exports a problem?][3].\n\n## Automation\n\nCode and dependency management is usually not the most exciting task for most of\nus. Knip's mission is to automate finding clutter. This is such a tedious job if\nyou were to do it manually, and where would you even start? Knip applies many\ntechniques and heuristics to report what you need and save a lot of time.\n\n:::tip\n\nKnip not only finds clutter, it can also [remove clutter][4]!\n\nUse Knip next to a linter like ESLint or Biome: after removing unused variables\ninside files, Knip might find even more unused code. Rinse and repeat!\n\n:::\n\n## Comprehensive\n\nYou can use alternative tools that do the same. However, the advantage of a\nstrategy that addresses all of dependencies, exports and files is in their\nsynergy:\n\n- Utilizing plugins to find their dependencies includes the capacity to find\n  additional entry and configuration files. This results in more resolved and\n  used files. Better coverage gives better insights into unused files and\n  exports.\n- Analyzing more files reveals more unused exports and dependency usage,\n  refining the list of both unused and unlisted dependencies.\n- This approach is amplified in a [monorepo setting][5]. In fact, files and\n  internal dependencies can recursively reference each other (across\n  workspaces).\n\nKnip reaches this coverage through [fine-grained entry points][6], [custom\nmodule resolution][7], [configuration-file parsers][8], an [advanced\nshell-script parser][9], and [built-in and custom compilers][10], then [fixes\nmost of it automatically][4].\n\n## Greenfield or Legacy\n\nInstalling Knip in greenfield projects ensures the project stays neat and tidy\nfrom the start. Add it to your CI workflow and prevent any regressions from\nentering the codebase.\n\n:::tip\n\nUse Knip in a CI environment to prevent future regressions.\n\n:::\n\nIn large and/or legacy projects, Knip may report false positives and require\nsome configuration. It aims to be a great assistant when cleaning up parts of\nthe project or doing large refactors. Even a list of results with a few false\npositives is many times better and faster than if you were to do it manually.\n\n## Unobtrusive\n\nKnip does not introduce new syntax for you to learn. This may sound obvious, but\nconsider comments like the following:\n\n```js\n// eslint-disable-next-line\n// prettier-ignore\n// @ts-expect-error\n```\n\nKnip doesn't have similar comments like `// knip-ignore` so you can get rid of\nfalse positives for a variety of reasons:\n\n1. A false positive may be a bug in Knip, and should be reported, not dismissed.\n2. Instead of proprietary comments, use [standardized annotations][11] that also\n   serve as documentation.\n3. In the event you want to remove Knip, just uninstall `knip` without having to\n   remove useless comments scattered throughout the codebase.\n\nTip: use `@lintignore` in JSDoc comments, so other linters can use the same.\n\n[1]: https://jfmengels.net/safe-dead-code-removal/#yagni-you-arent-gonna-need-it\n[2]: ../typescript/unused-dependencies.md#why-are-unused-dependencies-a-problem\n[3]: ../typescript/unused-exports.md#why-are-unused-exports-a-problem\n[4]: ../features/auto-fix.mdx\n[5]: ../features/monorepos-and-workspaces.md\n[6]: ./entry-files.md\n[7]: ../reference/faq.md#why-doesnt-knip-use-an-existing-module-resolver\n[8]: ./plugins.md#configuration-files\n[9]: ../features/script-parser.md\n[10]: ../features/compilers.md\n[11]: ../reference/jsdoc-tsdoc-tags.md\n\n<!-- File: packages/docs/src/content/docs/features/catalogs.md (Tokens: ~553 | Category: anthropic-skill) -->\n---\ntitle: Catalogs\ndescription: How Knip finds unused pnpm, Yarn and Bun catalog entries referenced through the `catalog:` protocol, and removes them with auto-fix.\n---\n\nCatalogs let you define dependency version ranges once and reference them across\nworkspaces in a monorepo. Knip reports catalog entries that are defined but no\nlonger referenced, and references to entries that do not exist. It can remove\nunused entries with [auto-fix][1].\n\n## Supported catalogs\n\nKnip reads catalogs from the first applicable location:\n\n- `pnpm-workspace.yaml` — the `catalog` (default) and `catalogs` (named) keys\n- `.yarnrc.yml` — the `catalog` and `catalogs` keys\n- `package.json` — the `catalog` and `catalogs` keys\n- `package.json#workspaces` — the `catalog` and `catalogs` keys (Bun)\n\n## Unused catalog entries\n\nA catalog entry is reported as unused when no workspace references it through\nthe `catalog:` protocol in its `package.json`:\n\n```json title=\"packages/app/package.json\"\n{\n  \"dependencies\": {\n    \"react\": \"catalog:\",\n    \"zod\": \"catalog:validation\"\n  }\n}\n```\n\n`catalog:` references the `default` catalog, while `catalog:validation`\nreferences the named `validation` catalog. References are resolved from\n`dependencies`, `devDependencies`, `peerDependencies`, `optionalDependencies`,\n`resolutions`, `pnpm-workspace.yaml#overrides`, and `pnpm.overrides` in the root\n`package.json` (pnpm 10 and older).\n\nEntries defined in a catalog but not referenced anywhere are reported as [unused\ncatalog entries][2].\n\n## Unresolved catalog references\n\nA `catalog:` reference is reported when the selected catalog does not define\nthat package. These issues point to the consuming `package.json` or\n`pnpm-workspace.yaml`, where package managers would otherwise fail to resolve\nthe version.\n\n## Filter and fix\n\nThe `catalog` and `catalogReferences` issue types are included by the\n[`--dependencies`][3] shortcut. Focus on them (or exclude them) like any other\nissue type:\n\n```sh\nknip --include catalog,catalogReferences\nknip --exclude catalog,catalogReferences\n```\n\n[Auto-fix][1] removes unused catalog entries from the catalog file:\n\n```sh\nknip --fix --fix-type catalog\n```\n\n[1]: ./auto-fix.mdx#catalog-entries\n[2]: ../reference/issue-types.md\n[3]: ./rules-and-filters.md#shorthands\n\n<!-- File: packages/docs/src/content/docs/features/compilers.md (Tokens: ~1424 | Category: anthropic-skill) -->\n---\ntitle: Compilers\ndescription: Built-in and custom compilers let Knip analyze non-standard files like `.astro`, `.mdx`, `.svelte` and `.vue` for imports and exports.\n---\n\nProjects may have source files that are not JavaScript or TypeScript, and thus\nrequire compilation (or transpilation, or pre-processing, you name it). Files\nlike `.mdx`, `.astro`, `.vue` and `.svelte` may also import other source files\nand external dependencies. So ideally, these files are included when linting the\nproject. That's why Knip supports compilers.\n\n## Built-in compilers\n\nKnip has built-in \"compilers\" for the following file extensions:\n\n- `.astro`\n- `.css` (only enabled by `tailwindcss`)\n- `.mdx`\n- `.prisma`\n- `.sass` + `.scss`\n- `.less`\n- `.styl` + `.stylus`\n- `.svelte`\n- `.tsrx`\n- `.vue`\n\nKnip does not include real compilers for those files, but regular expressions to\ncollect `import` statements. This is fast, requires no dependencies, and enough\nfor Knip to build the module graph. The tradeoff is that unused exports inside\nthese files go unreported.\n\nReal compilers recover those exports, but bring their own challenges. The Svelte\ncompiler, for instance, keeps `exports` intact even when they represent\ncomponent properties, so Knip reports them as unused. When you need that\nfidelity, override any built-in with the framework's own compiler (see the\n[Svelte][1] and [Vue][2] examples below). For example, to report unused exports\nin [`.tsrx`][3] files.\n\nCompilers are enabled only when a related dependency is found. The `.tsrx`\ncompiler when a `@tsrx/*` package is installed, for example. If that detection\ndoesn't work for your project, set `true` to enable any compiler manually:\n\n```ts title=\"knip.ts\"\nexport default {\n  compilers: {\n    mdx: true,\n  },\n};\n```\n\n## Compiled files and `project` patterns\n\nThe default `project` patterns include compiler extensions automatically. When\nyou override `project`, list them explicitly:\n\n```ts title=\"knip.ts\"\nexport default {\n  project: ['src/**/*.{ts,tsx,css}'],\n};\n```\n\nFiles outside `project` are not analyzed, so their imports don't count. A\nnarrowed pattern like `['src/**/*.{ts,tsx}']` silently drops everything a\nstylesheet imports, which is a common source of false positives: `@import\n'tailwindcss'` in an excluded `.css` file gets `tailwindcss` reported as an\nunused dependency. Knip reports a configuration hint when a compiled extension\nis excluded this way.\n\n## Custom compilers\n\nBuilt-in compilers can be overridden, and additional compilers can be added.\nSince compilers are functions, the Knip configuration file must be a dynamic\n`.js` or `.ts` file.\n\n### Interface\n\nThe compiler function interface is straightforward. Text in, text out:\n\n```ts\n(source: string, filename: string) => string | PromiseLike<string>;\n```\n\nReturn a string or a Promise-like value that resolves to a string. Knip compiles\nfiles on demand and awaits asynchronous results; the `async` keyword is\noptional.\n\n### Examples\n\n- [CSS][4]\n- [MDX][5]\n- [Svelte][1]\n- [Vue][2]\n\n#### CSS\n\nHere's an example, minimal compiler for CSS files:\n\n```ts title=\"knip.ts\"\nexport default {\n  compilers: {\n    css: (text: string) => [...text.matchAll(/(?<=@)import[^;]+/g)].join('\\n'),\n  },\n};\n```\n\nYou may wonder why the CSS compiler is not included by default. It's currently\nnot clear if it should be included. And if so, what would be the best way to\ndetermine it should be enabled, and what syntax(es) it should support. Note that\nTailwind CSS, SASS/SCSS, Less and Stylus compilers are included.\n\n#### MDX\n\nAnother example, in case the built-in MDX compiler is not enough:\n\n```ts\nimport { compile } from '@mdx-js/mdx';\n\nexport default {\n  compilers: {\n    mdx: async text => (await compile(text)).toString(),\n  },\n};\n```\n\n#### Svelte\n\nIn a Svelte project, the compiler is automatically enabled. Override and use\nSvelte's compiler for better results if the built-in \"compiler\" is not enough:\n\n```ts\nimport type { KnipConfig } from 'knip';\nimport { compile } from 'svelte/compiler';\n\nexport default {\n  compilers: {\n    svelte: (source: string) => compile(source, {}).js.code,\n  },\n} satisfies KnipConfig;\n```\n\n#### Vue\n\nIn a Vue project, the compiler is automatically enabled. Override and use Vue's\nparser for better results if the built-in \"compiler\" is not enough:\n\n```ts\nimport type { KnipConfig } from 'knip';\nimport {\n  parse,\n  type SFCScriptBlock,\n  type SFCStyleBlock,\n} from 'vue/compiler-sfc';\n\nfunction getScriptBlockContent(block: SFCScriptBlock | null): string[] {\n  if (!block) return [];\n  if (block.src) return [`import '${block.src}'`];\n  return [block.content];\n}\n\nfunction getStyleBlockContent(block: SFCStyleBlock | null): string[] {\n  if (!block) return [];\n  if (block.src) return [`@import '${block.src}';`];\n  return [block.content];\n}\n\nfunction getStyleImports(content: string): string {\n  return [...content.matchAll(/(?<=@)import[^;]+/g)].join('\\n');\n}\n\nconst config = {\n  compilers: {\n    vue: (text: string, filename: string) => {\n      const { descriptor } = parse(text, { filename, sourceMap: false });\n      return [\n        ...getScriptBlockContent(descriptor.script),\n        ...getScriptBlockContent(descriptor.scriptSetup),\n        ...descriptor.styles.flatMap(getStyleBlockContent).map(getStyleImports),\n      ].join('\\n');\n    },\n  },\n} satisfies KnipConfig;\n\nexport default config;\n```\n\n## Tracking non-source files\n\nTo track any file extension that's not meant to compile to JavaScript, register\na no-op compiler:\n\n```ts title=\"knip.ts\"\nexport default {\n  compilers: { template: () => '' },\n};\n```\n\n[1]: #svelte\n[2]: #vue\n[3]: https://tsrx.dev\n[4]: #css\n[5]: #mdx\n\n<!-- File: packages/docs/src/content/docs/features/custom-elements.md (Tokens: ~767 | Category: anthropic-skill) -->\n---\ntitle: Custom Elements\ndescription: How Knip credits custom element classes registered via `customElements.define()` or Lit, FAST, Stencil and Catalyst decorators.\n---\n\nCustom elements are registered under a tag name. When such a class isn't\nreferenced elsewhere, Knip would report the export as unused. Instead, Knip\nrecognizes the registration and considers the class used.\n\nNative registration needs no configuration. Framework registrations are credited\nthrough their plugin, which is enabled when the framework is a dependency.\n\n## Native registration\n\nThe web standard `customElements.define()` credits the registered class:\n\n```ts\nexport class MyCard extends HTMLElement {}\n\ncustomElements.define('my-card', MyCard);\n```\n\nThe registry can be the global `customElements` — directly, through a `window`,\n`globalThis` or `self` prefix, or a local alias — a `CustomElementRegistry`\ninstance, or a shadow root's scoped registry:\n\n```ts\nconst registry = new CustomElementRegistry();\nregistry.define('my-card', MyCard);\n```\n\nA class can also register itself from a `static` block using `this`:\n\n```ts\nexport class MyCard extends HTMLElement {\n  static {\n    customElements.define('my-card', this);\n  }\n}\n```\n\n## Framework registration\n\n| Framework     | Plugin        | Registration                    | Imported from                                            |\n| ------------- | ------------- | ------------------------------- | -------------------------------------------------------- |\n| [Lit][1]      | [lit][2]      | `@customElement('tag')`         | `lit/decorators`, `lit-element`, `@lit/reactive-element` |\n| [FAST][3]     | [fast][4]     | `@customElement` or `.define()` | `@microsoft/fast-element`                                |\n| [Stencil][5]  | [stencil][6]  | `@Component({ tag })`           | `@stencil/core`                                          |\n| [Catalyst][7] | [catalyst][8] | `@controller`                   | `@github/catalyst`                                       |\n\nThe decorator counts only when imported from the framework. A locally defined or\ndifferently-imported decorator is ignored.\n\n### Lit\n\nA `@customElement('tag')` decorator credits the class when the matching plugin\nis enabled:\n\n```ts\nimport { LitElement } from 'lit';\nimport { customElement } from 'lit/decorators.js';\n\n@customElement('my-card')\nexport class MyCard extends LitElement {}\n```\n\n### FAST\n\n[FAST][3] also registers elements through a static `define()` or `defineAsync()`\nmethod. A class extending `FASTElement`, directly or through a mixin, is\ncredited when registered this way:\n\n```ts\nimport { FASTElement } from '@microsoft/fast-element';\n\nexport class MyCard extends FASTElement {}\n\nMyCard.define('my-card');\n```\n\n### Stencil\n\nA `@Component` decorator credits the class:\n\n```ts\nimport { Component } from '@stencil/core';\n\n@Component({ tag: 'my-card' })\nexport class MyCard {}\n```\n\n### Catalyst\n\nThe bare `@controller` decorator registers the element under a tag derived from\nthe class name:\n\n```ts\nimport { controller } from '@github/catalyst';\n\n@controller\nexport class MyCardElement extends HTMLElement {}\n```\n\n[1]: https://lit.dev\n[2]: ../reference/plugins/lit.md\n[3]: https://fast.design\n[4]: ../reference/plugins/fast.md\n[5]: https://stenciljs.com\n[6]: ../reference/plugins/stencil.md\n[7]: https://catalyst.rocks\n[8]: ../reference/plugins/catalyst.md\n\n<!-- File: packages/docs/src/content/docs/features/integrated-monorepos.md (Tokens: ~435 | Category: anthropic-skill) -->\n---\ntitle: Integrated Monorepos\ndescription: Configure Knip for repositories with a single `package.json` and many projects, like the Nx integrated monorepo style.\n---\n\nSome repositories have a single `package.json`, but consist of multiple projects\nwith configuration files across the repository. A good example is the [Nx\nintegrated monorepo style][1].\n\n:::tip\n\nAn integrated monorepo is a single workspace.\n\n:::\n\n## Entry Files\n\nThe default entrypoints files might not be enough. Here's an idea that might fit\nthis type of monorepo:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"{apps,libs}/**/src/index.{ts,tsx}\"],\n  \"project\": [\"{apps,libs}/**/src/**/*.{ts,tsx}\"]\n}\n```\n\n## Plugins\n\nLet's assume some of these projects are applications (\"apps\") which have their\nown ESLint configuration files and Cypress configuration and test files. This\nmay result in those files getting reported as unused, and consequently also the\ndependencies they import and refer to.\n\nIn that case, we could configure the ESLint and Cypress plugins like this:\n\n```json title=\"knip.json\"\n{\n  \"eslint\": {\n    \"config\": [\"{apps,libs}/**/.eslintrc.json\"]\n  },\n  \"cypress\": {\n    \"entry\": [\"apps/**/cypress.config.ts\", \"apps/**/cypress/e2e/*.spec.ts\"]\n  }\n}\n```\n\nAdapt the file patterns to your project, and the relevant `config` and `entry`\nfiles and dependencies should no longer be reported as unused.\n\n## Internal Workspace Dependencies\n\nA note about repositories with multiple `package.json` files and **internal**\nworkspace packages: it is recommended to list all dependencies in each consuming\n`package.json`, allowing Knip to do fine-grained reporting of both unused and\nunlisted dependencies.\n\nAn alternative is to `ignoreDependencies: [\"@internal/*\"]`.\n\n[1]: https://nx.dev/getting-started/tutorials/integrated-repo-tutorial\n\n<!-- File: packages/docs/src/content/docs/features/monorepos-and-workspaces.md (Tokens: ~1070 | Category: anthropic-skill) -->\n---\ntitle: Monorepos & Workspaces\ndescription: How Knip discovers and configures workspaces in package-based monorepos, with per-workspace options and the `--workspace` filter.\n---\n\nWorkspaces are handled out-of-the-box by Knip.\n\nWorkspaces are sometimes also referred to as package-based monorepos, or as\npackages in a monorepo. Knip uses the term workspace exclusively to indicate a\ndirectory that has a `package.json`.\n\n## Configuration\n\nHere's example configuration with custom `entry` and `project` patterns:\n\n```json title=\"knip.json\"\n{\n  \"workspaces\": {\n    \".\": {\n      \"entry\": \"scripts/*.js\",\n      \"project\": \"scripts/**/*.js\"\n    },\n    \"packages/*\": {\n      \"entry\": \"{index,cli}.ts\",\n      \"project\": \"**/*.ts\"\n    },\n    \"packages/cli\": {\n      \"entry\": \"bin/cli.js\"\n    }\n  }\n}\n```\n\n:::tip\n\nRun Knip without any configuration to see if and where custom `entry` and/or\n`project` files are necessary per workspace.\n\n:::\n\nEach workspace has the same [default configuration][1].\n\nThe root workspace is named `\".\"` under `workspaces` (like in the example\nabove).\n\n:::caution\n\nIn a project with workspaces, the `entry` and `project` options at the root\nlevel are ignored. Use the workspace named `\".\"` for those (like in the example\nabove).\n\n:::\n\n## Workspaces\n\nKnip reads workspaces from four possible locations:\n\n1. The `workspaces` array in `package.json` (npm, Bun, Yarn, Lerna)\n2. The `packages` array in `pnpm-workspace.yaml` (pnpm)\n3. The `workspaces.packages` array in `package.json` (legacy)\n4. The `workspaces` object in Knip configuration\n\nThe `workspaces` in Knip configuration (4) not already defined in the root\n`package.json` or `pnpm-workspace.yaml` (1, 2, 3) are added to the analysis.\n\n:::caution\n\nA workspace must have a `package.json` file.\n\n:::\n\nFor projects with only a root `package.json`, please see [integrated\nmonorepos][2].\n\n## Additional workspaces\n\nIf a workspace is not configured as such in `package.json#workspaces` (or\n`pnpm-workspace.yaml`) it can be added to the Knip configuration manually. Add\ntheir path to the `workspaces` configuration object the same way as\n`\"packages/cli\": {}` in the example above.\n\n## Source mapping\n\nSee [Source Mapping][3].\n\n## Additional options\n\nThe following options are available inside workspace configurations:\n\n- [ignore][4]\n- [ignoreBinaries][5]\n- [ignoreDependencies][6]\n- [ignoreIssues][7]\n- [ignoreMembers][8]\n- [ignoreUnresolved][9]\n- [includeEntryExports][10]\n\n[Plugins][11] can be configured separately per workspace.\n\nUse `--debug` for verbose output and see the workspaces Knip includes, their\nconfigurations, enabled plugins, glob options and resolved files.\n\n## Filter workspaces\n\nUse the `--workspace` (or `-W`) argument to select one or more workspaces:\n\n```sh\nknip --workspace packages/my-lib\n```\n\nThe filter supports multiple formats:\n\n```sh\nknip --workspace @myorg/my-lib     # Package name\nknip --workspace '@myorg/*'        # Package name glob\nknip --workspace packages/my-lib   # Directory path\nknip --workspace './apps/*'        # Directory glob\n```\n\nCombine selectors to include or exclude workspaces:\n\n```sh\nknip --workspace @myorg/* --workspace '!@myorg/legacy'\nknip --workspace './apps/*' --workspace '@shared/utils'\n```\n\nThis will include the target workspace(s), but also ancestor, dependency and\ndependent workspaces. For three reasons:\n\n- Ancestor workspaces may list dependencies in `package.json` the linted\n  workspace uses.\n- Dependency workspaces may provide configuration and source information used by\n  the linted workspace.\n- Dependent workspaces may reference exports from the linted workspace.\n\nTo lint the workspace in isolation, there are two options:\n\n- Combine the `workspace` argument with [strict production mode][12].\n- Run Knip from inside the workspace directory.\n\n[1]: ../overview/configuration.md#defaults\n[2]: ./integrated-monorepos.md\n[3]: ./source-mapping.md\n[4]: ../reference/configuration.md#ignore\n[5]: ../reference/configuration.md#ignorebinaries\n[6]: ../reference/configuration.md#ignoredependencies\n[7]: ../reference/configuration.md#ignoreissues\n[8]: ../reference/configuration.md#ignoremembers\n[9]: ../reference/configuration.md#ignoreunresolved\n[10]: ../reference/configuration.md#includeentryexports\n[11]: ../reference/configuration.md#plugins\n[12]: ./production-mode.md#strict-mode\n\n<!-- File: packages/docs/src/content/docs/features/production-mode.md (Tokens: ~698 | Category: anthropic-skill) -->\n---\ntitle: Production Mode\ndescription: Use `--production` and `--strict` with `!` entry patterns to lint only shipped code, ignoring tests, stories and config files.\n---\n\nThe default mode for Knip is comprehensive and targets all project code,\nincluding configuration files, test files, Storybook stories, and so on. Test\nfiles usually import production files. This prevents production files or their\nexports from being reported as unused, while sometimes both of them can be\ndeleted. Knip features a \"production mode\" to focus only on the code that you\nship.\n\n## Configuration\n\nTo tell Knip what is production code, add an exclamation mark behind each\n`pattern!` that represents production code:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts!\", \"build/script.js\"],\n  \"project\": [\"src/**/*.ts!\", \"build/*.js\"]\n}\n```\n\nDepending on file structure and enabled plugins, you might not need to modify\nyour configuration at all.\n\nRun Knip with the `--production` flag:\n\n```sh\nknip --production\n```\n\nHere's what's included in production mode:\n\n- Only `entry` and `project` patterns suffixed with `!`\n- Only production `entry` file patterns exported by plugins (such as Next.js and\n  Remix)\n- Only the `start` script (of `package.json#scripts`)\n- Ignore exports with the [`@internal` tag][1]\n\n:::note\n\nThe production run does not replace the default run. Depending on your needs you\ncan run either of them or both separately. Usually both modes can share the same\nconfiguration.\n\n:::\n\nTo see the difference between default and production mode in great detail, use\nthe `--debug` flag and inspect what entry and project files are used, and the\nplugins that are enabled. For instance, in production mode this shows that files\nsuch as tests and Storybook files (stories) are excluded from the analysis.\n\nIn case files like mocks and test helpers are reported as unused files, use\nnegated patterns to exclude those files in production mode:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts!\"],\n  \"project\": [\"src/**/*.ts!\", \"!src/test-helpers/**!\"]\n}\n```\n\nAlso see [configuring project files][2] to align `entry` and `project` with\nproduction mode.\n\n## Strict Mode\n\nIn production mode, only `dependencies` (not `devDependencies`) are considered\nwhen finding unused or unlisted dependencies.\n\nAdditionally, the `--strict` flag can be added to:\n\n- Verify isolation: workspaces should use strictly their own `dependencies`\n- Include required `peerDependencies` when finding unused or unlisted\n  dependencies\n- [Distinguish development-only type imports from types exposed to package\n  consumers][3]\n\n```sh\nknip --production --strict\n```\n\nUsing `--strict` implies `--production`, so the latter can be omitted.\n\n## Types\n\nAdd `--exclude types` if you don't want to include types in the report:\n\n```sh\nknip --production --exclude types\n```\n\n[1]: ../reference/jsdoc-tsdoc-tags.md#internal\n[2]: ../guides/configuring-project-files.md\n[3]: ../guides/handling-issues.mdx#production-types\n\n<!-- File: packages/docs/src/content/docs/features/reporters.md (Tokens: ~2704 | Category: anthropic-skill) -->\n---\ntitle: Reporters & Preprocessors\ndescription: Knip's built-in reporters (including the shape of `knip --reporter json` for scripts, CI and coding agents), plus custom reporters and preprocessors.\n---\n\n## Built-in Reporters\n\nKnip provides the following built-in reporters:\n\n- [`codeclimate`][1]\n- [`codeowners`][2]\n- `compact`\n- [`cycles`][3]\n- [`disclosure`][4]\n- [`github-actions`][5]\n- [`json`][6]\n- [`markdown`][7]\n- [`sarif`][8]\n- `symbols` (default)\n\nExample usage:\n\n```sh\nknip --reporter compact\n```\n\n### CodeClimate\n\nThe built-in `codeclimate` reporter generates output in the Code Climate Report\nJSON format. Example usage:\n\n```text\n$ knip --reporter codeclimate\n\n[\n  {\n    \"type\": \"issue\",\n    \"check_name\": \"Unused exports\",\n    \"description\": \"isUnused\",\n    \"categories\": [\"Bug Risk\"],\n    \"location\": {\n      \"path\": \"path/to/file.ts\",\n      \"positions\": {\n        \"begin\": {\n          \"line\": 6,\n          \"column\": 1\n        }\n      }\n    },\n    \"severity\": \"major\",\n    \"fingerprint\": \"e9789995c1fe9f7d75eed6a0c0f89e84\"\n  }\n]\n```\n\n### CODEOWNERS\n\nWhen a `.github/CODEOWNERS` file exists, each entry gains an `owners` array.\nPoint the reporter at a different path through [`--reporter-options`][9]:\n\n```sh\nknip --reporter json --reporter-options '{\"codeowners\":\"docs/CODEOWNERS\"}'\n```\n\n### Cycles\n\nA verbose, multi-line tree view of [circular dependencies][10]. Each file path\nis suffixed with the location of the import that continues the cycle. Each edge\nshows the import kind and specifier, descends one file per level, and closes\n(`↩`) back to the file it started from.\n\nUse `--cycles` to report only circular dependencies and `--reporter cycles` to\ndisplay them as a tree:\n\n```text\n$ knip --cycles --reporter cycles\n\nCircular dependencies (1)\n\nsrc/i18n/index.ts:1:28\n└── import ./middleware → src/i18n/middleware.ts:3:15\n    └── re-export ../core/i18n/handler → src/core/i18n/handler.ts:5:10\n        └── import ../../i18n → src/i18n/index.ts:1:28 ↩\n```\n\nKnip reports representative cycle paths found while walking the module graph.\nThis is not an exhaustive list of every possible simple cycle in a cyclic\nsubgraph, because that can produce a noisy and very large report. If the same\nfile participates in multiple distinct reported paths, each path is shown\nseparately.\n\nUse [`cycles.allow`][11] to accept known cycle paths.\n\nDynamic imports are ignored by default because they are commonly used to avoid\nsynchronous circular loads. Set [`cycles.dynamicImports`][11] to include them.\nRepeated starting imports are grouped under one heading.\n\nFor one line per cycle path, use `knip --cycles` with the default reporter. To\nreport unused code as well, [combine the issue-type shorthands][12].\n\nCycles are warnings by default. Set `\"rules\": { \"cycles\": \"error\" }` to make\nreported cycles cause a non-zero exit code.\n\n### Disclosure\n\nThis reporter is useful for sharing large reports. Groups of issues are rendered\nin a closed state initially. The reporter renders this:\n\n````text\n$ knip --reporter disclosure\n\n<details>\n<summary>Unused files (2)</summary>\n\n```\nunused.ts\ndangling.js\n```\n\n</details>\n\n<details>\n<summary>Unused dependencies (2)</summary>\n\n```\nmy-package     package.json:17:5\nunused-dep     package.json:20:5\n```\n\n</details>\n````\n\nThe above can be copy-pasted where HTML and Markdown is supported, such as a\nGitHub issue or pull request, and renders like so:\n\n<details>\n  <summary>Unused files (2)</summary>\n\n```\nunused.ts\ndangling.js\n```\n\n</details>\n\n<details>\n  <summary>Unused dependencies (2)</summary>\n\n```\nmy-package     package.json:17:5\nunused-dep     package.json:20:5\n```\n\n</details>\n\n### GitHub Actions\n\nUse the GitHub Actions reporter in a workflow for annotations in pull requests.\nExample usage:\n\n```sh\nknip --reporter github-actions\n```\n\nChanged files in pull requests will now contain inline annotations for lint\nfindings.\n\n### JSON\n\nThe `json` reporter prints machine-readable results for scripts, CI, and tools\n(including coding agents) to consume:\n\n```sh\nknip --reporter json\n```\n\nOutput is one line of JSON. Formatted here for readability:\n\n```json\n{\n  \"issues\": [\n    {\n      \"file\": \"src/legacy.ts\",\n      \"files\": [{ \"name\": \"src/legacy.ts\" }]\n    },\n    {\n      \"file\": \"src/math.ts\",\n      \"exports\": [{ \"name\": \"factorial\", \"line\": 12, \"col\": 14, \"pos\": 256 }],\n      \"types\": [{ \"name\": \"Radians\", \"line\": 20, \"col\": 13, \"pos\": 410 }]\n    },\n    {\n      \"file\": \"package.json\",\n      \"dependencies\": [{ \"name\": \"lodash\" }],\n      \"unlisted\": [{ \"name\": \"rimraf\" }]\n    }\n  ]\n}\n```\n\nThe top level is an object with a single `issues` array. Each element groups\nevery issue found in one file:\n\n| Field        | Type         | Notes                                               |\n| :----------- | :----------- | :-------------------------------------------------- |\n| `file`       | `string`     | Path relative to the working directory              |\n| `owners`     | `{ name }[]` | Code owners, only when a `CODEOWNERS` file is found |\n| _issue type_ | array        | One key per enabled issue type (see below)          |\n\nEach entry carries a key for **every enabled [issue type][10]**, so the keys are\nthe same across entries. An array is empty when that file has no issues of that\ntype. Drop a type's key by disabling it with [filters or rules][12].\n\nIssue-type items are objects with position info:\n\n| Field       | Type      | Notes                                          |\n| :---------- | :-------- | :--------------------------------------------- |\n| `name`      | `string`  | The unused symbol, dependency, file, or import |\n| `namespace` | `string?` | Set for namespace members                      |\n| `line`      | `number?` | 1-based line                                   |\n| `col`       | `number?` | 1-based column                                 |\n| `pos`       | `number?` | Character offset                               |\n\nSee [Issue types][10] for the full set of issue-type keys.\n\nFor a typed object instead of JSON to parse, write a [custom reporter][13].\nCoding agents can also call Knip through the [MCP server][14], which returns\nstructured results and configuration hints directly.\n\n### SARIF\n\nThe `sarif` reporter emits [SARIF 2.1.0][15] for code-scanning integrations:\n\n```sh\nknip --reporter sarif > knip.sarif\n```\n\nFor example, upload the report to GitHub Code Scanning after installing project\ndependencies:\n\n```yaml\npermissions:\n  contents: read\n  security-events: write\n\nsteps:\n  - uses: actions/checkout@v4\n  - run: pnpm exec knip --reporter sarif > knip.sarif\n  - if: always()\n    uses: github/codeql-action/upload-sarif@v4\n    with:\n      sarif_file: knip.sarif\n```\n\nThe upload step runs even when Knip finds issues and exits non-zero. GitHub Code\nScanning availability for private repositories depends on the repository's\nGitHub Code Security plan.\n\n### Markdown\n\nThe built-in `markdown` reporter output is meant to be saved to a Markdown file.\nThis allows following the changes in issues over time. It reports issues in\nMarkdown tables separated by issue types as headings, for example:\n\n```md\n# Knip report\n\n## Unused files (1)\n\n- src/unused.ts\n\n## Unlisted dependencies (2)\n\n| Name            | Location          | Severity |\n| :-------------- | :---------------- | :------- |\n| unresolved      | src/index.ts:8:23 | error    |\n| @org/unresolved | src/index.ts:9:23 | error    |\n\n## Unresolved imports (1)\n\n| Name         | Location           | Severity |\n| :----------- | :----------------- | :------- |\n| ./unresolved | src/index.ts:10:12 | error    |\n```\n\n## Custom Reporters\n\nWhen the provided built-in reporters are not sufficient, a custom local reporter\ncan be implemented or an external reporter can be used. Multiple reporters can\nbe used at once by repeating the `--reporter` argument.\n\nThe results are passed to the function from its default export and can be used\nto write issues to `stdout`, a JSON or CSV file, or sent to a service. It\nsupports a local JavaScript or TypeScript file or an external dependency.\n\n### Local\n\nThe default export of the reporter should be a function with this interface:\n\n```ts\ntype Reporter = (options: ReporterOptions) => void;\n\ntype ReporterOptions = {\n  report: Report;\n  issues: Issues;\n  counters: Counters;\n  configurationHints: ConfigurationHints;\n  isDisableConfigHints: boolean;\n  isTreatConfigHintsAsErrors: boolean;\n  cwd: string;\n  isProduction: boolean;\n  isShowProgress: boolean;\n  options: string;\n};\n```\n\nThe data can then be used to write issues to `stdout`, a JSON or CSV file, or\nsent to a service.\n\nHere's a most minimal reporter example:\n\n```ts title=\"./my-reporter.ts\"\nimport type { Reporter } from 'knip';\n\nconst reporter: Reporter = function (options) {\n  console.log(options.issues);\n  console.log(options.counters);\n};\n\nexport default reporter;\n```\n\nExample usage:\n\n```sh\nknip --reporter ./my-reporter.ts\n```\n\n### External\n\nPass `--reporter [pkg-name]` to use an external reporter. The default exported\nfunction of the `main` script (default: `index.js`) will be invoked with the\n`ReporterOptions`, just like a local reporter.\n\n## Preprocessors\n\nA preprocessor is a function that runs after the analysis is finished. It\nreceives the results from the analysis and should return data in the same\nshape/structure (unless you pass it to only your own reporter).\n\nThe data goes through the preprocessors before the final data is passed to the\nreporters. There are no built-in preprocessors. Just like reporters, use e.g.\n`--preprocessor ./my-preprocessor` from the command line (can be repeated).\n\nThe default export of the preprocessor should be a function with this interface:\n\n```ts\ntype Preprocessor = (options: ReporterOptions) => ReporterOptions;\n```\n\nLike reporters, you can use local JavaScript or TypeScript files and external\nnpm packages as preprocessors.\n\nExample preprocessor:\n\n```ts title=\"./preprocess.ts\"\nimport type { Preprocessor } from 'knip';\n\nconst preprocess: Preprocessor = function (options) {\n  // modify options.issues and options.counters\n  return options;\n};\n\nexport default preprocess;\n```\n\nExample usage:\n\n```sh\nknip --preprocessor ./preprocess.ts\n```\n\nPreprocessors can also be configured in the Knip configuration file:\n\n```json title=\"knip.json\"\n{\n  \"preprocessor\": \"./preprocess.ts\"\n}\n```\n\n[1]: #codeclimate\n[2]: #codeowners\n[3]: #cycles\n[4]: #disclosure\n[5]: #github-actions\n[6]: #json\n[7]: #markdown\n[8]: #sarif\n[9]: ../reference/cli.md#--reporter-options-json\n[10]: ../reference/issue-types.md\n[11]: ../reference/configuration.md#cycles\n[12]: ./rules-and-filters.md\n[13]: #custom-reporters\n[14]: ../reference/integrations.md\n[15]: https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html\n\n<!-- File: packages/docs/src/content/docs/features/rules-and-filters.md (Tokens: ~936 | Category: anthropic-skill) -->\n---\ntitle: Rules & Filters\ndescription: Customize Knip's output with `--include`/`--exclude` filters, shorthand flags and `rules` to set issue types to error, warn or off.\n---\n\nUse rules or filters to customize Knip's output. This has various use cases, a\nfew examples:\n\n- Temporarily focus on a specific issue type.\n- You don't want to see unused `type`, `interface` and `enum` exports reported.\n- Specific issue types should be printed, but not counted against the total\n  error count.\n\nIf you're looking to handle one-off exceptions, also see [JSDoc tags][1].\n\n## Filters\n\nYou can `--include` or `--exclude` any of the reported issue types to slice &\ndice the report to your needs. Alternatively, they can be added to the\nconfiguration (e.g. `\"exclude\": [\"dependencies\"]`).\n\nUse `--include` to report only specific issue types. The following example\ncommands do the same:\n\n```sh\nknip --include files --include dependencies\nknip --include files,dependencies\n```\n\nOr the other way around, use `--exclude` to ignore the types you're not\ninterested in:\n\n```sh\nknip --include files --exclude enumMembers,duplicates\n```\n\nThe `nsExports` and `nsTypes` types are [off by default][2]. Including only\nthose _adds_ them to the default report, rather than narrowing it to just those.\n\n`cycles` is also off by default. `--include cycles` (or `\"include\": [\"cycles\"]`\nin configuration) reports only circular dependencies. Use it with the [cycles\nreporter][3] for a detailed tree view.\n\nAlso see the [list of issue types][4].\n\n### Shorthands\n\nKnip has shortcuts to report only specific issue types.\n\n1. The `--dependencies` flag includes:\n   - `dependencies` (and `devDependencies` + `optionalPeerDependencies`)\n   - `unlisted`\n   - `binaries`\n   - `unresolved`\n   - `catalog`\n   - `catalogReferences`\n\n2. The `--exports` flag includes:\n   - `exports`\n   - `types`\n   - `enumMembers`\n   - `namespaceMembers`\n   - `duplicates`\n\n3. The `--files` flag is a shortcut to report only unused files.\n\n4. The `--cycles` flag is a shortcut to report only circular dependencies.\n\nCombine shorthands to report the default issue types plus circular dependencies:\n\n```sh\nknip --dependencies --exports --files --cycles\n```\n\n## Rules\n\nUse `rules` in the configuration to customize the issue types that count towards\nthe total error count, or to exclude them altogether.\n\n| Value     | Default | Printed | Counted | Description                       |\n| :-------- | :-----: | :-----: | :-----: | :-------------------------------- |\n| `\"error\"` |   ✓ ¹   |    ✓    |    ✓    | Similar to the `--include` filter |\n| `\"warn\"`  |    -    |    ✓    |    -    | Printed in faded/gray color       |\n| `\"off\"`   |    -    |    -    |    -    | Similar to the `--exclude` filter |\n\nExample:\n\n```json title=\"knip.json\"\n{\n  \"rules\": {\n    \"files\": \"warn\",\n    \"duplicates\": \"off\"\n  }\n}\n```\n\nNotes:\n\n- ¹ Exception: the `cycles` issue type is a warning by default.\n- If the `dependencies` issue type is included, the `devDependencies` and\n  `optionalPeerDependencies` types can still be set to `\"warn\"` separately.\n- The rules are modeled after the ESLint `rules` configuration, and could be\n  extended in the future.\n\nAlso see the [issue types overview][4].\n\n## Rules or filters?\n\nFilters are meant to be used as command-line flags, rules allow for more\nfine-grained configuration.\n\n- Rules are more fine-grained since they also have \"warn\".\n- Rules could be extended in the future.\n- Filters can be set in configuration and from CLI (rules only in\n  configuration).\n- Filters have shorthands (rules don't have this).\n\n[1]: ../reference/jsdoc-tsdoc-tags.md\n[2]: ../guides/namespace-imports.md\n[3]: ./reporters.md#cycles\n[4]: ../reference/issue-types.md\n\n<!-- File: packages/docs/src/content/docs/features/script-parser.md (Tokens: ~1385 | Category: anthropic-skill) -->\n---\ntitle: Script Parser\ndescription: How Knip statically parses shell scripts and CLI arguments in `package.json`, plugins and source code to find entry files and dependencies.\n---\n\nKnip parses shell commands and scripts to find additional dependencies, entry\nfiles and configuration files in various places:\n\n- In [`package.json`][1]\n- In [CLI arguments][2]\n- In [scripts][3]\n- In [source code][4]\n\nShell scripts are parsed and statically analyzed, but they're not executed.\n\n## package.json\n\nThe `main`, `bin`, `exports` and `scripts` fields may contain entry files. Let's\ntake a look at this example:\n\n```json title=\"package.json\"\n{\n  \"name\": \"my-package\",\n  \"main\": \"index.js\",\n  \"exports\": {\n    \"./lib\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./dist/index.cjs\"\n    }\n  },\n  \"bin\": {\n    \"program\": \"bin/cli.js\"\n  },\n  \"scripts\": {\n    \"build\": \"rollup src/entry.ts\",\n    \"start\": \"node --loader tsx server.ts\"\n  }\n}\n```\n\nFrom this example, Knip automatically adds the following files as entry files:\n\n- `index.js`\n- `./dist/index.mjs`\n- `./dist/index.cjs`\n- `bin/cli.js`\n- `src/entry.ts`\n- `server.ts`\n\n### Excluded files\n\nKnip would not add the `exports` if the `dist` folder is matching a pattern in a\nrelevant `.gitignore` file or `ignore` option.\n\nKnip does not add scripts without a standard extension. For instance, the\n`bin/tool` file might be a valid executable for Node.js, but wouldn't be added\nor parsed by Knip.\n\n### CLI Arguments\n\nWhen parsing the `scripts` of `package.json` and other files, Knip detects\nvarious types of inputs. Some examples:\n\n- The first positional argument is usually an entry file\n- Configuration files are often in the `-c` or `--config` argument\n- The `--require`, `--loader` or `--import` arguments are often dependencies\n\n```json\n{\n  \"name\": \"my-lib\",\n  \"scripts\": {\n    \"start\": \"node --import tsx/esm run.ts\",\n    \"bundle\": \"tsup -c tsup.lib.config.ts\",\n    \"type-check\": \"tsc -p tsconfig.app.json\"\n  }\n}\n```\n\nThe `\"start\"` script will have `tsx` marked as a referenced dependency, and adds\n`run.ts` as an entry file.\n\nAdditionally, the following files are detected as configuration files:\n\n- `tsup.lib.config.ts` - to be handled by the tsup plugin\n- `tsconfig.app.json` - to be handled by the TypeScript plugin\n\nSuch executables and their arguments are all defined in plugins separately for\nfine-grained results.\n\n## Scripts\n\nPlugins may also use the script parser to extract entry files and dependencies\nfrom commands. A few examples:\n\n- GitHub Actions: workflow files may contain `run` commands (e.g.\n  `.github/workflows/ci.yml`)\n- Husky & Lefthook: Git hooks such as `.git/hooks/pre-push` contain scripts;\n  also `lefthook.yml` has `run` commands\n- Lint Staged: configuration values are all commands\n- Nx: task executors and `nx:run-commands` executors in `project.json` contains\n  scripts\n- Release It: `hooks` contain commands\n\nPlugins can also return configuration files. Some examples:\n\n- The Angular plugin detects `options.tsConfig` as a TypeScript config file\n- The GitHub Actions plugin parses `run` commands which may contain\n  configuration file paths\n\n## Source Code\n\nWhen Knip is walking the abstract syntax trees (ASTs) of JavaScript and\nTypeScript source code files, it looks for imports and exports. But there's a\nfew more (rather obscure) things that Knip detects in the process. Below are\nexamples of additional scripts Knip parses to find entry files and dependencies.\n\n### bun\n\nIf the `bun` dependency is imported in source code, Knip considers the contents\nof `$` template tags to be scripts:\n\n```ts\nimport { $ } from 'bun';\nawait $`bun boxen I ❤ unicorns`;\nawait $`boxen I ❤ unicorns`;\n```\n\nParsing the script results in the `boxen` binary (the `boxen-cli` dependency) as\nreferenced (twice).\n\n### execa\n\nIf the `execa` dependency is imported in source code, Knip considers the\ncontents of `$` template tags to be scripts:\n\n```ts\nawait $({ stdio: 'inherit' })`c8 node hydrate.js`;\n```\n\nParsing the script results in `hydrate.js` added as an entry file and the `c8`\nbinary/dependency as referenced. The `execa()`, `execaSync()`, `execaCommand()`\nand `execaCommandSync()` call forms are parsed the same way.\n\n### zx\n\nIf the `zx` dependency is imported in source code, Knip considers the contents\nof `$` template tags to be scripts:\n\n```ts\nawait $`node scripts/parse.js`;\n```\n\nThis will add `scripts/parse.js` as an entry file.\n\n### child\\_process\n\nIf `node:child_process` is imported in source code, Knip parses the command in\n`exec`/`execSync` calls and the executable (with its arguments) in\n`spawn`/`spawnSync`/`execFile`/`execFileSync` calls:\n\n```ts\nimport { execSync, execFile } from 'node:child_process';\nexecSync('eslint --cache');\nexecFile('boxen', ['I ❤ unicorns']);\n```\n\nThis marks the `eslint` and `boxen` binaries as referenced. An inline\n`path.join(__dirname, …)` argument to `spawn`, `execFile` or `fork` is added as\nan entry file instead.\n\n### nano-spawn\n\nIf `nano-spawn` is imported in source code, Knip parses the executable and its\narguments:\n\n```ts\nimport spawn from 'nano-spawn';\nawait spawn('gsutil', ['cp', './file.txt', 'gs://bucket/']);\n```\n\nThis marks the `gsutil` binary as referenced.\n\n[1]: #packagejson\n[2]: #cli-arguments\n[3]: #scripts\n[4]: #source-code\n\n<!-- File: packages/docs/src/content/docs/features/source-mapping.md (Tokens: ~960 | Category: anthropic-skill) -->\n---\ntitle: Source Mapping\ndescription: How Knip maps build artifacts in `dist`/`outDir` back to their original source files using `tsconfig.json` to avoid false positives.\n---\n\nKnip is mostly interested in source code. Analyzing build artifacts hurts\nperformance and often leads to false positives, as they potentially contain\nbundled code and unresolvable imports.\n\nThat's why Knip tries to map such build artifacts back to their original source\nfiles and analyze those instead. This is done based on `tsconfig.json` settings.\n\n## Example 1: package.json\n\nLet's look at an example case with `package.json` and `tsconfig.json` files, and\nsee how \"dist\" files are mapped to \"src\" files.\n\n```jsonc title=\"package.json\"\n{\n  \"name\": \"my-workspace\",\n  \"main\": \"index.js\",\n  \"exports\": {\n    \".\": \"./src/entry.js\",\n    \"./feat\": \"./lib/feat.js\",\n    \"./public\": \"./dist/app.js\",\n    \"./public/*\": \"./dist/*.js\",\n    \"./public/*.js\": \"./dist/*.js\",\n    \"./dist/internal/*\": null,\n  },\n}\n```\n\nWith this TypeScript configuration:\n\n```json title=\"tsconfig.json\"\n{\n  \"compilerOptions\": {\n    \"baseUrl\": \"src\",\n    \"outDir\": \"dist\"\n  }\n}\n```\n\n- `./src/entry.js` is not in an `outDir` folder, so it's added as an entry file\n- `./lib/feat.js` is not in an `outDir` folder, so it's added as an entry file\n- `./dist/app.js` is in a `dist` folder and mapped to `./src/app.{js,ts}` (¹)\n- `./dist/*.js` is in a `dist` folder and mapped to `./src/**/*.{js,ts}` (¹)\n- `./dist/internal/*` is translated to `./dist/internal/**` and files in this\n  directory and deeper are ignored when globbing entry files\n\n(¹) full extensions list is actually: `js`, `mjs`, `cjs`, `jsx`, `ts`, `tsx`,\n`mts`, `cts`\n\nIn `--debug` mode, look for \"Source mapping\" to see this in action.\n\n:::tip\n\nUsing `./dist/*.js` means that all files matching `./src/**/*.{js,ts}` are added\nas entry files. By default, unused exports of entry files are not reported. Use\n[includeEntryExports][1] to include them.\n\n:::\n\n## Example 2: monorepo\n\nLet's say we have this module in a monorepo that imports `helper` from another\nworkspace in the same monorepo:\n\n```ts title=\"index.js\"\nimport { helper } from '@org/shared';\n```\n\nThe target workspace `@org/shared` has this `package.json`:\n\n```json title=\"package.json\"\n{\n  \"name\": \"@org/shared\",\n  \"main\": \"dist/index.js\"\n}\n```\n\nThe module resolver will resolve `@org/shared` to `dist/index.js`. That file is\nusually compiled and git-ignored, while Knip wants the source file instead.\n\n:::tip\n\nYou may need to compile build artifacts to `outDir` first before Knip can\nsuccessfully apply source mapping for internal references in a monorepo.\n\n:::\n\nIf the target workspace has a `tsconfig.json` file with an `outDir` option, Knip\nwill try to map the \"dist\" file to the \"src\" file. Then if `src/index.ts`\nexists, Knip will use that file instead of `dist/index.js`.\n\nCurrently this only works based on `tsconfig.json`, in the future more source\nmappings may be added.\n\n## Example 3: source conditions\n\nSource-first monorepos may expose source files directly through a custom\ncondition in `package.json#exports` or `#imports` maps:\n\n```json title=\"package.json\"\n{\n  \"name\": \"@org/shared\",\n  \"exports\": {\n    \".\": {\n      \"@org/source\": \"./src/index.ts\",\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    }\n  }\n}\n```\n\nWhen module resolution fails because the targets aren't built, Knip falls back\nto the first conditional target of the workspace package that exists on disk,\nregardless of the condition's name. No build step or configuration required.\n\n[1]: ../reference/configuration.md#includeentryexports\n\n<!-- File: packages/docs/src/content/docs/guides/adopt-gradually.md (Tokens: ~886 | Category: anthropic-skill) -->\n---\ntitle: Adopt Knip gradually\ndescription: Roll Knip out on a large or legacy codebase without trying to reach zero on day one. Baseline, focus one issue type at a time, then ratchet with rules.\n---\n\nOn a large or legacy codebase the first run can report a lot. Reaching zero in\none sitting is then the wrong goal. Get a trustworthy signal first, then ratchet\nthe codebase toward clean and keep it there.\n\n## Actionable baseline\n\nMost of the noise on a first run comes from gaps in what Knip can reach: a\ndependency that Knip does not have a plugin for yet, an entry point it can't\nresolve, a phantom dependency. Fix the gaps before you delete anything:\n\n- Address [configuration hints][1].\n- Tune [entry and project files][2] so Knip analyzes the right set of files.\n- Tune configuration for your tools' [plugins][3].\n\nRead the output from the top. One unused file hides its exports and\ndependencies, so files come first.\n\nOnce the report reflects real findings instead of gaps, you have an actionable\nbaseline.\n\n## Focus one issue type at a time\n\nDon't fix everything at once. Narrow the report with [filters][4]:\n\n```sh\nknip --files        # unused files only (the major cascade!)\nknip --dependencies # then dependencies\nknip --exports      # then exports and types\n```\n\nClear one type, commit, move to the next.\n\n## Stage by rules\n\n[Rules][5] set a severity per issue type. Start by setting all types to\n`\"warn\"`, and then the types you've cleaned to `\"error\"`. Warnings are printed\nin gray, and they don't fail the run. Example:\n\n```json title=\"knip.json\"\n{\n  \"rules\": {\n    \"files\": \"error\",\n    \"dependencies\": \"error\",\n    \"exports\": \"warn\",\n    \"duplicates\": \"off\"\n  }\n}\n```\n\nAs each `\"warn\"` type reaches zero, set it to `\"error\"`. Keep iterating and\nprune the codebase to perfection.\n\n## Gate CI without blocking the team\n\nAdd Knip to [CI][6] as soon as you have a baseline, so new clutter is caught in\nreview. A few ways to stage it:\n\n- Mark cleaned types `\"error\"` and the rest `\"warn\"`, so CI fails only on the\n  types you've finished.\n- Workspace by workspace: in a [monorepo][7], scope passes with `--workspace`\n  (accepts multiple workspaces and glob patterns).\n- Production first: [`--production`][8] limits analysis to shipped code, so you\n  can clean what matters most and defer tests and tooling.\n- Set a budget, so CI fails only when the count exceeds the number (e.g. `knip\n--max-issues 50`). This blocks regressions while you burn down the rest.\n- Run report-only with [`--no-exit-code`][9] while you're still triaging.\n\n## Suppress only what's justified\n\nWhen something is genuinely fine as-is, prefer a specific, documented signal\nover a blanket `ignore`, for example:\n\n- tag an export with e.g. [`@lintignore` or `@internal`][10]\n- use [`ignoreExportsUsedInFile`][11] for internal-only exports\n- list known exceptions in [`ignoreDependencies`][12]\n\n[Resolving reported issues][13] covers the right tool for each case.\n\n[1]: ../reference/configuration-hints.md\n[2]: ./configuring-project-files.md\n[3]: ../explanations/plugins.md\n[4]: ../features/rules-and-filters.md#filters\n[5]: ../features/rules-and-filters.md#rules\n[6]: ./using-knip-in-ci.md\n[7]: ../features/monorepos-and-workspaces.md\n[8]: ../features/production-mode.md\n[9]: ../reference/cli.md#--no-exit-code\n[10]: ../reference/jsdoc-tsdoc-tags.md\n[11]: ../reference/configuration.md#ignoreexportsusedinfile\n[12]: ../reference/configuration.md#ignoredependencies\n[13]: ./handling-issues.mdx\n\n<!-- File: packages/docs/src/content/docs/guides/configuring-project-files.md (Tokens: ~1302 | Category: anthropic-skill) -->\n---\ntitle: Configuring Project Files\ndescription: How to set Knip's `entry` and `project` file patterns, use negations and production mode, and when to reach for `ignore`.\n---\n\nThe `entry` and `project` file patterns are the first and most important\noptions. Getting those right is essential to help you delete more code and make\nKnip faster:\n\n- Start with defaults. Only add targeted `entry` overrides when needed.\n- Use `project` patterns (with negations) to define the scope for Knip.\n- Use production mode to exclude tests and other non-production files.\n- Use `ignore` only to suppress issues in specific files; it does not exclude\n  files from analysis.\n\nLet's dive in and expand on all of these.\n\n## Entry files\n\nAvoid adding too many files as `entry` files:\n\n1. Knip does not report [unused exports][1] in entry files by default.\n2. Proper `entry` and `project` patterns allow Knip to find unused files and\n   exports.\n\n## Unused files\n\nFiles are reported as unused if they are in the set of `project` files, but are\nnot resolved from the `entry` files:\n\n```\nunused files = project files - (entry files + resolved files)\n```\n\nSee [entry files][2] to see where Knip looks for entry files. Fine-tune `entry`\nand adjust `project` to fit your codebase.\n\n:::tip\n\nUse negated `project` patterns to precisely include/exclude files for unused\nfiles detection.\n\nUse `ignore*` to suppress specific issues in matching files; it does not exclude\nfiles from analysis.\n\n:::\n\n## Negated patterns\n\nWhen there are too many files in the analysis, start here.\n\nFor instance, routes are entry files except those prefixed with an underscore:\n\n```json\n{\n  \"entry\": [\"src/routes/*.ts\", \"!src/routes/_*.ts\"]\n}\n```\n\nSome files are not part of your source and are reported as unused (false\npositives)? Use negated `project` patterns:\n\n```json\n{\n  \"entry\": [\"src/index.ts\"],\n  \"project\": [\"src/**/*.ts\", \"!src/exclude/**\"]\n}\n```\n\n❌   Don't use `ignore` for generated artifacts:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts\", \"scripts/*.ts\"],\n  \"ignore\": [\"build/**\", \"dist/**\", \"src/generated.ts\"]\n}\n```\n\n✅   Do define your project boundaries:\n\n```json title=\"knip.json\"\n{\n  \"entry\": [\"src/index.ts\", \"scripts/*.ts\"],\n  \"project\": [\"src/**\", \"scripts/**\"],\n  \"ignore\": [\"src/generated.ts\"]\n}\n```\n\nWhy this is better:\n\n- `project` defines what belongs to the codebase, so build outputs are excluded\n  from analysis and unused file detection\n- `ignore` is for the few files that should be analyzed but contain exceptions\n- Improves performance by analyzing fewer files\n\n## Ignore issues in specific files\n\nUse `ignore` when a specific analyzed file is not handled properly by Knip or\nintentionally contains unused exports (e.g. generated files exporting\n\"everything\"):\n\n```json\n{\n  \"entry\": [\"src/index.ts\"],\n  \"project\": [\"src/**/*.ts\"],\n  \"ignore\": [\"src/generated.ts\"]\n}\n```\n\nAlso see [ignoreExportsUsedInFile][3] for a more targeted approach.\n\n## Production Mode\n\nDefault mode includes tests and other non-production files in the analysis. To\nfocus on production code, use [production mode][4].\n\nDon't try to exclude tests via `ignore` or negated `project` patterns. That's\ninefficient and ineffective due to entries added by plugins. Use production mode\ninstead.\n\n❌   Don't do this:\n\n```json\n{\n  \"ignore\": [\"**/*.test.js\"]\n}\n```\n\nWhy not: `ignore` hides issues from the report; it does not exclude files from\nanalysis.\n\n❌   Also don't do this:\n\n```json\n{\n  \"entry\": [\"index.ts\", \"!**/*.test.js\"]\n}\n```\n\nWhy not: plugins add test files as `entry` files; you can't and shouldn't\noverride that globally.\n\n❌   Or this:\n\n```json\n{\n  \"project\": [\"**/*.ts\", \"!**/*.spec.ts\"]\n}\n```\n\nWhy not: `project` is for unused file detection; negating test files is\nineffective because they are `entry` files.\n\n✅   Do this instead:\n\n```shell\nknip --production\n```\n\nTo fine-tune the resulting production file set, for instance to exclude test\nhelper files that still show as unused, use the exclamation mark suffix on\nproduction patterns:\n\n```json\n{\n  \"entry\": [\"src/index.ts!\"],\n  \"project\": [\"src/**/*.ts!\", \"!src/test-helpers/**!\"]\n}\n```\n\nRemember to keep adding the exclamation mark `suffix!` for production file\npatterns.\n\n:::tip\n\nUse the exclamation mark (`!`) on both ends (`!`) to exclude files in production\nmode.\n\n:::\n\n## Defaults & Plugins\n\nTo reiterate, the default `entry` and `project` files for each workspace:\n\n```json\n{\n  \"entry\": [\n    \"{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\",\n    \"src/{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}\"\n  ],\n  \"project\": [\"**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}!\"]\n}\n```\n\nNext to this, there are other places where [Knip looks for entry files][2].\n\nAdditionally, [plugins have plenty of entry files configured][5] that are\nautomatically added as well.\n\n[1]: ../typescript/unused-exports.md\n[2]: ../explanations/entry-files.md\n[3]: ../reference/configuration.md#ignoreexportsusedinfile\n[4]: ../features/production-mode.md\n[5]: ../explanations/plugins.md#entry-files\n\n<!-- File: packages/docs/src/content/docs/guides/contributing.md (Tokens: ~227 | Category: anthropic-skill) -->\n---\ntitle: Contributing to Knip\ndescription: Ways to contribute to Knip, including filing reproductions, opening pull requests, and writing a plugin.\n---\n\nHere are some ways to contribute to Knip:\n\n- Spread the word!\n- [Star the project][1]\n- [File an issue with a reproduction][2]\n- [Pull requests are welcome][3]\n\n[Writing a plugin][4] is a great and fun way to get started.\n\nThe [CONTRIBUTING.md][3] and [DEVELOPMENT.md][5] guides should get you up and\nrunning quickly.\n\nThe main goal of Knip is to keep projects clean & tidy. Everything that\ncontributes to that goal is welcome!\n\n[1]: https://github.com/webpro-nl/knip\n[2]: ./issue-reproduction.md\n[3]: https://github.com/webpro-nl/knip/blob/main/.github/CONTRIBUTING.md\n[4]: ../writing-a-plugin/index.md\n[5]: https://github.com/webpro-nl/knip/blob/main/.github/DEVELOPMENT.md\n\n<!-- File: packages/docs/src/content/docs/guides/issue-reproduction.md (Tokens: ~958 | Category: anthropic-skill) -->\n---\ntitle: Issue Reproduction\ndescription: How to create a minimal reproduction for a Knip bug or false positive using CodeSandbox, StackBlitz, a repo, or a test fixture.\n---\n\nIf you encounter an issue or false positives when using Knip, you can [open an\nissue on GitHub][1]. This will help you in your project, and will also improve\nKnip for everyone else!\n\nThink of Knip as a kitchen sink, it handles a large amount of projects and\nconfigurations, and your project is different from all others. Many factors may\ninfluence the issue at hand, such as:\n\n- Code syntax, import and export structure in source files\n- Dependencies, scripts and entry files in `package.json`\n- TypeScript configuration in `tsconfig.json`\n- Enabled plugins and related configuration files\n- Dependent or depending workspaces in a monorepo\n- Knip configuration in `knip.json`\n\n## Keep it minimal\n\nCreate the minimum of source code and configuration with a few files to\nreproduce and demonstrate the issue. Having this as a basis has many benefits:\n\n- Minimize barriers and unrelated contextual overhead\n- Optimize shared understanding of the situation\n- Serves as a \"contract\" to fix the actual issue\n- Files serve as a fixture to the project\n\nProviding this with an issue description will help us help you and improve the\nchances the issue can be looked into efficiently and in a timely manner.\n\nUseful **complements** to a minimal reproduction might include:\n\n- Screenshots, videos, code snippets or log output\n- Links to an existing project repository\n- Applications scaffolded by tools like Angular or Svelte CLI\n\n## Before opening an issue\n\nBefore opening an issue, please make sure you:\n\n- are using the latest version\n- have read the relevant documentation\n- have searched [existing issues][1]\n- have checked the list of [known issues][2]\n\nPlease file only a single issue at a time, so each of them can be labeled and\ntracked separately.\n\nThere is no need to open an issue if you're going to submit a pull request to\nclose it right away anyway. In that case it's preferred to keep things central\nin either an issue or pull request.\n\n## Templates\n\nA convenient way to create a minimal reproduction is by starting with one of\nthese templates in CodeSandbox or StackBlitz:\n\n| Template |                  |                 |\n| :------- | ---------------- | --------------- |\n| Basic    | [CodeSandbox][3] | [StackBlitz][4] |\n| Monorepo | [CodeSandbox][5] | [StackBlitz][6] |\n\nShoutout to [CodeSandbox][7] and [StackBlitz][8] for generously providing these\nfree dev containers!\n\n## Alternatives\n\nOther solutions to share a minimal and reproducible case may work well too,\nincluding:\n\n- A public repository on e.g. GitHub or GitLab.\n- A pull request with a new [test][9] and/or [fixture folder][10].\n\nThe goal is to have an easy and common understanding and reproduction. If you're\nunable to create a reproduction using one of the methods described then please\nclearly explain this in the issue or [contact me][11].\n\n## Pull Request\n\nThe optimal way is to add fixtures and failing tests to the Knip repository, and\nopen a pull request to discuss the issue! Also see [instructions for\ndevelopment][12].\n\n[1]: https://github.com/webpro-nl/knip/issues?q=is%3Aissue\n[2]: https://knip.dev/reference/known-issues\n[3]: https://codesandbox.io/p/devbox/github/webpro-nl/knip/main/templates/issue-reproduction/basic\n[4]: https://stackblitz.com/github/webpro-nl/knip/tree/main/templates/issue-reproduction/basic\n[5]: https://codesandbox.io/p/devbox/github/webpro-nl/knip/main/templates/issue-reproduction/monorepo\n[6]: https://stackblitz.com/github/webpro-nl/knip/tree/main/templates/issue-reproduction/monorepo\n[7]: https://codesandbox.io\n[8]: https://stackblitz.com\n[9]: https://github.com/webpro-nl/knip/blob/main/.github/DEVELOPMENT.md#tests\n[10]: https://github.com/webpro-nl/knip/tree/main/packages/knip/fixtures\n[11]: https://github.com/webpro\n[12]: https://github.com/webpro-nl/knip/blob/main/.github/DEVELOPMENT.md\n\n<!-- File: packages/docs/src/content/docs/guides/namespace-imports.md (Tokens: ~770 | Category: anthropic-skill) -->\n---\ntitle: Namespace Imports\ndescription: How Knip handles exports used through `import * as NS` namespace imports, its usage heuristic, and the `nsExports` and `nsTypes` issue types.\n---\n\nThe intention of exports used through namespace imports may not always be clear\nto Knip. Here's a guide to better understand how Knip handles such exports.\n\n## Example\n\nWe start off by having two exports:\n\n```ts title=\"my-namespace.js\"\nexport const version = 'v5';\nexport const getRocket = () => '🚀';\n```\n\nThe next snippet shows how to import all the exports above on a namespace. All\nexports of the `my-namespace.js` module will be members on the `NS` object:\n\n```ts title=\"my-module.ts\"\nimport * as NS from './my-namespace.js';\nimport send from 'stats';\nsend(NS);\n```\n\nThe intention of export usage is not always clear. In the example above is\n`version` or `getRocket` used? We're not sure, but we _probably_ don't want them\nto be reported as unused. The same goes for the next example:\n\n```ts title=\"my-module.ts\"\nimport * as NS from './my-namespace.js';\n\nexport { NS };\n```\n\nIf this is all usage of the `NS` namespace object, we also don't know whether\nindividual exports like `version` or `getRocket` will be used. However, if at\nleast one reference to a property such as `NS.version` is found, then the\nindividual exports are considered separately again and `getRocket` will be\nmarked as unused:\n\n```ts title=\"index.ts\"\nimport { NS } from './my-module.js';\n\nconst version = NS.version;\n```\n\n## The default heuristic\n\nKnip uses the following heuristic to determine which of the individual exports\nare used:\n\n- If there's one or more references to the import namespace object, but without\n  any property access, all exports on that namespace are considered used.\n- Otherwise, exports are considered separately.\n\nBelow are a few more examples, and a way to disable this default behavior.\n\n## Examples\n\nLet's take a look at more examples:\n\n```ts title=\"my-namespace.ts\"\nexport const start = 1;\n\nexport const end = 1;\n```\n\nIn the following cases all exports of `my-namespace.ts` are considered used:\n\n```ts title=\"index.ts\"\nimport * as NS from './my-namespace.js';\nimport send from 'stats';\n\nsend(NS);\n\nconst spread = { ...NS };\n\nconst shorthand = { NS };\n\nconst assignment = NS;\n\nconst item = [NS];\n\ntype TypeOf = typeof NS;\n\nObject.values(NS);\n\nfor (const fruit in NS) {\n  //\n}\n\nexport { NS };\n\nexport { NS as AliasedNS };\n\nexport = NS;\n```\n\nHowever, this is no longer the case when one of the properties is accessed:\n\n```ts title=\"index.js\"\nimport * as NS from './namespace.js';\n\nconst begin = NS.start;\n\nsend(NS);\n```\n\nIn this case, the `end` export will be reported as unused, even though the `NS`\nobject itself is referenced on its own as well.\n\n## Include `nsExports` and `nsTypes`\n\nTo disable the heuristic as explained above, and enforce Knip to consider each\nexport on a namespace individually, include the `nsExports` issue type:\n\n```json\n{\n  \"include\": [\"nsExports\"]\n}\n```\n\nOr use the `--include nsExports` argument from the CLI. The `nsTypes` can be\nadded as well to do the same for exported types.\n\nIncluding these _adds_ them to the report; all other issue types are still\nreported.\n\n<!-- File: packages/docs/src/content/docs/guides/performance.md (Tokens: ~408 | Category: anthropic-skill) -->\n---\ntitle: Performance\ndescription: How to profile and speed up Knip using the `--cache`, `--performance`, and `--debug` flags, file patterns, and per-workspace linting.\n---\n\nThis page describes a few topics around Knip's performance, and how you might\nimprove it.\n\nKnip does not want to tell you how to structure files or how to write your code,\nbut it might still be good to understand inefficient patterns for Knip.\n\nUse the `--debug` and `--performance` flags to find potential bottlenecks.\n\n## Cache\n\nUse `--cache` to speed up consecutive runs.\n\n## Ignoring files\n\nFiles matching the `ignore` patterns are not excluded from the analysis. They're\njust not printed in the report. Use negated `entry` and `project` patterns to\nexclude files from the analysis.\n\nRead [configuring project files][1] for details and examples. Improving\nconfiguration may have a significant impact on performance.\n\n## Metrics\n\nUse [the `--performance` flag][2] to see how many times potentially expensive\nfunctions (e.g. `findReferences`) are invoked and how much time is spent in\nthose functions. Example usage:\n\n```sh\nknip --performance\n```\n\n## ignoreExportsUsedInFile\n\nThe [ignoreExportsUsedInFile][3] option slows down the process slightly.\nTypically, anywhere between 0.25% and 10% of total running time. To find out:\n\n```sh\nknip --performance-fn hasRefsInFile\n```\n\n## A last resort\n\nIn case Knip is unbearably slow (or even crashes), you could resort to [lint\nindividual workspaces][4].\n\n[1]: ./configuring-project-files.md\n[2]: ../reference/cli.md#--performance\n[3]: ../reference/configuration.md#ignoreexportsusedinfile\n[4]: ../features/monorepos-and-workspaces.md#filter-workspaces\n\n<!-- File: packages/docs/src/content/docs/guides/troubleshooting.md (Tokens: ~1181 | Category: anthropic-skill) -->\n---\ntitle: Troubleshooting\ndescription: Troubleshoot Knip lint issues and exceptions using exit codes, `--debug`, and `--trace` to see where exports and dependencies are used.\n---\n\nWe can distinguish two types of issues:\n\n- [Lint issues reported by Knip][1]\n- [Exceptions thrown by Knip][2]\n\nAlso see the [debug][3] and [trace][4] options below that can help to\ntroubleshoot issues.\n\n:::note[Rationale]\n\nThe JavaScript/TypeScript ecosystem has a vast amount of frameworks and tools.\nAdditionally, file locations, configuration semantics, command-line arguments\nand so on vary wildly. Files and dependencies are referenced in many ways. Knip\ntries harder than you think to cover it all.\n\nKnip is intentionally strict to maximize its potential. It may initially report\nmany unused files. However, getting this right will result in great reports and\ntidy codebases.\n\nIf it doesn't work out at first, a small change can go a long way.\n\n:::\n\n## Lint issues reported by Knip\n\nKnip reports lint issues in your codebase. See [handling issues][5] to deal with\nthe reported issues.\n\nIf you're considering filing an issue, please read [issue reproduction][6]\nfirst.\n\nExit code 1 indicates a successful run, but lint issues were found.\n\n## Exceptions thrown by Knip\n\nKnip may throw an exception, resulting in an unsuccessful run.\n\nSee [known issues][7] as it may be listed there and a workaround may be\navailable. If it isn't clear what's throwing the exception, try another run with\n`--debug` to locate the cause of the issue with more details.\n\nIf you're considering filing an issue, please read [issue reproduction][6]\nfirst.\n\nExit code 2 indicates an exception was thrown by Knip.\n\n## Debug\n\nTo better understand why Knip reports what it does, run it in debug mode by\nadding `--debug` to the command:\n\n```sh\nknip --debug\n```\n\nThis will give a lengthy output, including:\n\n- Included workspaces\n- Used configuration per workspace\n- Enabled plugins per workspace\n- Glob patterns and options followed by matching file paths\n- Plugin config file paths and found dependencies per plugin\n- Compiled non-standard source files\n\n## Trace\n\nUse `--trace` to see where exports or dependencies are used:\n\n- Use `--trace-file [path]` to output this only for the given file.\n- Use `--trace-export [name]` to output this only for the given export name.\n- Use `--trace-dependency [name]` to find where a dependency is imported\n- Use both to trace a specific named or default export of a certain file.\n\nThis works across re-exports, barrel files and workspaces. Here's an example\nscreenshot:\n\n<img src=\"/screenshots/trace-export.png\" alt=\"trace export\" class=\"mw500\" />\n\nIt's like a reversed module graph. Instead of traversing imports it goes in the\nopposite direction and shows where exports are imported.\n\nThe `--trace-dependency` accepts strings for exact matches, but if it looks like\na regex that works too:\n\n<img src=\"/screenshots/trace-dependency.png\" alt=\"trace dependency\" class=\"mw500\" />\n\nUse [--workspace \\[filter\\]][8] to filter accordingly.\n\n#### Legend\n\n| Marker | Description                         |\n| ------ | :---------------------------------- |\n| `✓`    | Referenced (not reported as unused) |\n| `✗`    | Reported as unused                  |\n| `⎆`    | Entry file                          |\n\nEach child node is prefixed with how the export is consumed: `import`,\n`importAs` (shown as `original → alias`), `importNS`, or a re-export\n(`reExport`, `reExportAs`, `reExportNS`, `reExportStar`). A `refs:` line lists\nthe references found in that file; a `members:` line shows per-member status for\nnamespaces and enums. An `[ambiguous]` line lists the competing definitions when\na name reaches the file through more than one `export *`. A name that reaches\nthe file only through `export *` is traced from its definition.\n\n## Opening an issue\n\nIf you want to open an issue, please see [issue reproduction][6].\n\n## Understanding Knip\n\nLooking to better understand how Knip works? The [entry files][9] and\n[plugins][10] explanations cover two core concepts. After this you might want to\ncheck out features like [production mode][11] and [monorepos & workspaces][12].\n\nIn a more general sense, [Why use Knip?][13] explains what Knip can do for you.\n\n## Asking for help\n\nIf you can't find your answer in any of the aforementioned resources, feel free\nto [open an issue on GitHub][14].\n\n[1]: #lint-issues-reported-by-knip\n[2]: #exceptions-thrown-by-knip\n[3]: #debug\n[4]: #trace\n[5]: ../guides/handling-issues.mdx\n[6]: ./issue-reproduction.md\n[7]: ../reference/known-issues.md\n[8]: ../reference/cli.md#--workspace-filter\n[9]: ../explanations/entry-files.md\n[10]: ../explanations/plugins.md\n[11]: ../features/production-mode.md\n[12]: ../features/monorepos-and-workspaces.md\n[13]: ../explanations/why-use-knip.md\n[14]: https://github.com/webpro-nl/knip/issues\n\n<!-- File: packages/docs/src/content/docs/guides/using-knip-in-ci.md (Tokens: ~396 | Category: anthropic-skill) -->\n---\ntitle: Using Knip in CI\ndescription: Run Knip in continuous integration to catch regressions, with a GitHub Actions workflow example, exit codes, caching, and reporters.\n---\n\nKnip is your companion during local development. But it is even more valuable in\na continuous integration (CI) environment to prevent regressions over time. Knip\nwill notify you of unused dependencies, exports and files if you forgot to\nremove them.\n\nKnip will exit the process with code `1` if there are one or more issues.\n\n## GitHub Actions\n\nHere's an example workflow configuration for GitHub Actions:\n\n```yaml\nname: Lint project\n\non: push\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    name: Ubuntu/Node v24\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions/setup-node@v6\n        with:\n          node-version: 24\n      - name: Install dependencies\n        run: npm install --ignore-scripts\n      - name: Run knip\n        run: npm run knip\n```\n\n## Notes\n\n- Use [--cache][1] to speed up consecutive runs (default location:\n  `./node_modules/.cache/knip`).\n- See [Reporters][2] including the GitHub Actions reporter.\n- Consider running Knip twice: a default run and a [production mode][3] run.\n- See [CLI arguments → Output][4] for some relevant options such as\n  `--treat-config-hints-as-errors` and `--no-exit-code`.\n- In CI environments, the [--no-progress][5] flag is set automatically.\n\n[1]: ../reference/cli.md#--cache\n[2]: ../features/reporters.md\n[3]: ../features/production-mode.md\n[4]: ../reference/cli.md#output\n[5]: ../reference/cli.md#--no-progress\n\n<!-- ... +26 more modular skills available via /api/skills/webpro-nl/knip?path={path} -->\n</yakaai_skills>"}