Skip to main content
Zubin KhavarianZubin Khavarian

Conventional Comments: Say What It Is and Whether It Blocks

· Last updated · 5 min read · #git #process

Editorial illustration of a hand annotating a code-review sheet with labeled stamps: praise, nitpick, suggestion, and issue.

Most friction in code review isn’t technical. It’s ambiguity. A reviewer writes “Maybe rename this?” and the author is left guessing: is that a request, a passing thought, or the thing standing between them and a merge?

Conventional Comments (opens in a new tab) fixes this with a short prefix that says what kind of feedback you’re leaving and what the author should do with it.

<label> [decorations]: <subject>

[discussion]

The label and the subject are required. Decorations and discussion are optional. That’s the whole spec, and it fits on one line of a comment:

labeldecorationsubjectwhat kind?does it block?what to dosuggestion (blocking): Use AbortController, not a boolean flag.The fetch keeps running after unmount and writes to state.discussionwhy, if it helps
Label and subject are required. Decorations and discussion are optional, but the decoration is what answers “does this block?”

What do the labels mean?

Here’s the spec’s list, condensed:

LabelMeans
praiseSomething good. Sincere, or skip it.
nitpickTrivial preference. Non-blocking by nature.
suggestionA concrete improvement. Decorate it.
issueA real problem. Pair it with a suggestion when you can.
todoSmall, necessary, easy to miss next to an issue.
questionYou’re not sure yet. Ask before you assert.
thoughtAn idea, not a request. Non-blocking by nature.
choreProcess before merge (rebase, changelog). Link the process.
noteInformation. Always non-blocking.

The spec also offers typo, polish and quibble. You don’t need them; nine labels is already plenty to remember.

You’re also free to invent your own. I wouldn’t. If what you want to say isn’t on this list, pick the closest label and let the subject do the rest.

Why decorate?

Decorations go in parentheses after the label, separated by commas. The spec’s own example is issue (ux,non-blocking). Three of them do most of the work:

  • (blocking): resolve this before merge.
  • (non-blocking): don’t hold the PR for this.
  • (if-minor): fix it only if the fix stays small.

Both blocking and non-blocking exist because teams don’t agree on the default. Some treat every comment as blocking unless told otherwise, and some treat every comment as optional. The decoration overrides whichever default you inherited, so nobody has to know your team’s unwritten rule.

Some labels already answer the question for you. nitpick, thought and note are non-blocking by definition, and praise isn’t asking for anything. The others need you to say it.

never blocksnon-blocking by naturepraisenotethoughtnitpickdecorate it(blocking) or (non-blocking)suggestionissuequestionbefore mergesmall, but necessarytodochore
Four labels answer the merge question on their own. The three in the middle need a decoration to say it.

suggestion is the one that stalls PRs, and the spec tells you to decorate it. Please do.

suggestion (non-blocking): Pull the retry logic into `withRetry()` so
`syncProjects.ts` can use it. Fine as a follow-up.

suggestion (blocking): Use `AbortController` here instead of a boolean
flag. The fetch keeps running after unmount and writes to state.

Same label, opposite merge rules, and the author doesn’t have to guess which is which.

What does a good comment look like?

An issue with a reproduction:

issue (blocking): `parseAmount("1,000.50")` returns `1`. The regex
strips commas before the decimal check.

  expect(parseAmount("1,000.50")).toBe(1000.5);

A failing test in the comment is worth ten paragraphs of explanation.

A question that might turn out to be an issue:

question: Is `userId` set when this runs? `onSubmit` reads it from
`session`, which can be `null` during sign-out.

If the answer is no, edit the label to issue. If the answer is “yes, because of X,” then X probably belongs in the code as a comment or a guard.

A nitpick the author can happily ignore:

nitpick: `useUserData` reads better than `useUserDataHook` to me.
Take it or leave it.

That “take it or leave it” matters. Without it, every nitpick turns into a small negotiation.

A thought that isn’t a demand:

thought: If we get a third permission check like this,
`usePermission(action, resource)` might be worth it. Not for this PR.

And praise that actually says something. A bare “nice!” is noise, but specific praise shows the rest of the team what to copy:

praise: The `Result<T, E>` wrapper cleaned up four call sites that
used to swallow errors.

The spec asks for at least one sincere piece of praise per review. One per review, not one per hunk.

What should you not do?

Leave suggestion undecorated. That’s the comment authors stall on most.

Treat issue as automatically blocking. The spec’s own example is issue (ux,non-blocking). If it blocks, write (blocking).

Call a blocker a nitpick. Nitpicks are non-blocking by nature, and mislabeling them teaches people to ignore the prefix entirely.

Stack labels. suggestion/issue: means you haven’t decided yet. The spec has one label per comment, so decide.

Review fifty lines of an approach that shouldn’t exist. Leave one top-level issue (blocking) about the design and stop there.

Hand-wave. issue: this is broken isn’t a review comment. Say what’s broken and what you’d do about it.

Order matters too. Put the strongest blocker first, on its own, because a wall of nitpicks buries the bug:

wall of nitpicksblocker firstnitpick: rename useUserDataHooknitpick: trailing commanitpick: sort these importsnitpick: prefer const hereissue (blocking): drops decimalsnitpick: typo in commentissue (blocking): drops decimalsnitpick: rename useUserDataHooknitpick: trailing commanitpick: sort these importsnitpick: prefer const herenitpick: typo in comment
Same six comments. On the left the bug is comment five; on the right it's the only thing that can't be skimmed.

And when you can, attach a patch to your suggestion. Suggestions with code get applied; suggestions without code get debated.

Do you need a rollout?

No. Just start using the labels yourself for a couple of weeks. Authors will ask what (non-blocking) means, and other reviewers will start copying it because it’s faster to read.

If you get tired of typing the prefixes, save the ones you actually use. GitHub saved replies (opens in a new tab) are personal, you can keep up to 100, and they work in any comment box. GitLab comment templates (opens in a new tab) can be personal or shared with a group or project.

I’d start with three: suggestion (blocking), suggestion (non-blocking) and nitpick, and decorate issue as you write it. The prefix is the whole feature. The wiki page can wait.

Stay in touch

Don't miss out on new posts or project updates. Hit me up on X for updates, queries, or some good ol' tech talk.

Follow @zkmake
Zubin Khavarian, Software EngineerWritten by