Dead Code Removal skill for Codex

Delete unused code with evidence, not hope. Codex treats a knip, vulture or deadcode report as a list of suspects, then checks each one for reflection, string lookups, framework conventions and outside callers before deleting anything. Removals land in themed batches (dependencies, files, exports, symbols) with a full build and test run after each, and every kept false positive gets a documented ignore.

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- dead-code-removal

Installs to ~/.agents/skills/dead-code-removal/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $dead-code-removal, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Finds and safely deletes unused files, exports, functions, dependencies and stale feature-flag branches using knip for JavaScript and TypeScript, vulture and deptry for Python, deadcode and staticcheck for Go, and cargo-machete for Rust, then proves nothing dynamic still reaches the code before removing it in small reviewable commits. Use when asked to clean up unused code, remove dead exports or unused npm or pip packages, shrink a bundle or dependency list, or delete a module everyone thinks is unused.

Use it when

  • A codebase has accumulated unused files, exports or packages
  • You want to shrink install size, bundle size or attack surface
  • A feature was retired and its code may still be lying around
  • Lint reports unused symbols and you need to decide which are real

Use something else when

How to check the result

Rerun the detector after the last batch and get only documented ignores, with build, typecheck, tests and app start all passing.

The mistake it prevents

Deleting a function that static analysis called unused but a plugin registry, route convention or cron job loads by name at runtime.

~/.agents/skills/dead-code-removal/SKILL.md

--- name: dead-code-removal description: Finds and safely deletes unused files, exports, functions, dependencies and stale feature-flag branches using knip for JavaScript and TypeScript,… license: MIT ---

Deleting code is safe when three things are true: a tool reported it unused, a search for dynamic references came back empty, and the full test suite plus build pass after removal. A tool report alone is a list of suspects, not a verdict.

Before you start

  • Read AGENTS.md for the test, lint and build commands, and run them once on a clean tree so you know the baseline (pre-existing failures are not yours).
  • Ask what counts as public: a library’s exported API is used by code you cannot see. Never remove exports from a published package without a deprecation cycle (see semantic-versioning).
  • Work on a branch; deletion PRs are easy to review only when they are small and themed.

Tool choice

EcosystemDefault toolFindsCommand
JS / TSknipunused files, exports, types, deps, devDeps, unlisted depsnpx knip
Python codevultureunused functions, classes, variables, importsvulture src/ --min-confidence 80
Python depsdeptryunused, missing and transitive deps vs pyproject.tomldeptry .
Godeadcodefunctions unreachable from main (whole-program)go run golang.org/x/tools/cmd/deadcode@latest -test ./...
Go (lint)staticcheckunused identifiers (U1000)staticcheck ./...
Rustcompiler + cargo-machetedead_code warnings; unused cratescargo build, cargo machete
CSSPurgeCSS report, or coverage in browser DevToolsselectors never matchedproject-specific

npx, pip install and go run ...@latest download packages, which needs network; in a Codex sandbox with network off, ask for approval or use the versions already in the lockfile. Prefer adding the tool as a dev dependency when the team will rerun it.

Workflow

- [ ] 1. Baseline: tests, build, typecheck green (or failures recorded)
- [ ] 2. Configure the tool with the real entry points
- [ ] 3. Run it; save the raw report
- [ ] 4. Classify every finding (table below)
- [ ] 5. Verify "unused" candidates against dynamic references
- [ ] 6. Delete in themed batches: deps, then files, then exports, then symbols
- [ ] 7. After each batch: build, typecheck, tests, bundle or start the app
- [ ] 8. One commit per batch with the evidence in the message

Step 2: configure entry points

False positives come mostly from entry points the tool does not know about. For knip, add a knip.json (or knip.ts) only when the auto-detected plugins miss something:

{
  "$schema": "https://unpkg.com/knip@5/schema.json",
  "entry": ["src/index.ts", "scripts/*.ts", "src/workers/*.ts"],
  "project": ["src/**/*.{ts,tsx}", "scripts/**/*.ts"],
  "ignore": ["src/generated/**"],
  "ignoreDependencies": ["@types/node"]
}

Useful knip runs:

npx knip                        # everything
npx knip --production           # only production code paths (skips tests, devDeps)
npx knip --include files,dependencies
npx knip --reporter json > knip-report.json

For vulture, mark known-dynamic names in a whitelist rather than lowering confidence:

vulture src/ --min-confidence 80
vulture src/ --make-whitelist > vulture_whitelist.py   # review it, then:
vulture src/ vulture_whitelist.py --min-confidence 80

