Use whenever drafting, editing, fixing, amending, or reviewing a git commit message — or a PR title that will be squash-merged into main. Triggers on phrases like "commit this", "what's a good commit message for…", "fix the commit message", "rewrite this commit", as well as before running `git commit`, `git commit --amend`, or `gh pr create`. Produces Conventional Commits 1.0.0 output (type, optional scope, optional !, description, optional body, optional footers) so CHANGELOG generation, SemVer bumps, and commitlint stay correct.
How this skill is triggered — by the user, by Claude, or both
Slash command
/writing-commit-messages:writing-commit-messagesThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Every commit message must follow [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/). The format is machine-parseable so it can drive CHANGELOG generation, SemVer bumps, and release tooling — that's why the rules below exist; they're not arbitrary.
Every commit message must follow Conventional Commits 1.0.0. The format is machine-parseable so it can drive CHANGELOG generation, SemVer bumps, and release tooling — that's why the rules below exist; they're not arbitrary.
For the common case (one-line summary, no body, no footers), the Quick start below + the Quick reference table are enough. Skim the rest only when you hit edge cases (breaking changes, scope ambiguity, footers, multi-paragraph bodies).
Before drafting, look at what's actually being committed (git diff --staged, not the working tree) so the type and scope match the staged change — not whatever else you happen to be editing.
Skeleton — fill in the brackets, drop the parts you don't need:
<type>(<scope>)<!>: <imperative description, lowercase, no period>
<body — explain *why*, wrap ~72 chars, optional>
<Footer-Token: value>
<BREAKING CHANGE: required if you broke something and didn't use !>
Worked example:
feat(api)!: drop legacy v1 endpoint
The v1 endpoint was deprecated in 2.3 and telemetry shows under 0.1%
of traffic still uses it. Removing it simplifies the rate limiter
and unblocks the v3 migration.
Closes: #482
BREAKING CHANGE: clients on /v1 must migrate to /v2 (see UPGRADE.md).
| Need | Prefix |
|---|---|
| New user-facing feature | feat: (MINOR) |
| User-facing bug fix | fix: (PATCH) |
| Breaking API / DTO / schema / config | feat!: or BREAKING CHANGE: footer (MAJOR) |
| Performance improvement | perf: (PATCH) |
| Refactor with no behaviour change | refactor: (no bump) |
| Tests only | test: (no bump) |
| Docs / README / comments only | docs: (no bump) |
| Build, packaging, Dockerfiles | build: (no bump) |
| CI config (Actions, pipelines, hooks) | ci: (no bump) |
| Formatting, whitespace | style: (no bump) |
| Reverting a previous commit | revert: (depends on what was reverted) |
| Maintenance, deps bumps, repo hygiene | chore: (no bump) |
<type>[optional scope][!]: <description>
[optional body]
[optional footer(s)]
feat(api):, fix(parser):, chore(deps):.feat!: or feat(api)!:.Token: value or Token #value. Tokens use - instead of spaces (e.g. Reviewed-by, Refs, Co-authored-by). BREAKING CHANGE is the one allowed exception with a space.| Type | When to use | SemVer |
|---|---|---|
feat | A new feature for the user. | MINOR |
fix | A bug fix. | PATCH |
docs | Documentation-only changes (README, CLAUDE.md, code comments, ADRs). | — |
style | Formatting, whitespace, missing semicolons — no code-meaning changes. | — |
refactor | Code change that neither fixes a bug nor adds a feature. | — |
perf | Performance improvement. | PATCH |
test | Adding or correcting tests. | — |
build | Build system, packaging, NuGet/CPM, Dockerfiles, npm scripts. | — |
ci | CI configuration (GitHub Actions, pipelines, hooks). | — |
chore | Maintenance that doesn't fit elsewhere (deps bumps, repo hygiene). | — |
revert | Reverts a previous commit. Body should reference the reverted SHA. | depends |
BREAKING CHANGE in any commit type bumps MAJOR regardless of the prefix.
A scope is a single noun in parentheses naming the section of the codebase the change belongs to. Pick the smallest unit that still reads cleanly — typically a feature folder, package, or top-level area.
feat(user-auth):, not feat(userAuth):).chore: bump Node 22).CLAUDE.md / AGENTS.md (or a commitlint config); this skill encodes only the format.Two equivalent ways to flag a breaking change — pick one, don't double up unless you want both for emphasis:
feat(api)!: drop legacy v1 endpoint. Description alone explains the break.BREAKING CHANGE: <description> footer. The token MUST be uppercase. BREAKING-CHANGE: is also allowed as a synonym.When the public API, DTO shape, configuration schema, or DB schema migration is non-additive, mark it breaking.
git log --oneline (~50 chars is the Tim Pope convention; the Conventional Commits spec itself sets no length limit).✅ fix(checkout): prevent duplicate submit on slow networks
❌ Fixed bug. / fix: Updated the form to handle a case where it submits twice when the network is slow.
git log (~72 chars is community convention; not part of the Conventional Commits spec).<token>: <value> or <token> #<value> (the # form is convenient for issue references).Reviewed-by, Co-authored-by).BREAKING CHANGE (uppercase, with a space) is the only token allowed to contain whitespace. BREAKING-CHANGE is an accepted synonym.BREAKING CHANGE: footers are allowed in a single commit.Refs: #123 / Closes: #123 — issue links.Reviewed-by: Name <email> — reviewers.Co-authored-by: Name <email> — pair / AI co-authors. Use the same token regardless of whether the co-author is a human or an AI assistant; git and GitHub both render it the same way.Signed-off-by: Name <email> — for projects using the Developer Certificate of Origin (git commit -s).docs: correct spelling of CHANGELOG
feat(api): add bulk import endpoint
fix: prevent racing of requests
Introduce a request id and a reference to the latest request.
Dismiss incoming responses other than from the latest request.
Remove timeouts that were used to mitigate the racing issue but are
obsolete now.
! — preferred for short summaries)feat(api)!: drop legacy v1 endpoint
feat: allow provided config object to extend other configs
BREAKING CHANGE: `extends` key in config file is now used for extending
other config files.
fix(checkout): prevent racing of submit handlers
Introduce a submission id and a reference to the latest submission.
Dismiss incoming responses other than from the latest submission.
Reviewed-by: Z
Refs: #123
revert: add bulk import endpoint
This reverts commit 9f2e1a7c. The endpoint shipped without the
required permission check; reverting until that lands.
Refs: #456
Conventional Commits doesn't standardise revert syntax — it just lists
revertas a community-used type. The form above matches whatgit revertproduces by default. Don't nest the original prefix inside the subject (revert: feat(api): …); most parsers won't recognise it.
Before writing the commit message:
git diff --staged) — not the working tree. The message describes what's about to be committed.git log --oneline.! or a BREAKING CHANGE: footer (not both, unless you want emphasis).Refs: / Closes: footers for any tracked issue.These are bad outcomes — commit messages that should never ship.
wip, update, misc, stuff — pick a real type and description.breaking change: — the token MUST be uppercase.These are warning signs you'll catch while drafting — the corresponding bad-outcome lives in What to avoid above. If any of these fire, fix the message (or split the commit) before committing.
chore because nothing else "obviously" fits → re-read the diff; usually it's refactor, build, ci, or docs.! and no BREAKING CHANGE: footer → add one.wip: or update: to commit faster → finish the change or split it; never ship wip to a shared branch.fixup! / squash! commits intended for git rebase --autosquash — leave git's prefix alone; they get folded into the original commit and disappear.Merge pull request #X from …) — don't reformat them.Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.
npx claudepluginhub mssalkhalifah/agent-skills --plugin writing-commit-messages