how to

How to detect and delete dead code (commented-out blocks, TODO piles, debug leftovers)

the short answer

To detect dead code, hunt the three forms it actually takes in shipped repos — commented-out blocks (delete them; git history already keeps them), piles of stale TODO/FIXME markers (triage: delete, fix, or move to the issue tracker), and leftover debug logging like console.log calls (delete or route through a leveled logger) — or paste the repo into cleanvibes, whose dead code & leftovers category flags each one with file and line and a Claude prompt to clean it.

Dead code is the politest kind of mess: it compiles, it lints, it never throws. That's exactly why it accumulates — nothing ever forces you to deal with it. But every commented-out function makes a reader stop and wonder whether it's load-bearing, every stale TODO is a decision the next person has to re-make, and every console.log left in production is noise at best and a leak of internal state at worst.

Vibe-coded repos collect dead code faster than most, because AI-assisted iteration is cheap: try an approach, comment it out, try another, ship the one that worked. The corpses stay. This guide covers the three forms dead code actually takes, how to find each one, and the one-rule policy that stops it coming back.

50.5%of 99 vibe-coded repos had dead-code findings — commented-out code alone appeared in 47.5%Source: cleanvibes rules-engine study, 99 public AI/vibe-coded GitHub repos, collected june 10, 2026

Commented-out code: delete it, git remembers

The biggest and most damaging form is the commented-out block: a function, a component, a whole alternative implementation, switched off but left in the file. It rots immediately — it stops compiling against the live code, contradicts what the codebase actually does, and forces every reader to ask the unanswerable question: is this here for a reason?

The policy is one rule with no exceptions: delete it. Version control exists precisely so your files don't have to be their own archive — the block is one git log -p away if you ever want it back, and you almost never will. cleanvibes detects contiguous commented-out code blocks and reports the starting line and size of each, so the deletions are surgical rather than archaeological.

TODO piles: triage, don't accumulate

A TODO is fine; a file with a dozen of them is deferred work nobody is tracking. The markers feel virtuous to write — future-you will fix it! — but they have no owner, no deadline, and no visibility, so they fossilise. Six months later nobody knows whether "TODO: handle the edge case" was handled, and the only safe assumption is that it wasn't.

The fix is triage, not a bigger pile: delete the stale ones (most of them), fix the genuinely quick ones now, and move the real ones into your issue tracker where work actually gets scheduled. cleanvibes flags files that cross a TODO/FIXME threshold and points at the first marker, which is usually all the prompt a triage session needs.

Debug leftovers: the logs that shipped

console.log("HERE 2") was useful at 1am and embarrassing forever after. Leftover debug logging clutters production consoles, occasionally leaks internal state (request bodies, tokens, user objects), and trains everyone to ignore the console entirely — which means the one log line that matters gets ignored too.

Sweep them: delete the one-off debugging calls, and route anything genuinely worth keeping through a logger with levels, so production builds stay quiet by configuration rather than by discipline. cleanvibes flags JS/TS files where console.log calls pile up, with the count, the file, and the first offending line — and the paste-ready Claude prompt to clean the file in one diff.

how it works

  1. 01

    Hunt the commented-out blocks

    Search for runs of commented lines that look like code rather than prose. Delete them — every one is recoverable from git history, and none of them are doing anything.

  2. 02

    Count the TODOs

    Grep for TODO and FIXME. Files with piles of them need a triage session: delete the stale, fix the quick, move the real ones to the issue tracker.

  3. 03

    Sweep the debug logging

    Find the console.log calls (and print() equivalents) outside tests. Delete them or route through a leveled logger so production is quiet by default.

  4. 04

    Check for leftover copies

    Files like utils copy.js, app-old.ts, or final-v2-FINAL.py are dead code at file scale. Pick the live one, delete the rest.

  5. 05

    Or scan it all at once

    Paste the repo into cleanvibes: the dead code & leftovers category flags commented-out blocks, TODO piles, and debug logging with file + line, each with a ready-to-paste Claude cleanup prompt.

frequently asked

Isn't keeping commented-out code useful as documentation?
It documents something that is no longer true, which is worse than nothing. If the old approach is worth remembering, write one sentence about why it was abandoned — in a commit message or an ADR — and delete the code. Git keeps the full text forever.
How many TODOs is too many?
There's no magic number, but concentration is the signal: one TODO near fresh code is a note; a file accumulating them is an untracked backlog. cleanvibes uses a per-file threshold for exactly that reason — it flags the pile, not the note.
Does dead code actually hurt anything if it never runs?
It hurts the reader, which is where codebase cost actually lives. Every dead block is a false lead during debugging, a question during review, and a snag during refactors. The app doesn't pay; the next person to touch the file does.
Can cleanvibes delete the dead code for me?
It finds and locates it — file, line, size, severity — and writes the Claude prompt that does the deletion with behaviour-preserving constraints. You paste the prompt into Claude Code, review the diff, and re-scan to confirm the findings are gone.

Published June 10, 2026 · Last updated June 11, 2026

ready to try cleanvibes?

score your repo