Step 4: classify findings

FindingUsuallyAction
Unused dependency, not imported anywhereRealRemove from manifest, regenerate lockfile
Unused dependency used by a CLI or config (eslint-config-*, @types/*, babel plugins)False positiveIgnore in config with a comment
Unused file with no imports and no recent commitsRealDelete after step 5
Unused export, used inside its own fileHalf-deadDrop the export, keep the symbol
Unused export in a published libraryPublic APIDeprecate, do not delete
Unused function referenced by name in strings, decorators, routes, DIFalse positiveWhitelist with a reason
Code behind a flag that is 100% on (or off) for weeksStale branchRemove the losing branch and the flag together (see feature-flags)
Test-only helpers for deleted codeRealDelete with the code

Step 5: hunt dynamic references

Static tools miss anything resolved at runtime. Before deleting generateInvoicePdf or legacy_export.py, search for the name in every form it could take:

rg -n "generateInvoicePdf|generate_invoice_pdf|generate-invoice-pdf" --hidden -g '!node_modules'
rg -n "legacy_export" -g '*.{yml,yaml,json,toml,ini,cfg,html,sql,md}'   # configs, templates, cron

Check specifically:

  • Reflection and registries: getattr, importlib, require(variable), dynamic import(), Spring component scanning, Rails autoloading, plugin entry points in pyproject.toml.
  • Framework conventions: file-system routes, Django management commands, Celery tasks registered by decorator, migrations (never delete applied migrations).
  • Out-of-repo callers: other services, infra scripts, scheduled jobs, notebooks, SQL views, public URLs and webhooks. Ask the user when a symbol might be called from outside.
  • Production evidence when available: route hit counts, logs, coverage from a canary. “No calls in 90 days of logs” is stronger than any static report.

If a candidate is uncertain, do not delete it. Add a one-release tombstone instead (log or metric on entry) and list it for the user.

Step 6 and 7: delete in batches, verify each

Order matters: dependencies first (smallest blast radius), then whole files, then exports, then individual symbols. After each batch:

pnpm install && pnpm typecheck && pnpm test && pnpm build    # adapt from AGENTS.md
npx knip                                                      # new orphans appear after deletes

Deleting one file often orphans its imports; rerun the tool until the report stops shrinking. knip can apply removals (npx knip --fix, plus --allow-remove-files to delete files); review its diff like any other change rather than trusting it blindly.

Hard rules

  • Never delete applied database migrations, public API endpoints, or exported library symbols as “dead code”; those need deprecation and a migration path.
  • Never combine dead-code removal with behaviour changes or refactors in the same commit.
  • Do not lower tool confidence or add blanket ignores to make the report clean. Each ignore gets a comment saying why the code is live.
  • Keep deletions reversible: one theme per commit so git revert <sha> restores it.
  • Ask before deleting anything outside the requested scope, even if it is obviously dead.

Commit and report

chore: remove unused invoice PDF v1 pipeline

knip and rg found no imports or string references to src/invoice/v1/**.
Route /api/invoices/v1/pdf had 0 requests in 90 days (dashboard link in PR).
Removes 1,240 lines and the pdfkit dependency.

Report to the user:

## Dead code removal
| Batch | Removed | Evidence | Verified by |
|---|---|---|---|
| deps | pdfkit, left-pad | not imported (knip), build green | pnpm build, tests |
| files | src/invoice/v1/** (14 files) | no imports, no string refs, 0 route hits | tests, typecheck |

### Kept on purpose (false positives)
- `src/plugins/*.ts` - loaded by glob in plugin-loader.ts:12 (added to knip entry)

### Needs a human decision
- `exportLegacyCsv` - referenced in a cron config outside this repo?

Verification

  • Tool report rerun after the last batch shows only documented, ignored items.
  • Build, typecheck, tests and app start pass; bundle or install size before and after is reported when the user cares about size.
  • Every remaining ignore has a reason comment.

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "Dead Code Removal"
  short_description: "Delete unused code with evidence, not hope"
  default_prompt: "$dead-code-removal Find unused exports and npm packages in this TypeScript repo and remove them safely"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc
Just launched

Codex Skills Pro is live

79 premium skills for Codex, each with scripts, references and an evidence report that proves the result.

Bought one by one$882.21
All 79 skills$49
94% off

That's $0.62 a skill, paid once.

Get all 79 for $49Or pick single skills from $4.99 →

Secure checkout by Creem