changelog
Turn raw git history into a clean CHANGELOG.md entry in the Keep a Changelog format. Handles both first-time generation (whole history) and incremental updates (new release since last tag).
When to use this
Any of the following:
- User says "write a changelog for vX.Y.Z" or "update the changelog"
- User asks "what changed since v1.2.0" in a context where they intend to release
- User is preparing a release (running
npm version,git tag, etc.) and needs release notes - User asks you to add a section to an existing CHANGELOG.md
Procedure
1. Figure out the range
Ask git for the commits to summarize. Priority order:
- If the user named a version range (
v1.2.0..HEAD,main..release/1.3), use it. - Otherwise, use
git describe --tags --abbrev=0to find the most recent tag, and summarize<that-tag>..HEAD. - If there are no tags yet, summarize the whole history (
git log).
For all cases, use:
git log --no-merges --pretty=format:"%h %s%n%b%n---" <range>
%b gives the body; the --- separator makes commit boundaries obvious after
multi-line bodies. Skip merge commits.
2. Categorize each commit
Sort commits into the standard Keep-a-Changelog buckets:
- Added — new features
- Changed — changes in existing behavior
- Deprecated — features marked for removal (usually flagged in the commit message)
- Removed — features taken out
- Fixed — bug fixes
- Security — vulnerability fixes
Heuristics for uncategorized commits:
- Commit subjects starting
add,introduce,new,feat:→ Added fix,bugfix,patch,fix:→ Fixedremove,delete,drop→ Removedrefactor,rework,rename,update→ Changedsecurity,CVE-,sanitize,escape→ Security- Anything else → make a best guess based on the body; when in doubt, Changed
Skip trivial commits: whitespace-only, "wip", "typo", "fix typo in comment", CI-only tweaks that don't affect users. If a commit's user-visible impact is zero, drop it — the changelog is for users, not the repo's history.
3. Rewrite for humans
Each commit's subject line was written for other developers. Rewrite each entry for the user of the software:
- Drop the conventional-commit prefix (
feat:,fix:, etc.) - Rewrite in imperative present tense from the reader's perspective
- Collapse related commits into one bullet (five commits fixing the same bug become one line)
- If a commit references an issue or PR (
#123,GH-456), keep the reference at the end in parentheses
Bad: feat: implement CachedResolver with hit-rate tracking (#456)
Good: - Added result caching to resolver — repeat lookups are now instant. (#456)
4. Write the output
If CHANGELOG.md exists at the repo root, insert the new release above the
previous most-recent release, keeping formatting consistent. If not, generate a
full file with a heading, an intro (link to Keep a Changelog), and the new
release as the first entry.
Standard entry format:
## [1.3.0] — 2026-07-23
### Added
- Result caching in the resolver — repeat lookups are instant. (#456)
- `--json` flag on the CLI for machine-readable output.
### Fixed
- Crash when the config file was missing a trailing newline. (#472)
### Security
- Upgraded `some-lib` from 1.4.2 to 1.4.5, closing CVE-2026-1234.
Use today's date. If the release version wasn't given, either take it from
package.json/pyproject.toml/git tag, or ask.
5. Sanity check
Before showing the user, verify:
- Every commit in the range was either categorized or intentionally dropped
- No commit hashes leak into the output (they belong in git, not the changelog)
- No internal jargon or codenames the reader wouldn't know
- Version and date are correct
Show the result. Offer to write it to CHANGELOG.md directly.
Anti-patterns to avoid
- Do not just dump
git log --onelineinto the file. That's raw history, not a changelog. The reader is a user of the software, not a maintainer of the repo. - Do not include every commit. Trivial ones (chore, ci, test-only) get dropped.
- Do not fabricate context. If a commit's purpose isn't clear from message + body + diff, ask rather than guess.
- Do not mix release entries into one bucket. Separate
Added/Fixed/etc. even if there's only one entry per section.
Examples
See examples/ for input git logs and the corresponding changelog output this
skill produces.