Changelog and Release Notes skill for Claude Code

Tell users what changed for them, not what you typed. Claude collects merged PRs and commits since the last tag, drops internal noise like refactors and CI tweaks, and rewrites each remaining change as its effect on the user. Entries land in Keep a Changelog sections, the version bump follows from the highest-impact change, and every breaking change gets a before and after example plus migration steps. Separate benefit-led notes can be written for end users.

  • namechangelog-release-notes
  • size198 lines · ≈1,900 tokens
  • files1
  • licenseMIT
  • updated

What Claude sees before loading it

This description is the only part of the skill that sits in context all the time. Claude reads it to decide when to load the full playbook below.

description: Writes changelogs in Keep a Changelog format and user-facing release notes from commits and merged PRs — grouped by impact, written as what changed for the user rather than what the developer did, with breaking changes and deprecations called out with migration steps, and semver-consistent versions. Use when preparing a release, updating CHANGELOG.md, writing release notes or a GitHub release, announcing breaking changes, or setting up changesets, git-cliff, or release-please.

Try asking

  • Write the changelog for v3.0.0 from everything merged since v2.8.1
  • Turn these release PRs into customer-facing release notes for our blog
  • We're changing the default timeout. Write the breaking change notice and migration steps

Use it when

  • Preparing a release or GitHub release
  • CHANGELOG.md is missing, stale, or just a git log
  • Announcing breaking changes or deprecations
  • Choosing between changesets, release-please, and git-cliff

Skip it when

  • You need the tagging, branching and release process itself, use release-management instead
  • You want better commit messages at the source, use commit-craft instead

How to check the result

Every PR merged since the last tag is listed or deliberately excluded, the semver bump matches the highest-impact section, and each breaking change has followable migration steps.

The common mistake it prevents

Filing a behavior change under Fixed because the old behavior was a bug, which still breaks every client that depended on it without warning.

~/.claude/skills/changelog-release-notes/SKILL.md

--- name: changelog-release-notes description: Writes changelogs in Keep a Changelog format and user-facing release notes from commits and merged PRs — grouped by impact, written as what… license: MIT ---

A changelog entry is done when a user can tell, without reading code, whether the release affects them and what to do about it. Breaking changes are impossible to miss and come with migration steps. A pasted git log is not a changelog.

Two documents, two readers

CHANGELOG.mdRelease notes
ReaderDevelopers upgrading the package or serviceUsers or customers of the product
ScopeEvery user-visible change, including small fixesHighlights that change what people can do
ToneTerse, factualBenefit-led, plain language, can include visuals
FormatKeep a Changelog sections per versionHeadline + highlights + improvements + fixes
WhereRepo root, GitHub ReleasesBlog, in-app “What’s new”, email, docs

Ground rules

  • Write for the reader’s impact: “Exports no longer drop rows with empty dates”, not “Fix null check in ExportService”.
  • Exclude internal noise: refactors, CI changes, dependency bumps with no user effect, test changes.
  • Breaking changes first, in their own section, each with a before/after and migration steps.
  • Version numbers follow semver for libraries: breaking → major, feature → minor, fix → patch. (Pre-1.0: breaking → minor is common; say so in the README.)
  • Every entry links to its PR or issue for detail.
  • Keep an ## [Unreleased] section updated in each PR; release day is then a rename.

Workflow

- [ ] 1. List changes since the last release
- [ ] 2. Filter out non-user-facing changes
- [ ] 3. Classify (Added, Changed, Deprecated, Removed, Fixed, Security) and spot breaking ones
- [ ] 4. Rewrite each entry for user impact
- [ ] 5. Decide the version number
- [ ] 6. Write breaking-change and migration notes
- [ ] 7. Produce release notes for end users if needed
- [ ] 8. Verify links, versions, and dates

1. Collect

LAST=$(git describe --tags --abbrev=0)
git log "$LAST"..HEAD --no-merges --pretty='%h %s (%an)'
gh pr list --state merged --search "merged:>=$(git log -1 --format=%cs "$LAST")" --limit 200 \
  --json number,title,labels --jq '.[] | "#\(.number) \(.title) [\(.labels|map(.name)|join(","))]"'
git log "$LAST"..HEAD --grep='BREAKING CHANGE' -i --pretty='%h %s'
git log "$LAST"..HEAD --pretty='%h %s' | grep -E '^\w+ \w+(\(.+\))?!:'   # conventional "feat!:" markers

PR descriptions are better input than commit subjects; read them for the user-facing effect.

3. Classify (Keep a Changelog 1.1.0)

