task-comment-format

July 19, 2026 · View on GitHub

Targeted pattern scope

This rule checks TODO-style task comments that start with markers such as TODO, FIXME, XXX, or HACK.

It applies to line comments, block comments, and JSDoc-style comment text after block-comment decoration is normalized. Tool-control comments such as eslint-disable and TypeScript suppression comments are ignored.

What this rule reports

This rule reports task comments that stop at the marker or only contain recognized owner or issue metadata without any descriptive prose.

By default, comments like TODO, FIXME:, HACK (legacy), or TODO [#123] are invalid because they record that something is wrong without explaining what should happen next. Parenthesized or bracketed multiword text, such as (This is broken) or [Needs redesign], remains descriptive prose instead of being discarded as metadata.

Why this rule exists

Bare task comments create maintenance debt. They signal unfinished work, but they do not tell future readers what needs to change or why the task still matters.

Requiring a short descriptive body makes task comments more actionable during code review, easier to search for later, and less likely to become permanent noise.

❌ Incorrect

// TODO
startServer();
// FIXME:
retryRequest();
/* HACK (legacy) */
enableFallback();
// TODO @jane #123
removeFallback();

✅ Correct

// TODO: remove the temporary fallback after the API v2 rollout.
startServer();
// FIXME(jane): handle null input from the partner API.
retryRequest();
/* HACK [PROJ-123]: keep this branch until the cache bug is fixed upstream. */
enableFallback();
// TODO: (This is broken)
repairFallback();
// TODO [Needs redesign]
redesignFallback();

Behavior and migration notes

  • The rule is report only. It does not rewrite task comments for you.
  • Optional metadata matching the grammar below is allowed, but metadata alone is not enough.
  • The default markers are TODO, FIXME, XXX, and HACK.
  • Directive comments such as // eslint-disable-next-line ... are ignored.

Accepted metadata grammar

The rule uses deterministic token validation. It does not try to infer meaning from natural language. The accepted metadata grammar is:

metadata            = parenthesized-owner | bracketed-issue | handle | issue
parenthesized-owner = "(", ["@"], owner, ")"
bracketed-issue     = "[", issue, "]"
handle              = "@", owner
issue               = hash-issue | keyed-issue
hash-issue          = "#", digit, {digit}
keyed-issue         = ascii-letter, {ascii-letter | digit}, "-", digit, {digit}
owner               = owner-edge | owner-edge, {owner-character}, owner-edge
owner-character     = owner-edge | "." | "-"
owner-edge          = ascii-letter | digit | "_"
ascii-letter        = "A" ... "Z" | "a" ... "z"
digit               = "0" ... "9"

Each metadata token must end at the comment end, whitespace, or a supported separator (:, -, or ). Multiple metadata tokens must be separated by whitespace or a supported separator. A parenthesized owner may immediately follow the task marker, as in FIXME(jane). Separators may appear between the marker, metadata, and prose.

Consequently, the following prefixes are recognized and stripped before the description-length check:

  • (jane) and (@jane)
  • @jane
  • #123 and PROJ-123
  • [#123] and [PROJ-123]

Empty, multiword, malformed, or unclosed delimiters are not metadata. Neither are partial issue references such as #123abc or PROJ-123abc. Those strings remain part of the descriptive text and are evaluated against minDescriptionLength like any other prose.

Additional examples

Customize the accepted task markers and minimum description length:

import writeGoodComments from "eslint-plugin-write-good-comments-2";

export default [
 {
  plugins: {
   "write-good-comments": writeGoodComments,
  },
  rules: {
   "write-good-comments/task-comment-format": [
    "error",
    {
     minDescriptionLength: 12,
     terms: ["TODO", "NOTE"],
    },
   ],
  },
 },
];

ESLint flat config example

import writeGoodComments from "eslint-plugin-write-good-comments-2";

export default [
 {
  files: ["**/*.{ts,tsx,js,jsx}"],
  plugins: {
   "write-good-comments": writeGoodComments,
  },
  rules: {
   "write-good-comments/task-comment-format": "error",
  },
 },
];

When not to use it

Do not use this rule if your team bans TODO-style comments entirely with a rule such as eslint/no-warning-comments or if all follow-up work must live only in an external issue tracker.

If your team keeps task comments, this rule works best when you want them to be descriptive instead of bare markers.

Package documentation

This rule complements related task-comment tooling:

Rule catalog ID: R002

Further reading