Skip to content

Commit Message Format

We use conventional commits:

<type>(<scope>): <short summary> #<ticketid|0>

Types and scopes are listed in .github/scripts/pr-title-lint.config.json — the source of truth, kept current because the library and move generators append new project scopes to it. Local commits are not linted, but reuse those values: the PR title is auto-filled from your first commit subject, and it is linted (see below).

Just before committing, ensure that:

  • Ticket ID is provided, prompt user if missing.
  • Short summary is concise and descriptive.
  • The commit subject line has a hard limit of 72 characters — the whole <type>(<scope>): <summary> #<ticketid>, prefix and ticket included. Character counts cannot be estimated reliably, so measure it, do not guess: after writing the message run git log -1 --format=%s | awk '{print length}' and, if it prints more than 72, shorten the summary and amend the commit until it does. A PR's title is auto-filled from the first commit's subject, and GitHub truncates longer subjects with a , which can cut off the trailing ticket id. If a longer, more descriptive title is genuinely warranted, keep the commit subject within 72 and set/edit the PR title manually instead — a manually entered PR title is not subject to that truncation.
  • All tests pass and that linting is successful.
    • If linting fails, run pnpm run lint:fix && pnpm run format to automatically fix issues where possible.

Pull Request Title

CI lints the PR title (PR · Title Lint) because we squash-merge — the title, not your commits, becomes the commit on master. Local commit messages are intentionally left free.

<type>(<scope>): <short summary> <ticket>
  • Type and scope must appear in .github/scripts/pr-title-lint.config.json, the source of truth. Scopes are app/domain names (recruitee, grow, manage, workspace, …), never feature names — feat(grow): …, not feat(custom-surveys): ….
  • The ticket must end the title, unbracketed: … #86cauuv77, not … (CU-86cauuv77). Prefixes #, CU- and KI- are accepted; one ticket is enough.
  • The workspace scope needs no ticket. Draft and bot PRs are skipped.

Since the title is auto-filled from the first commit's subject, end that subject with a bare ticket id and the PR title passes as-is.

A red X here is informational — it comments and fails the step, but does not block merging. Why → decision log FE-0002.