Changelog Generator
Translates raw commit history (often terse, inconsistent, developer-facing: "fix bug", "wip", "refactor auth") into a changelog a user or stakeholder would actually want to read — organized by impact, not by commit order.
Why raw commit history isn't a changelog
Commit logs are chronological and developer-oriented. A changelog is impact-oriented and reader-oriented. The same set of commits should read differently depending on whether the audience is end-users, other engineers, or leadership — this skill's main job is that translation, not just reformatting.
Workflow
Step 1: Categorize every commit/PR before writing prose
Sort into standard categories (skip empty ones):
- Breaking changes — always first, always most detailed, since these require reader action
- New features
- Improvements (perf, UX polish, non-breaking behavior changes)
- Bug fixes
- Deprecations — things that still work but won't in a future version
- Internal/maintenance — dependency bumps, refactors, test additions — usually excluded from user-facing notes, kept in a "Chores" section only for a developer-audience changelog
Step 2: Rewrite each entry for the target audience
- Raw:
fix: null pointer in checkout when cart empty (#412) - User-facing: "Fixed an issue where the checkout page could crash if your cart was empty"
- Developer-facing (e.g. library changelog): "Fixed a null reference in
Checkout.render()whencart.itemsis empty (#412)"
Never invent detail beyond what the commit/PR title and any linked description support — if a commit message is too vague to translate confidently ("fix stuff"), either flag it for the user to clarify or use the vaguest accurate paraphrase ("various stability fixes") rather than fabricating a specific cause.
Step 3: Follow semantic versioning conventions if the project uses them
If tags follow MAJOR.MINOR.PATCH, breaking changes should correspond to a MAJOR bump, new features to MINOR, fixes to PATCH — flag a mismatch (e.g., a breaking change found in what's tagged as a patch release) rather than silently ignoring it, since that's a real risk for downstream consumers.
Step 4: Format per common convention
Default to Keep a Changelog format unless the repo already uses a different one (check CHANGELOG.md for existing style and match it):
## [1.4.0] - 2026-07-23
### Added
- ...
### Changed
- ...
### Fixed
- ...
### Deprecated
- ...
Step 5: Highlight what needs migration action
For breaking changes, add a one-line "what you need to do" note, not just a description of what changed — this is the single highest-value addition a changelog can make over a raw diff.
Anti-patterns
- Listing every commit 1:1 (squash trivial/related commits into one entry)
- Using the exact commit message verbatim when it's written in developer shorthand a non-engineer reader wouldn't parse
- Omitting breaking changes or burying them at the bottom
- Fabricating a "why" behind a change that the commit history doesn't actually explain
Reference
references/keepachangelog-format.md— full format spec and category definitions