Skip to main content

todo-linter

Ensure to-do items in your code have an owner and an issue.

This is inspired by the todo_linter.py I wrote several years ago for ISARA.

todo-linter searches for various "TODO" tags in the given files, and complains if they don't include an owner and a reference to an issue or task describing the deferred work:

// TODO(chrish@pobox.com https://worktree.ca/taffer/todo-linter/issues/1): a short
// description

or:

# TODO(chrish@pobox.com https://worktree.ca/taffer/todo-linter/issues/1): a short
# description

or:

<!--
TODO(chrish@pobox.com https://worktree.ca/taffer/todo-linter/issues/1): a short
description
-->

The idea here is that future you, or someone else, will know where to get more context for the task, so they can actually address it at some point. The linter makes no attempt to verify the user email or the issue URL, so these can be whatever makes sense for your project.

You can run todo-linter against any file, as long as it's valid UTF-8.

To-do items

By default, todo-linter looks lines containing these tags: TODO, FIXME, XXX, followed by a user identifier, space, and URL inside of parentheses.

You can adjust these with the --delimiter, --issue-reference, --todo-tags, and --user-identifier arguments:

  • --delimiter - Character to use as a delimiter between the user identifier and the issue reference. Defaults to space.
  • --issue-reference - One of these values, such as --issue-reference url:
    • number - An issue number in your repo, such as #14. This is nice and short, but doesn't provide a clickable link like url does.
    • other - Free-form.
    • unsafe-url - Like url but for http://hostname/path type strings.
    • url - Matches https://hostname/path type strings.
  • --todo-tags - A comma-separated list of to-do tags, such as --todo-tags To-do or --todo-tags TODO,FIXME,XXX (the default).
  • --user-identifier - One of these values, such as --user-identifier email:
    • at-tag - Matches @user type strings, frequently found in Discord, Mastodon, Mattermost, Slack, etc.
    • bare - Matches any user.
    • email - Matches user@hostname type strings. (Default)

Again, todo-linter doesn't validate issue references or user identifiers.

You can also set these in a .todo-linter.toml file in the current directory (or anywhere is you use the --config argument).

Ignoring problems

You can tell todo-linter to ignore an invalid to-do item by adding an inline comment with todo-linter: ignore:

// I don't want to correct my linter errors:
//
// TODO: I hate writing real TODO items. todo-linter: ignore
# This one isn't actually an error:
#
# This is a big TODO. todo-linter: ignore

You can disable (and re-enable) the linter for larger blocks (or entire files) using todo-linter: disable and todo-linter: enable comments:

# todo-linter: disable
#
# Any TODO, FIXME, XXX, etc. in this block will be ignored by the linter.
# You can put todo-linter: disable at the top of a file to exclude it entirely.
#
# Use this to reactivate the linter:
#
# todo-linter: enable

Because todo-linter isn't parsing your code at all, these can appear anywhere in your comments (or even your code if that's your thing).

If it comes up, todo-linter: ignore takes precedent over disable/enable.

Installation

If you're using todo-linter with pre-commit, you can skip this.

To install todo-linter, use pipx:

$ pipx install todo-linter
  installed package todo-linter 1.0.10, installed using Python 3.14.6
  These apps are now available
    - todo-linter
done!  🌟 

Using it with pre-commit

pre-commit is handy, you should try it!

To use todo-linter with your project, add this - repo stanza to your .pre-commit-config.yaml's repos: section:

repos:
  - repo: https://worktree.ca/taffer/todo-linter
    rev: {release}
    hooks:
      - id: todo-linter

Where {release} is the version tag you want to use, such as v1.0.10 or a commit hash.

Credits

Repo icon by Delapoutie on game-icons.net, licensed under the Creative Commons BY 3.0 license.

License

todo-linter is Creative Commons BY-NC-SA 4.0; see LICENSE.md for details.

No, you cannot train your LLM on this repo. Yes, I know you're going to ignore that, you slop-generating scum.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

todo_linter-1.0.10.tar.gz (14.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

todo_linter-1.0.10-py3-none-any.whl (13.1 kB view details)

Uploaded Python 3

File details

Details for the file todo_linter-1.0.10.tar.gz.

File metadata

  • Download URL: todo_linter-1.0.10.tar.gz
  • Upload date:
  • Size: 14.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"EndeavourOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for todo_linter-1.0.10.tar.gz
Algorithm Hash digest
SHA256 94acc6fbbbc03e3c847c4f290c00c21fa7b49e5df90923ec1ad4ac13fe5ffb50
MD5 d839881ba0285874f34fc15c5ed860e1
BLAKE2b-256 4c1da81bc6308f9370480bcbe3535e5c8a2090ca5985072ba4646cf68e21dc82

See more details on using hashes here.

File details

Details for the file todo_linter-1.0.10-py3-none-any.whl.

File metadata

  • Download URL: todo_linter-1.0.10-py3-none-any.whl
  • Upload date:
  • Size: 13.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"EndeavourOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for todo_linter-1.0.10-py3-none-any.whl
Algorithm Hash digest
SHA256 c825dfe03ba005c281b4ea54c894b8109dafd707b587a053995d5674c2eec9bc
MD5 871c01e987bf2898e0338a0d91ef043e
BLAKE2b-256 19fafcca7f8344db3eb08a59f7ef1662b57602f54764dd42a92f9036ea73d3e9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page