Developer pack
Claude Skill

Commit Message Writer

Generates conventional commit messages from staged changes — subject + body, why-not-what.

What it does

Reads a diff (typically `git diff --cached`) and produces a conventional-commit subject line plus a short body explaining the WHY. Refuses to write "update files" or "fix stuff" — pushes the user to articulate the change's purpose, not just its mechanics.

When to use

  • You have staged changes and want a clean, conventional message
  • You're squashing a branch and need one good message instead of "wip", "wip2", "fix"
  • You want to keep `git log` actually readable

When not to use

  • WIP commits on a personal branch you'll squash anyway — message hygiene doesn't matter yet
  • You don't know what your own change does — figure that out first

Install

Download the .zip, then unzip into your Claude skills folder.

mkdir -p ~/.claude/skills
unzip ~/Downloads/commit-message-writer.zip -d ~/.claude/skills/

# Restart Claude Code session.
# Skill is now available — Claude will use it when relevant.

SKILL.md

SKILL.md
---
name: commit-message-writer
description: Use when writing a commit message from a staged diff or condensing a branch into one message. Triggers on "commit message", "git commit message", "conventional commit", or pasted `git diff --cached` output.
---

# Commit Message Writer

Most commits in `git log` are noise. The few that aren't share three traits: they describe the WHY (not the WHAT), they're scannable in one line, and the body fills in just enough context to make the change self-explanatory in 6 months.

## Required inputs

1. **The diff** — `git diff --cached` or equivalent
2. **The reason** — what user/system problem this solves; if not obvious from the diff, ask
3. **Linked issue** — Jira / Linear / GitHub issue if any

If the diff is mechanical (config bump, dependency update) the reason can be terse. For behavior changes, the reason should be in the body.

## Format (Conventional Commits)

```
<type>(<scope>): <subject>

<body — wrap at 72 chars>

<footer — refs, breaking change notes>
```

### Types

- `feat` — new user-visible feature
- `fix` — bug fix
- `refactor` — internal restructure, no behavior change
- `perf` — performance improvement
- `docs` — docs only
- `test` — tests only
- `build` — build system, dependencies
- `ci` — CI config
- `chore` — tooling, config; nothing user-visible
- `revert` — reverts a prior commit

### Scope

Project-specific. Common: a service name, package name, top-level directory.

### Subject line rules

- 50 chars target, 72 max
- Imperative mood: "add", "fix", "update" — NOT "added", "fixes", "updating"
- No trailing period
- Lowercase after the type prefix unless naming a proper noun

GOOD: `fix(checkout): retry idempotency lookup on transient ECONNRESET`
BAD: `Fix: Fixed some issues with the checkout.`

### Body

Skip the body for trivial commits. Include it when the diff doesn't tell the whole story:

- WHY this change (1-2 sentences)
- What was considered and rejected (if non-obvious)
- Any caveat the future reader needs (deferred work, related TODOs)
- "Closes #123" or "Refs PROJ-456" in footer

The body answers the question: why did this change become necessary?

## Anti-patterns to refuse

If the user asks for a commit message and the change is just "update files" or "various fixes," push back:
- "What problem does this solve?"
- "Is this a bug fix, a feature, or a refactor? They get different prefixes."

Reject these subject lines on sight:
- `update X` (update HOW)
- `fix bug` (which bug?)
- `misc changes` (split the commit)
- `wip` (squash before merging)
- `address review feedback` (squash into the original commit)

## Examples

```
feat(auth): add refresh token rotation

Implements rotating refresh tokens per RFC 6749 §10.4. Old refresh
token is invalidated on use; reuse triggers session revocation across
all devices for that user.

Closes PROJ-2031.
```

```
fix(checkout): release DB connection on early-return path

If the cart was empty we returned 200 before releasing the pooled
connection, slowly leaking pool capacity. Reproduced under k6 load
at 50rps; pool exhausted in ~12 minutes.
```

```
refactor(billing): extract pricing calc into pure function

No behavior change. Prep for the tiered-pricing work in PROJ-2099.
```

## Squash guidance

When condensing a branch:
- Pick the type and scope of the meaningful change (ignore WIP / fixup commits)
- Subject describes the OUTCOME of the branch, not the journey
- Body can list the 2-3 substantial pieces if the change is multi-part
- Drop the per-commit nitty-gritty; `git log` shouldn't read like a diary

## Output

Return the message in a single fenced code block ready for `git commit -m` or `git commit -F`. If the change has multiple logical parts, suggest splitting into multiple commits before writing the message.

Example prompts

Once installed, try these prompts in Claude:

  • Write a commit message for this staged diff. [paste git diff --cached]
  • Squash these 6 commits into one good message. [paste git log of branch]