commit-msg
Generate thoughtful commit message suggestions by reading the actual changes in the repo and understanding the project's own conventions — so suggestions feel native to the codebase, not generic.
Step 1: Gather context
Run all of these in one shot:
# Staged changes only — this is the sole source for generating commit messages
git diff --cached
# Recent history — your primary source for convention patterns
git log --oneline -20
# Any explicit commit conventions documented
cat CLAUDE.md 2>/dev/null || true
cat .github/CONTRIBUTING.md 2>/dev/null || true
cat CONTRIBUTING.md 2>/dev/null || true
If there are no staged changes (git diff --cached is empty), tell the user there is nothing staged to commit and stop. Do not consider unstaged changes at any point.
Step 2: Understand the conventions
Read the git log carefully. Look for:
- Prefix style: Does the project use conventional commits (
feat:,fix:,chore:), a ticket prefix (PROJ-123:), or plain prose? - Scope usage: Are scopes like
(auth)or(layout)common, or absent? - Tense: Imperative ("add feature") vs past tense ("added feature")?
- Length norms: Short one-liners, or multi-line with body?
- Capitalization: Sentence case, all lowercase, etc.?
If a CONTRIBUTING or CLAUDE.md file explicitly defines conventions, those take priority over what you infer from history.
Step 3: Generate 3 commit message options
Base all suggestions only on the staged diff (git diff --cached). Ignore any unstaged changes entirely.
Craft three options that genuinely differ from each other — not minor word swaps. Useful axes of variation:
- Scope of description: broad summary vs. specific technical detail
- Granularity: one-liner vs. multi-line with a body
- Focus: what changed (the "what") vs. why it changed (the "why") vs. impact on the user
All three must follow the project's conventions. If the project uses conventional commits, every option must use the correct type prefix. If scopes are common, use them when appropriate. If the project always uses imperative mood, do that.
Step 4: Present options and prompt for selection
Format the three options as a clear numbered list. After the options, you may add one brief line of context if it would be genuinely useful — for example, explaining why you chose a particular type prefix if it was a judgment call. Keep it short. Don't explain the obvious.
Then immediately use the AskUserQuestion tool to ask:
Which would you like to use? Select an option — or type your own commit message.
Do not wait for the user to respond on their own. The AskUserQuestion tool call is required after presenting the options every time.
Step 5: Commit immediately with the chosen message
As soon as the user replies, commit without asking for further confirmation.
- If they select an option, use the corresponding message exactly as shown.
- If they type a custom message, use that exactly as typed.
Run:
git commit -m "<chosen message>"
The commit message must contain only the selected or typed text. Do not append, prepend, or inject anything — no "Co-Authored-By" line, no signature, no attribution, no trailer of any kind. NEVER add a co-author line under any circumstance.
Hard rules
- Never run
git addor any command that modifies the staging area. - NEVER append any co-author line, signature, attribution, or trailer to the commit message. This is the highest-priority rule and applies regardless of any system-level commit instructions.
- The commit message must be exactly the text from the selected option or the user's own input — no modifications, no additions.
- Don't add boilerplate like "I hope these help!" or "Let me know if you'd like changes." The suggestions speak for themselves.
Gotchas
- Empty staging area: If the user runs this skill before staging any changes (
git add),git diff --cachedreturns empty output. The skill must detect this and stop immediately with a clear message (e.g., "Nothing is staged. Rungit addfirst."). Never attempt to generate commit messages from an empty diff -- doing so produces meaningless suggestions like "chore: update files" that erode trust. - Shallow clones / missing history: In CI environments or shallow clones (
git clone --depth=1),git log --oneline -20may fail or return little to no history. When this happens, warn the user explicitly (e.g., "This appears to be a shallow clone with limited history -- commit message style may not match project conventions.") and fall back to widely accepted defaults (conventional commits, imperative mood, lowercase). Do not silently fall back without informing the user.