Conventional Commits
Use this skill to produce commit messages that follow the Conventional Commits 1.0.0 specification. Use the official spec as the source of truth: https://www.conventionalcommits.org/en/v1.0.0/#specification
Output Format
Write commit messages in this structure:
<type>[optional scope][optional !]: <description>
[optional body]
[optional footer(s)]
Apply these REQUIRED rules:
- Start with a type, then optional scope, optional
!, then:. - Use
featfor new features. - Use
fixfor bug fixes. - Put scope in parentheses when used, e.g.
fix(parser):. - Place the description immediately after
:. - Start body one blank line after the description.
- Start footer block one blank line after body (or after description if no body).
- Format each footer as
<token>: <value>or<token> #<value>. - Use
-in footer tokens instead of spaces, exceptBREAKING CHANGE. - Mark breaking changes with
!before:and/orBREAKING CHANGE: <description>footer. - Keep
BREAKING CHANGEuppercase when used. - Treat other structural units as case-insensitive when validating.
Apply these RECOMMENDED quality rules:
- Write the description in imperative mood (for example
fix auth timeout, notfixed auth timeout). - Keep the description concise so the header is easy to scan in
git log. - Wrap body/footer lines at about 72 characters for terminal readability.
- Use a body to explain why the change is needed when intent is not obvious from the diff.
- Use explicit issue/action trailers when relevant (for example
Fixes: #123,Resolves: #77,Refs: #42).
Type Selection
Choose one primary type that best matches intent:
feat: add behavior or capabilityfix: correct incorrect behaviordocs: documentation-only changestyle: formatting-only changerefactor: internal change without behavior fix/featureperf: performance improvementtest: add or change testsbuild: build/dependency/tooling changeci: CI/CD pipeline changechore: maintenance that does not fit aboverevert: revert a previous change
Use types outside feat and fix when appropriate; only feat, fix, and breaking markers imply SemVer meaning by default.
Drafting Workflow
- Summarize what changed and why in one sentence.
- Decide if the change is a feature, fix, or other type.
- Choose a scope noun if it clarifies impact (
api,auth,parser,deps). - Detect breaking behavior:
- Add
!before:, and/or - Add
BREAKING CHANGE: <description>footer.
- Add
- Write a concise description line.
- Use imperative mood in the description and keep it standalone.
- Add body paragraphs only when extra context is needed; wrap around 72 columns.
- Add trailer footers for metadata (for example
Fixes: #123,Reviewed-by: Name). - Re-check against the checklist below before finalizing.
Validation Checklist
Confirm all items before returning a commit message:
- Header matches
<type>[scope][!]: <description>. - Description exists and is not empty.
- Body and footer blocks are separated by exactly one blank line.
- Footer tokens are valid trailers.
- Breaking changes are explicitly marked (
!orBREAKING CHANGE:). feat/fixare used correctly when applicable.- Description uses imperative wording and is concise.
- Body/footers are wrapped for readability when multi-line.
SemVer Mapping
fix-> PATCHfeat-> MINOR- Any commit with breaking change marker -> MAJOR
Examples
feat(auth): add device-bound refresh tokens
fix(api): prevent duplicate invoice creation
Add idempotency key validation for create-invoice endpoint.
Refs: #482
feat(storage)!: replace v1 blob schema
BREAKING CHANGE: remove support for legacy v1 blob readers.