Metadata-Version: 2.4
Name: todoage
Version: 0.1.0
Summary: 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.
Author: yyfjj
License: MIT
Project-URL: Homepage, https://github.com/jjdoor/todoage-py
Project-URL: Repository, https://github.com/jjdoor/todoage-py
Project-URL: Issues, https://github.com/jjdoor/todoage-py/issues
Keywords: todo,fixme,hack,tech-debt,git,git-blame,code-comments,linter,ci,cli,devtools,static-analysis
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Version Control :: Git
Classifier: Topic :: Utilities
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# 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.

```bash
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](https://github.com/augmentable-dev/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

```bash
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](https://github.com/jjdoor/todoage)). Both ports are tested against
the same vectors, so they produce byte-for-byte identical output.

## Usage

```bash
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

```bash
# 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`, and `is_stale` are
  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
