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 from your clone of the repo:

$ pipx install .
  installed package todo-linter 1.0.0, installed using Python 3.14.5
  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 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.9.tar.gz (14.2 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.9-py3-none-any.whl (13.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: todo_linter-1.0.9.tar.gz
  • Upload date:
  • Size: 14.2 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.9.tar.gz
Algorithm Hash digest
SHA256 50c72b962421450a1455a949e3afbc3d73928cb97e8642d891f2e7599b3c2564
MD5 d24f2f1d8f3c3921e8261cf78ce5a9bd
BLAKE2b-256 81b60507851319da0dc5298121beb0057802254474597843111415a330695c3f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: todo_linter-1.0.9-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.9-py3-none-any.whl
Algorithm Hash digest
SHA256 17e6dfd1783ddb0d6c2e36ed144475190adf081724aa0436b6b7c816a5cd6ac1
MD5 a7a383189adff2528f1ec28060f8f559
BLAKE2b-256 5b0c61eccf7c74a1bcd5ca3e6d5fd3c6883eec99a3174b698b4096e695427efc

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