When to use this
- Periodic codebase hygiene pass, or before a major version cleanup.
- When a file/function feels vestigial and you want confirmation before deleting it.
- Not a substitute for a language-specific dead-code linter where one exists -- run that first, use this for what it misses (dynamic dispatch, reflection, string-based lookups).
The skill file
Copy this verbatim. It's written in the SKILL.md format (YAML frontmatter + markdown instructions) that Claude Code, and increasingly other agent tools, read directly.
--- name: dead-code-finder description: Locate exports, functions, files, and branches that nothing in the codebase actually calls or imports, and verify each candidate before recommending removal. Use for codebase cleanup passes, not for reviewing a specific diff. --- # Dead Code Finder False positives here are expensive -- deleting something a dynamic caller still needs breaks production silently. Verify harder than you think you need to. ## Search strategy 1. For each candidate symbol (function, class, export, route, config key), search the whole repo for its name as plain text, not just as an import statement -- dynamic dispatch, string-keyed lookups, and reflection won't show up as a normal reference. 2. Check non-code call sites too: templates, config files, CI scripts, database migration references, feature-flag definitions. 3. Check test files -- a symbol only referenced by its own test is still dead in production, but flag that distinction explicitly rather than silently excluding it. 4. For a whole file, check the build/bundle entry points and route tables, not just other source files -- an unreferenced page component can still be live if it's wired through a router config. ## What to report For each candidate: the symbol/file, where you searched, and your confidence (certain / likely / needs a human to confirm because it's reachable only through configuration you can't fully trace here). ## Do not delete anything yourself Report findings; let the reviewer (or a follow-up task) do the deletion, especially for anything below "certain" confidence.
Installing it elsewhere
The frontmatter/body split above is Claude Code's convention. Here's how to carry the same instructions into other tools:
Save the file below verbatim (frontmatter included) at that path, project-local or in ~/.claude/skills/ for a user-level skill. Claude Code loads the name/description pair to decide when to pull it in, or you invoke it directly as /dead-code-finder.
Convert the YAML frontmatter to Cursor's rule format (description, globs, alwaysApply: false) and keep the markdown body as the rule content. Cursor surfaces it by description match, same idea as Claude Code's auto-load.
Codex CLI (and increasingly other agentic CLIs) read AGENTS.md at the repo root as always-on instructions. Paste the markdown body under a heading like ## {title}; for GitHub Copilot's coding agent, the equivalent file is .github/copilot-instructions.md.
Append the markdown body to .windsurfrules at the repo root. Windsurf treats the whole file as always-on context, so keep only the instructions you want applied on every request.
- Grepping only for import statements and missing string-based or reflective references.
- Flagging framework lifecycle methods (e.g. a hook a framework calls by convention) as dead because nothing in-repo "calls" them explicitly.
- Reporting low-confidence guesses with the same certainty as verified-dead code -- confidence level is part of the finding.