Skip to content
Claudekit.ai

Commit Message Prompt for Claude: Conventional Commits

A copy-paste commit message prompt for Claude that turns a staged diff into a Conventional Commits message with type, scope, body and breaking-change footer.

By Claudekit Team Published 3 min read

Category
Coding
Use case
Write a Conventional Commits message from a staged git diff
Tested with
Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5, Claude Haiku 5.5

Good commit messages are cheap to write and expensive to skip: changelogs, release notes and git blame all depend on them. This prompt turns a staged diff into a message that follows the Conventional Commits 1.0.0 specification, and it refuses to invent intent the diff doesn’t show.

The prompt

You write git commit messages that follow the Conventional Commits 1.0.0 specification.

<context>
Repository / project: {{PROJECT_CONTEXT}}
Why this change was made (optional): {{INTENT}}
Allowed types: {{ALLOWED_TYPES}}
Allowed scopes (optional): {{ALLOWED_SCOPES}}
</context>

<diff>
{{STAGED_DIFF}}
</diff>

<rules>
1. Format:
   <type>[optional scope][!]: <description>

   [optional body]

   [optional footer(s)]
2. Use only the allowed types. Use "feat" only for new user-facing capability and "fix" only for bug fixes.
3. Scope is a noun naming the part of the codebase, in parentheses. Omit it if no single scope fits.
4. Description: imperative mood, lowercase start, no trailing period, at most 72 characters for the whole first line.
5. Body: explain what changed and why, wrapped at 72 characters. Skip the body for trivial changes.
6. If the diff breaks a public API, config format or CLI flag, add "!" before the colon AND a footer starting with "BREAKING CHANGE: " that tells users what to do.
7. Add issue references as footers (e.g. "Refs: #123") only if they appear in the context.
8. If the diff mixes unrelated changes, do not write one message. Instead, list how to split it into separate commits, with a message for each.
9. Never guess the motivation. If the "why" is not in the diff or context, write the body from what the diff shows.
</rules>

Return only the commit message in a single code block, with no commentary. If you recommend splitting, return one code block per commit.

How to use it

  • claude.ai: run git diff --staged | pbcopy (macOS) or redirect it to a file, paste it into {{STAGED_DIFF}} and send.
  • Claude Code: save it as a skill at .claude/skills/commit-msg/SKILL.md, set disable-model-invocation: true so it only runs when you call it, and inject the diff with !`git diff --staged` in place of the placeholder. Our Claude Code skills guide and slash commands cheatsheet show the frontmatter.
  • Scripts and hooks: pipe the diff into headless mode, for example git diff --staged | claude -p "$(cat commit-prompt.txt)", and review the output before committing. See the headless mode guide.

Variables

VariableWhat to put there
{{PROJECT_CONTEXT}}Language, framework, what the repo is
{{INTENT}}Ticket title or one sentence on why; leave blank if unknown
{{ALLOWED_TYPES}}e.g. feat, fix, docs, refactor, perf, test, build, ci, chore
{{ALLOWED_SCOPES}}e.g. api, web, auth, deps; useful if you lint commits
{{STAGED_DIFF}}Output of git diff --staged

The spec in one table

Only feat and fix are defined by the specification; the rest are a widely used convention from Angular and @commitlint/config-conventional.

ElementRuleRelease effect
fix:Bug fixPATCH
feat:New featureMINOR
! or BREAKING CHANGE: footerBreaking change, any typeMAJOR
Other types (docs, refactor, ci…)Allowed, no automatic effectNone unless breaking
FooterToken: value or Token #value; spaces in tokens become -—

BREAKING CHANGE must be uppercase. Everything else is case-insensitive per the spec, but pick one style (lowercase is the norm) and stick to it.

Example output (illustrative)

feat(auth)!: replace session cookies with short-lived tokens

Sessions now use 15-minute access tokens plus a refresh token stored
in an httpOnly cookie. The /login response shape changed to return
both tokens.

BREAKING CHANGE: clients must call /auth/refresh when they receive a
401 instead of redirecting to /login.
Refs: #482

Tips and variations

  • Enforce it: pair the prompt with commitlint in a git hook or CI so a bad message fails fast, whoever wrote it.
  • Team language: if your team writes summaries in another language, say so in rule 4 and keep the type keyword in English so tooling still parses it.
  • Changelog next: once history is consistent, ask Claude to group git log --oneline v1.2.0..HEAD by type into release notes.
  • Review first: run the code review prompt before committing, then this one.
  • More prompting technique: Claude prompting best practices.

Frequently asked questions

Which commit types does Conventional Commits allow?

The specification only mandates feat and fix. Types such as build, chore, ci, docs, style, refactor, perf and test come from the Angular convention used by @commitlint/config-conventional, and the spec says additional types are allowed.

How do I mark a breaking change?

Add ! before the colon, as in feat(api)!: drop v1 endpoints, or add a footer that starts with BREAKING CHANGE: followed by a description. The footer token must be uppercase; BREAKING-CHANGE is accepted as a synonym.

Should Claude see the whole diff?

Give it git diff --staged, which is exactly what will be committed. For very large diffs, add git diff --staged --stat and the most important hunks, or split the change into smaller commits first.

Can Claude Code write commits without this prompt?

Yes. Claude Code can commit when you ask it to. Saving this prompt as a skill makes the format consistent across the team, because everyone gets the same rules instead of the model's defaults.

Get the weekly Claude digest

New skills, MCP servers, prompts and Claude updates — one short email a week. No spam, unsubscribe anytime.

The newsletter is launching soon. Follow the RSS feed in the meantime.