Scan your codebase for TODO/FIXME/HACK/XXX/BUG comments and use git blame to show how old each one is and who wrote it. Flags tech debt older than N days. CI-friendly, zero dependencies.
Project description
todoage
How old is your tech debt? todoage scans your codebase for
TODO / FIXME / HACK / XXX / BUG comments, then uses git blame to show
how old each one is and who wrote it — and flags anything that's been rotting
longer than your threshold.
Zero dependencies (pure standard library). Zero config. Read-only — it never writes to your repo.
pipx run todoage
AGE TAG LOCATION AUTHOR TEXT
418d FIXME app/auth/session.py:71 Alice Dev refresh tokens before they expire
402d TODO app/billing/charge.py:12 Alice Dev validate the amount before charging
311d HACK app/api/proxy.py:88 Bob Maintainer works around the upstream 1.4 bug
9d TODO app/ui/cart.py:140 Carol wire up the empty-cart state
summary: 4 markers · 3 older than 90d
The red rows are your stalest debt — the stuff that quietly became permanent.
Why it exists
tickgit (324★) promised exactly this — blame + age tracking for your TODOs — and then went quiet in 2020 having never shipped it. VS Code's todo-tree solves IDE visibility, but there's no small CLI that does the age + author part for a CI report or a Markdown summary.
So that's all todoage is: the missing CLI. It answers one question — which
of these TODOs has been here so long it's basically a lie? — and answers it in
a way you can drop into a CI gate.
How it works
It walks your tree (skipping .git, node_modules, .venv, dist, build
artifacts and obvious binaries), matches comment markers in real comment
contexts (#, //, /* */, <!-- -->, --, ;, leading *), and asks
git blame for the author and author-date of each matching line. Age is whole
days from the commit that introduced the line.
Markers are case-sensitive UPPER, so todomvc and fixme_helper don't
trigger false positives — only an actual # TODO does.
Not in a git repo? It still lists every marker; age and author just show as ?.
Install
pipx run todoage # no install, run on demand
pip install todoage # or install the `todoage` command
There's an identical Node build too: npx todoage / npm i -g todoage
(see todoage). Both ports are tested against
the same vectors, so they produce byte-for-byte identical output.
Usage
todoage [path] [options]
| Option | Description |
|---|---|
--max-age <days|90d> |
Staleness threshold (default 90). Suffixes: d w m y (e.g. 12w, 6m, 1y). |
--tags <list> |
Comma-separated markers to scan for (default TODO,FIXME,HACK,XXX,BUG). |
--author <substr> |
Only items whose blame author contains this substring. |
--json |
Emit compact JSON instead of a table. |
--fail-on-stale |
Exit 1 if any item is stale — a one-line CI gate. |
--no-color |
Disable ANSI color. Also respects NO_COLOR. |
-h, --help |
Show help. |
-v, --version |
Print version. |
Exit codes: 0 nothing stale · 1 stale found (with --fail-on-stale) ·
2 usage error.
Examples
# fail CI if any TODO is older than a quarter
pipx run todoage --max-age 90d --fail-on-stale
# just the FIXMEs Alice left behind
todoage --tags FIXME --author alice
# feed a dashboard / Markdown summary
todoage --json | jq '.items[] | select(.stale)'
# scan one subtree, tighter threshold
todoage app/ --max-age 30d
Design notes
- One pure core, two runtimes.
scan_line,age_days, andis_staleare pure functions with no I/O, clock, or git — driven by a shared input→output vectors table that the Python and Node suites both run. That's what proves the two ports agree. - Age math never touches a
datetime. It's integer milliseconds → whole days, so the result is deterministic and identical across languages. - Read-only. It blames, it prints, it exits. No state, no cache, no config file, nothing written to your tree.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file todoage-0.1.0.tar.gz.
File metadata
- Download URL: todoage-0.1.0.tar.gz
- Upload date:
- Size: 13.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c45f0adea5f402336d3c12779e54c6afbf636f4c11f2f2387d944f50806d2c0d
|
|
| MD5 |
5a8283a5696922b9b8bdcc1b008e7b50
|
|
| BLAKE2b-256 |
e5bbc6afa541f8652a18d0dc04d0b0d8edba60231be5e5c5136d26e80ea81699
|
File details
Details for the file todoage-0.1.0-py3-none-any.whl.
File metadata
- Download URL: todoage-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9c1c140452796e04da43f1477113fe30af5a20a913ab3265e83c071923de51b1
|
|
| MD5 |
ae0c4a9dfefe5348e1a1a665ec9b9771
|
|
| BLAKE2b-256 |
7b23deab8cbeefb367cc33bff315d1384e8d13c12fe5034220907a27aab8fccf
|