conventional-commits
Generate Conventional Commits messages from staged changes. Use when the user asks to write a commit message, follow Conventional Commits, summarize staged changes, or prepare a commit.
Writes commit messages that follow the Conventional Commits spec — useful for automated changelogs, semver bumps, and humans skimming history.
When to use
- "Write a commit message for these changes"
- "Commit this with a conventional commit message"
- "Summarize what's staged"
Procedure
-
Inspect what's actually staged (not the working tree):
git diff --staged --stat git diff --stagedIf nothing is staged, ask the user whether to use
git diff(working tree) instead. -
Optionally run the helper script in
scripts/suggest.shto get a quick summary of touched paths and a type guess. -
Pick a type (see table below). When multiple apply, choose the one that best describes the user-facing intent.
-
Pick a scope (optional but recommended) — usually a top-level module, package, or feature area. Lowercase, no spaces.
-
Write the subject line:
<type>(<scope>): <imperative summary>- ≤72 chars, no trailing period
- Imperative mood: "add", "fix", "rename" — not "added", "adds"
-
Add a body if the change is non-trivial:
- Blank line after subject
- Wrap at ~72 chars
- Explain why, not what (the diff already shows what)
-
Footer for breaking changes or issue refs:
BREAKING CHANGE: <description>or!after type/scopeRefs: #123/Closes: #123
Types
| Type | Use for | Triggers semver |
|---|---|---|
feat |
New user-facing feature | minor |
fix |
Bug fix | patch |
perf |
Performance improvement | patch |
refactor |
Code change that neither fixes a bug nor adds a feature | none |
docs |
Documentation only | none |
test |
Adding or fixing tests | none |
build |
Build system, dependencies, packaging | none |
ci |
CI configuration | none |
chore |
Maintenance with no code impact | none |
style |
Formatting, whitespace, no logic change | none |
revert |
Revert a previous commit | depends |
Breaking changes: append ! (e.g. feat(api)!: rename /users to /accounts) and add a BREAKING CHANGE: footer explaining the migration.
Output format
Show the proposed message in a code block, then offer to run git commit:
feat(auth): support passwordless email login
Adds a magic-link flow alongside the existing password login.
Tokens are single-use and expire after 10 minutes.
Refs: #482
Then: "Run git commit -F- with this message? (yes/no)"
Anti-patterns
- ❌
chore: updates— meaningless; pick the real type and say what changed - ❌ Past tense ("added X") — use imperative ("add X")
- ❌ Multiple unrelated changes in one commit — suggest splitting instead
- ❌ Trailing period on the subject line
- ❌ Wrapping the subject across lines
Examples
fix(parser): handle escaped quotes inside attribute values
Closes: #1204
refactor(http): extract retry logic into a helper
No behavior change. Sets up the next commit which adds exponential backoff.
feat(api)!: return ISO 8601 timestamps everywhere
BREAKING CHANGE: `created_at` and `updated_at` were unix timestamps;
they are now ISO 8601 strings. Update clients accordingly.