SectionUse for
AddedNew features, endpoints, options
ChangedChanges in existing behavior (mark breaking ones)
DeprecatedFeatures that still work but will be removed; say when
RemovedFeatures removed in this release
FixedBug fixes users could have noticed
SecurityVulnerability fixes; include CVE/GHSA ID and affected versions

4. Rewrite for impact

Before (commit-speak)After (user impact)
“refactor date parsing”(omit, unless behavior changed)
“fix: handle null in exporter”“CSV export no longer skips rows that have an empty due date (#412).”
“feat: add retry option”“client.send() accepts retries (default 0) to retry on 5xx and network errors (#398).”
“bump axios to 1.7”(omit) or under Security if it fixes a CVE that affected users
“change default timeout”“Breaking: default request timeout is now 10s (was unlimited). Pass timeout: 0 to restore the old behavior (#401).”

Style: one line per entry when possible, past tense or present-tense description used consistently, code identifiers in backticks, PR link at the end.

5. Version

  • Any entry in Removed, or a breaking Changed → major (≥ 1.0).
  • Any Added or Deprecated → minor.
  • Only Fixed/Security → patch.
  • Use npx semver or the release tool to compute; never reuse a published version.

6. Breaking change block

### Breaking changes

#### `createClient()` now requires `region`
Previously `region` defaulted to `us-east-1`, which sent EU customers' data to the US.

Before:
    const client = createClient({ apiKey });
After:
    const client = createClient({ apiKey, region: "eu-west-1" });

Migration: add `region` to every `createClient()` call. A codemod is available:
`npx @example/codemods v3/region .` (#455)

Deprecations: say what replaces it and the removal version or date: “listAll() is deprecated and will be removed in 4.0 (no earlier than 2027-04). Use list({ autoPaginate: true }).”

CHANGELOG.md format

# Changelog

All notable changes to this project are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [3.0.0] - 2026-10-19

### Breaking changes
- `createClient()` requires `region`; see migration notes below (#455).

### Added
- `client.send()` accepts `retries` to retry on 5xx and network errors (#398).

### Fixed
- CSV export no longer skips rows with an empty due date (#412).

### Security
- Signed URLs now expire after 15 minutes instead of 7 days (GHSA-xxxx-xxxx-xxxx).

[Unreleased]: https://github.com/acme/sdk/compare/v3.0.0...HEAD
[3.0.0]: https://github.com/acme/sdk/compare/v2.8.1...v3.0.0

Dates are ISO 8601 (YYYY-MM-DD). Newest version first.

7. Release notes for users

# October release: scheduled exports and faster search

**Scheduled exports.** Set any report to export to CSV or Google Sheets daily or weekly.
Find it under Reports → Schedule. [Screenshot]

**Search is 3× faster** on workspaces with more than 10,000 documents.

### Improvements
- Invoices show the payment method used.
- You can now reorder dashboard widgets by dragging.

### Fixes
- Exports no longer skip rows with an empty due date.

### Heads-up
- On November 15 we're retiring the legacy API v1. If you use it, see the migration guide.

Lead with the benefit, name where to find it, show it. Skip internal jargon and ticket numbers.

Tooling (pick one; do not mix)

ToolModelCommand
Changesets (JS monorepos)Each PR adds a .changeset/*.md describing impact and bumpnpx changeset in the PR; npx changeset version at release
release-pleaseParses conventional commits, opens a release PRGitHub Action googleapis/release-please-action@v4
git-cliffGenerates from conventional commits via a templategit cliff --tag v3.0.0 -o CHANGELOG.md

Generated changelogs are drafts: still rewrite entries for impact and add migration notes by hand.

Gotchas

  • Commit-derived changelogs leak internal phrasing and miss user impact; edit them.
  • “Various bug fixes and improvements” tells users nothing; list them or say nothing.
  • Hiding a breaking change in Fixed because “it was a bug” still breaks clients that relied on the behavior; call it out.
  • Security entries must not include exploit details before users can upgrade; give affected versions and the fixed version.
  • Comparison links at the bottom must be updated each release or they point to the wrong range.

Verification

  • Every PR merged since the last tag is either in the changelog or deliberately excluded (cross-check the gh pr list output).
  • The version bump matches the highest-impact section.
  • Each breaking change has before/after and migration steps; someone can follow them.
  • Links resolve (lychee CHANGELOG.md or click through), dates are ISO, newest first.

About this skill

Written and maintained by the Claude Skills editors to the same editorial standard as every skill in the directory: a selective trigger, a real workflow, known pitfalls and a verification step. First published , last updated . MIT licensed.

esc