gostale tracks and enforces TODOs and FIXMEs with expiration dates in Go code.
gostale helps you manage technical debt by scanning Go files for todo and fixme comments that include a stale: date (and optionally an expires: date and message). When a date is reached or passed, it can warn or fail โ making TODOs actionable.
Example:
// todo(cbrgm): stale:01-03-2025 expires:01-04-2025 implement a new AuthHandler
func oldAuth() {}- โ
Make TODOs count โ Add real deadlines to your
TODOandFIXMEcomments. - ๐ Prevent forgotten work โ Expired comments can fail your CI (if you want ๐).
- ๐งน Enforce cleanup culture โ Track stale code before it turns to rot.
- ๐ Zero friction โ Just plain Go comments. No custom tags or weird syntax.
- โ๏ธ Flexible โ Supports custom date formats, default expiry windows, log levels, and directory filters.
The gostale binary supports the following flags:
--today: Optional - Override todayโs date inDD-MM-YYYYformat. Can also be set via theGOSTALE_DATEenvironment variable.--exclude: Optional - Comma-separated list of directories to skip (e.g.,vendor,third_party).--fail-on-expired: Optional - Exit with code1if any expired annotations are found.--log-level: Optional - Set log verbosity. Options:debug,info,warn,error. Default isinfo.--default-expiry-days: Optional - Default number of days after thestaledate to consider code expired. Default is90.--date-format: Optional - Custom date format for parsingstaleandexpiresfields. Default is02-01-2006(DD-MM-YYYY).
Positional arguments:
PATH: Path or Go package pattern (e.g.,./...) to scan. Defaults to current directory.
You can use gostale via the go tool directive introduced in Go 1.24:
go tool github.com/cbrgm/gostale@latest
go tool run gostale .- Download from Releases.
- Pick the right binary for your OS.
- Place it in your
$PATH.
You can build gostale from sourc using the following commands:
git clone https://github.com/cbrgm/gostale.git && cd gostale
make build && ./bin/gostale -hor via go install.
gostale can be executed independently from workflows within a container. To do so, use the following command:
podman run --rm -v $(pwd):/code ghcr.io/cbrgm/gostale:v1 /codeInputs
path: Optional - Path or package pattern to analyze (e.g.,./...). Defaults to..today: Optional - Override todayโs date (format:DD-MM-YYYY). Useful for deterministic testing.exclude: Optional - Comma-separated list of directories to exclude from scanning.fail-on-expired: Optional - Exit with code 1 if expired annotations are found. Acceptstrueorfalse. Defaults tofalse.log-level: Optional - Specifies the logging level (debug,info,warn,error). Defaults toinfo.
Example Workflow:
name: Check for stale annotations
on:
pull_request:
paths:
- '**.go'
jobs:
gostale:
name: Run gostale
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run gostale
uses: cbrgm/gostale@v1
with:
path: ./...
fail-on-expired: true
log-level: warn
Long
// todo(cbrgm): stale:01-03-2025 expires:01-04-2025 implement a new AuthHandler
func oldAuth() {}Short
// todo(cbrgm): stale:01-03-2025 implement a new AuthHandler
func oldAuth() {}Alternatives
// all of these are supported:
//
// todo: stale:01-01-2024
// fixme: stale:01-02-2024 expires:01-03-2024 Use new auth handler
// TODO(cbrgm): stale:10-03-2025 expires:09-06-2025 this is a test
// fixme(cbrgm): stale:01-01-2024 expires:01-04-2024 see https://example.com/refactor
// todo: stale:01-01-2024 improve this before release
func oldAuth() {}Output
time=2025-03-10T23:32:12.805+01:00 level=ERROR msg="EXPIRED: /gostale/cmd/gostale/main.go:58 [main]" stale_date=01-01-2024 expires=31-03-2024 todo=""
time=2025-03-10T23:32:12.805+01:00 level=ERROR msg="EXPIRED: /gostale/cmd/gostale/main.go:59 [main]" stale_date=01-02-2024 expires=01-03-2024 todo="Use new auth handler"
time=2025-03-10T23:32:12.805+01:00 level=WARN msg="STALE: /gostale/cmd/gostale/main.go:60 [main]" stale_date=10-03-2025 expires=09-06-2025 todo="this is a test"
time=2025-03-10T23:32:12.805+01:00 level=ERROR msg="EXPIRED: /gostale/cmd/gostale/main.go:61 [main]" stale_date=01-01-2024 expires=01-04-2024 todo="see https://example.com/refactor"
time=2025-03-10T23:32:12.805+01:00 level=ERROR msg="EXPIRED: /gostale/cmd/gostale/main.go:62 [main]" stale_date=01-01-2024 expires=31-03-2024 todo="improve this before release"- Contributions Welcome!: Interested in improving or adding features? Check our Contributing Guide for instructions on submitting changes and setting up development environment.
- Open-Source & Free: Developed in my spare time, available for free under Apache 2.0 License. License details your rights and obligations.
- Your Involvement Matters: Code contributions, suggestions, feedback crucial for improvement and success. Let's maintain it as a useful resource for all ๐.