todo-harvest
May 16, 2026 · View on GitHub
Each scenario shows a real repo state, the exact command, and the table that todo-harvest produces — captured from a hermetic test repo, not hand-written.
Scenario 1 — triage stale debt
Setup: A small repo with three TODOs of different ages — added across the years 2022, 2024, and 2026:
src/legacy.py:2 HACK "special-case the demo account UA" (Aug 2022)
src/db.py:2 FIXME "this `n+1` lookup needs a join" (Feb 2024)
src/auth.py:2 TODO "wire to the new OAuth2 path" (Apr 2026)
Command:
python3 scripts/harvest.py --format md
Helper output (captured verbatim against a hermetic test repo on 2026-05-16):
| age (d) | marker | file:line | author | note |
|---|---|---|---|---|
| 1369 | HACK | src/legacy.py:2 | Demo Dev | special-case the demo account UA — kept around since 2022 |
| 825 | FIXME | src/db.py:2 | Demo Dev | this `n+1` lookup needs a join |
| 44 | TODO | src/auth.py:2 | Demo Dev | wire to the new OAuth2 path |
Sorted oldest-first — the most-deferred work surfaces at the top.
What Claude does next (running /todo-harvest):
The 1369-day HACK can almost certainly be deleted — it predates the user-agent registry rewrite (
src/ua.py, Jan 2024). Suggest opening a one-line PR.The 825-day FIXME is real work — the n+1 was acknowledged but never scheduled. Suggest filing an issue and linking to
src/db.py:2.The 44-day TODO is in-flight — see commit
0070d08. Leave it.
Scenario 2 — only show what's old
Skip the noise:
python3 scripts/harvest.py --min-age 365 --format md
Shows only TODOs that are at least one year old. Useful for "stale debt week" cleanups.
Scenario 3 — narrow markers
HACK and XXX are usually higher-signal than TODO:
python3 scripts/harvest.py --markers HACK,XXX --format md
Scenario 4 — JSON for further analysis
python3 scripts/harvest.py --format json | jq '[.[] | select(.age_days > 180)] | length'
# 2
What todo-harvest does NOT do
- It doesn't rewrite or delete TODOs for you. Triage is a human decision.
- It doesn't follow renames or refactors — "age" is the age of the current line. A copy-paste resets it.
- It's slow on huge repos (one
git blameper match). Use--min-ageand--markersto narrow first.