Commit message storyteller
Transforms git diffs, staged files, modified file lists, or plain descriptions into copyable Conventional Commits messages with a clear subject, an optional story-driven body, and issue or breaking-change footers.
When to invoke
- "Write a commit message for this diff."
- "What should I commit this as?"
- "Summarize my staged changes as a Conventional Commit."
- "Help me commit with a message that explains why."
- "Generate multiple commit messages if this diff should be split."
Prerequisites and context
Have at least one source of change context:
git diff for unstaged working tree changes.
git diff --staged or git diff --cached for staged files.
- A plain-language description of what changed and why.
- A list of modified files, functions, symbols, or issue numbers.
Use https://www.conventionalcommits.org/ as the specification source. Read references/conventional-commits-guide.md when examples or scope guidance are needed.
Procedure
- Gather the change context: what changed, why it changed, and who or what triggered it.
- Infer or confirm whether the diff is one logical change or several unrelated changes.
- Select the Conventional Commits type from the table below.
- Write the subject in imperative mood, with an optional scope only when it clarifies the affected area.
- Add a body only when it tells the story: the previous problem, the reason for the change, or the impact.
- Add footers for issues and breaking changes.
- Return copyable messages and a one-line explanation of the story told.
Commit type selection
| Type |
Use when the change primarily |
feat |
Adds a new feature or capability. |
fix |
Corrects a bug or incorrect behavior. |
refactor |
Restructures code without changing behavior. |
perf |
Improves performance. |
docs |
Changes documentation only. |
style |
Changes formatting, whitespace, or semicolons with no logic change. |
test |
Adds or updates tests. |
chore |
Changes build process, dependencies, generated files, or routine config. |
ci |
Changes CI/CD pipelines or automation. |
revert |
Reverts a previous commit. |
Message construction
<type>(<optional scope>): <short imperative summary>
<body — the story: why this change was made, what problem it solves>
<footer — issue refs, breaking change notices>
| Part |
Rule |
| Subject |
Keep it under 72 characters, lowercase after the colon, no final period. |
| Verb |
Use imperative mood: add, fix, remove; not added, fixes, or removed. |
| Body |
Explain the why, because the diff already shows the what. Keep lines under 100 characters. |
| Footer |
Use Closes #123, Fixes #456, Refs #789, and BREAKING CHANGE: <description> when applicable. |
Split heuristics
| Situation |
Action |
| Different files with unrelated purposes |
Suggest multiple commits. |
| Same file but distinct concerns, such as bug fix plus refactor |
Suggest splitting unless the refactor enables the fix. |
| Everything is tightly coupled |
Produce one message. |
User says keep it short |
Omit the body and produce a strong subject line. |
| No issue number exists |
Omit the footer entirely. |
Gotchas
- Do not write update-only subjects: replace
update file.js with the specific intent and impact.
- Do not invent why: infer from the diff when possible; otherwise mark the reason as missing or keep the body neutral.
- Do not bury breaking changes: add
BREAKING CHANGE: even when the subject already uses !.
- Do not ask when context is enough: only ask whether one diff is one logical change or multiple when the split is genuinely ambiguous.
Progressive disclosure and bundled resources
references/conventional-commits-guide.md: detailed examples, type choices, and scope guidelines.
Commit context vocabulary
Preserve issue and audience context when present: Who/what triggered the change, whether it affects open-source maintainers, and runtime details such as mid-request failures.
Output template
### Commit message storyteller result
**Status:** message ready | split recommended | blocked
**Source reviewed:** `git diff` | `git diff --staged` | `git diff --cached` | description | file list
**Commit message**
```text
<type>(<scope>): <imperative summary>
<body explaining why, omitted when not needed>
<footer such as Closes #123 or BREAKING CHANGE: details>
```
**Story told:** <one sentence explaining the problem, decision, and impact>
**Split guidance:** <one commit is fine | suggested commit boundaries>
Quality gate
1---2name: commit-message-storyteller3description: Analyze git diffs, staged changes, or plain change descriptions and generate narrative Conventional Commits messages that explain why the change matters. Use when asked to "write a commit message", "generate a commit", "describe my changes", "what should I commit this as", "commit this", "summarize my diff", or "help me commit".4---56<!-- Generated from harness/github-copilot/skills/commit-message-storyteller/SKILL.md by harness/claude-code/scripts/convert_from_copilot.py. Edit the source, not this file. -->78# Commit message storyteller910Transforms git diffs, staged files, modified file lists, or plain descriptions into copyable Conventional Commits messages with a clear subject, an optional story-driven body, and issue or breaking-change footers.1112## When to invoke1314- "Write a commit message for this diff."15- "What should I commit this as?"16- "Summarize my staged changes as a Conventional Commit."17- "Help me commit with a message that explains why."18- "Generate multiple commit messages if this diff should be split."1920## Prerequisites and context2122Have at least one source of change context:2324- `git diff` for unstaged working tree changes.25- `git diff --staged` or `git diff --cached` for staged files.26- A plain-language description of what changed and why.27- A list of modified files, functions, symbols, or issue numbers.2829Use https://www.conventionalcommits.org/ as the specification source. Read `references/conventional-commits-guide.md` when examples or scope guidance are needed.3031## Procedure32331. Gather the change context: what changed, why it changed, and who or what triggered it.342. Infer or confirm whether the diff is one logical change or several unrelated changes.353. Select the Conventional Commits type from the table below.364. Write the subject in imperative mood, with an optional scope only when it clarifies the affected area.375. Add a body only when it tells the story: the previous problem, the reason for the change, or the impact.386. Add footers for issues and breaking changes.397. Return copyable messages and a one-line explanation of the story told.4041## Commit type selection4243| Type | Use when the change primarily |44| --- | --- |45| `feat` | Adds a new feature or capability. |46| `fix` | Corrects a bug or incorrect behavior. |47| `refactor` | Restructures code without changing behavior. |48| `perf` | Improves performance. |49| `docs` | Changes documentation only. |50| `style` | Changes formatting, whitespace, or semicolons with no logic change. |51| `test` | Adds or updates tests. |52| `chore` | Changes build process, dependencies, generated files, or routine config. |53| `ci` | Changes CI/CD pipelines or automation. |54| `revert` | Reverts a previous commit. |5556## Message construction5758```text59<type>(<optional scope>): <short imperative summary>6061<body — the story: why this change was made, what problem it solves>6263<footer — issue refs, breaking change notices>64```6566| Part | Rule |67| --- | --- |68| Subject | Keep it under 72 characters, lowercase after the colon, no final period. |69| Verb | Use imperative mood: `add`, `fix`, `remove`; not `added`, `fixes`, or `removed`. |70| Body | Explain the why, because the diff already shows the what. Keep lines under 100 characters. |71| Footer | Use `Closes #123`, `Fixes #456`, `Refs #789`, and `BREAKING CHANGE: <description>` when applicable. |7273## Split heuristics7475| Situation | Action |76| --- | --- |77| Different files with unrelated purposes | Suggest multiple commits. |78| Same file but distinct concerns, such as bug fix plus refactor | Suggest splitting unless the refactor enables the fix. |79| Everything is tightly coupled | Produce one message. |80| User says `keep it short` | Omit the body and produce a strong subject line. |81| No issue number exists | Omit the footer entirely. |8283## Gotchas8485- **Do not write update-only subjects**: replace `update file.js` with the specific intent and impact.86- **Do not invent why**: infer from the diff when possible; otherwise mark the reason as missing or keep the body neutral.87- **Do not bury breaking changes**: add `BREAKING CHANGE:` even when the subject already uses `!`.88- **Do not ask when context is enough**: only ask whether one diff is one logical change or multiple when the split is genuinely ambiguous.8990## Progressive disclosure and bundled resources9192- `references/conventional-commits-guide.md`: detailed examples, type choices, and scope guidelines.9394## Commit context vocabulary9596Preserve issue and audience context when present: `Who/what` triggered the change, whether it affects `open-source` maintainers, and runtime details such as `mid-request` failures.9798## Output template99100````markdown101### Commit message storyteller result102103**Status:** message ready | split recommended | blocked104**Source reviewed:** `git diff` | `git diff --staged` | `git diff --cached` | description | file list105106**Commit message**107```text108<type>(<scope>): <imperative summary>109110<body explaining why, omitted when not needed>111112<footer such as Closes #123 or BREAKING CHANGE: details>113```114115**Story told:** <one sentence explaining the problem, decision, and impact>116117**Split guidance:** <one commit is fine | suggested commit boundaries>118````119120## Quality gate121122- [ ] The message follows Conventional Commits type and subject rules.123- [ ] The subject is imperative, non-empty, lowercased after the colon, and under 72 characters.124- [ ] The body explains why, not just what files changed.125- [ ] Breaking changes use a `BREAKING CHANGE:` footer.126- [ ] Issue references use `Closes #123`, `Fixes #456`, or `Refs #789` only when known.127- [ ] Logically unrelated changes are split or explicitly called out.128- [ ] `references/conventional-commits-guide.md` is used when detailed examples are needed.