hermes

Remove dead code safely

Finds unused code, flags, endpoints, jobs and dependencies, proves each dead with static and runtime evidence, and removes it or stages a reversible retirement. Use to shrink a codebase.

context

Dead code costs reading time, build time and false leads when debugging. But "no references found" is not proof of death: code is also reached through reflection, dependency injection, string lookups, routing tables, templates, serialization, plugins, scheduled jobs and callers in other repositories. Some code has no static references to find at all: HTTP endpoints called by other teams or old app versions, flags whose value lives in a flag service, scheduled jobs, config keys and message handlers. Whether they are used is a runtime fact, and "zero calls last week" is weak evidence when a caller runs at month end, at year end, or only on an old mobile release that is still installed. Removing live code is an outage; leaving dead code is only clutter. When in doubt, keep it, or turn it off reversibly first.

task

Find and remove dead code in . Used outside this repository: . Only if [EVIDENCE_SOURCES] is given: Runtime evidence available:

  1. Find candidates: unreferenced functions, classes, exports and files; branches that can never run; feature flags that are always on or always off; configuration nobody reads; dependencies nothing imports; and runtime-reachable paths that may be unused: HTTP or RPC endpoints, GraphQL fields, message consumers, scheduled jobs, and tables or columns written but never read. Use the language's tooling where it exists (compiler warnings, unused-export or unused-dependency tools) and text search.
  2. Prove each candidate dead. Search the whole repository, not only the scope, for the name as a string as well as a symbol. Check dynamic dispatch and reflection, DI containers, routes, templates, config files, build scripts, cron and job definitions, serialization or ORM mappings, and tests.
  3. Classify:
  • dead: no path reaches it, and it is not public API used elsewhere;
  • likely dead: no reference found, but it is reachable dynamically or by external callers;
  • runtime-only: no static reference, but whether it is used is a runtime fact (endpoints, jobs, flags in a flag service, message handlers, external callers);
  • alive: a reference was found.
  1. Remove only dead items, in small commits grouped by kind, so each can be reverted alone. When a test exists only to exercise dead code, remove the test with it.
  2. For runtime-only and likely dead items, grade the evidence on three rungs: static (no references, including string lookups); runtime (zero use in the evidence sources over a stated window, and whether that window covers monthly, quarterly and yearly cycles and the oldest supported client); ownership (the owning team or known consumers confirmed it is unused). Confidence is high with all three, medium with two, low with one. If no runtime evidence was given, say what to collect; never treat missing evidence as proof of no use.
  3. Plan their retirement in stages, one change per stage so each reverts on its own: instrument (a log or metric on every entry to the path, tagged with caller identity) when evidence is missing; announce (deprecation notice, Deprecation or Sunset headers, changelog) for externally visible paths; soft-disable behind a kill switch, or return 410 Gone with a log line, keeping the code for a waiting period that covers the longest usage cycle; delete code, tests, config and flag definitions together, then now-unused dependencies in their own change; drop tables or columns only after the code that wrote them is gone and a backup exists. Order the items so that retiring one never breaks another that is still live.
  4. Run the build, type checker, linter and tests after the removal.
constraints
  • If is yes or unknown, treat exported or public symbols as likely dead at most, and do not remove them. Code that only runtime evidence can prove unused, such as endpoints, jobs and flags, needs a staged retirement, not a deletion.
  • Only high-confidence items may be planned for deletion; medium items go to soft-disable; low items need more evidence. Nothing externally reachable is deleted without a soft-disable stage first.
  • Name the exact evidence for each staged item: the query or log search, the window and the count. Do not invent numbers; write "missing" when evidence is missing.
  • Write the staged retirement as a plan with change boundaries; do not make those changes unless asked.
  • Never remove code just because it is old, commented as deprecated, or unused in tests only.
  • Do not refactor or reformat code that stays.
  • Do only what was asked. If you notice something else worth changing, mention it in one line at the end instead of changing it.
  • Keep the change as small as it can be while still being correct.
  • Before saying the work is done, run the check that proves it (tests, build, type check or the command the user gave) and report the real result.
  • If you could not run a check, say so plainly and say which one.
output format

Removed

A table: Item | Where | Evidence it was dead.

Kept

A table: Item | Where | Why it was kept (likely dead or alive, and the reference found). Or "None".

Staged retirement

A table: Item | Type | Static | Runtime (window, count) | Ownership | Confidence | Action (soft-disable / collect evidence / keep), then numbered stages with timing relative to start (week 0, week 4…), the signal that allows the next stage, and how to roll each stage back. Or "None".

Verification

Build, type-check, lint and test commands with results.

1 required value still a placeholder; the assistant will ask for it.

details

kind
Prompt: a task you run by name to get one finished thing back
domain
Software engineering
category
Refactoring
level
Intermediate
made for
Software engineer, Backend engineer, Open-source maintainer, Tech lead / staff engineer
needs
repo-read, file-write, shell, git
risk
runs-commands
version
v1.1.0 · incubating
reviewed
2026-10-02
aliases
retire-unused-code-paths
works in
Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Antigravity, OpenCode, Windsurf, Zed, Continue, AGENTS.md

Edit on GitHubReport a problem

use in

Hodios CLI
npx @hermes-hq/hodios install remove-dead-code --target claude-code
Agent Skills
npx skills add hermes-hq/hodios-dist --skill remove-dead-code -a claude-code
Add the Hodios marketplace (once)
claude plugin marketplace add hermes-hq/hodios-dist
Install the software-engineering plugin
claude plugin install hodios-software-engineering@hodios

The plugin brings every entry in this domain at once.

more in refactoring

All of Refactoring
PromptRefactoring

Extract a module

Moves one responsibility out of a large file or class into its own module in small, test-verified steps, without changing behaviour or the public API. Use when a file does too many things.

extract-module
PromptRefactoring

Improve naming in code

Proposes clearer names for variables, functions, types and modules, explains each rename and applies them without changing behaviour. Use when code reads poorly because of its names.

improve-naming
PromptRefactoring

Plan a large refactor in safe steps

Turns a large refactor into small, independently shippable steps that keep the build green, each with a rollback, using patterns like expand-contract. Use for refactors too big for one PR.

plan-large-refactor
PromptRefactoring

Reduce code duplication

Finds duplicated logic, separates true duplication from code that only looks alike, and merges only true duplicates behind one well-named function. Use when one fix keeps landing in many places.

reduce-duplication
PromptRefactoring

Simplify a complex function

Rewrites a hard-to-follow function into a clearer one with identical behaviour, using guard clauses, named steps and simpler conditions, verified by tests. Use on long or deeply nested code.

simplify-function
PromptRefactoring

Plan splitting a large module

Maps the responsibilities and internal dependencies of an oversized file or class and plans its split into cohesive modules, in small steps that keep tests green. Use before breaking up a god class.

split-large-module