Release notes templates in Markdown
Five copy-paste formats for libraries, CLIs and developer tools, each with the headings readers expect. Pick the one that matches your release, replace the placeholders and delete what you don't need.
Updated Last checked 6 min readOpen-source libraries and packages
The short answer
- For a CHANGELOG.md, use the Keep a Changelog 2.0.0 headings: Added, Changed, Deprecated, Removed, Fixed and Security. Mark breaking entries
**Breaking:**where they are. - For a GitHub release, lead with two or three highlights, then breaking changes, then the full list.
- For a major version, open with a one-line summary and a migration guide link, and give every breaking entry a short upgrade note.
- For a security fix, lead with the CVE identifier, name the affected and fixed versions and link the advisory. Leave exploit details out.
- Writing product updates for a SaaS app instead? Use the SaaS release notes template.
Template 1: a CHANGELOG.md entry (Keep a Changelog 2.0.0)
The everyday format for minor and patch releases. Collect lines under Unreleased as pull requests merge; on release day, rename it to the new version in both the heading and its link, and add a fresh Unreleased section.
## [Unreleased]
## [1.4.0] - YYYY-MM-DD
### Added
- `--json` flag for `my-cli status`. Thanks to Jane Doe ([#88]).
### Changed
- `my-cli init` asks before overwriting an existing config file ([#91]).
### Deprecated
- `--format=raw`: use `--json` instead. Removal is not yet scheduled.
### Fixed
- `my-cli status` exits with code 1 when the server is unreachable ([#90]).
[Unreleased]: https://github.com/OWNER/REPO/compare/v1.4.0...HEAD
[1.4.0]: https://github.com/OWNER/REPO/compare/v1.3.2...v1.4.0
[#88]: https://github.com/OWNER/REPO/pull/88
[#90]: https://github.com/OWNER/REPO/pull/90
[#91]: https://github.com/OWNER/REPO/pull/91Every name, version and number here is a placeholder. Search for OWNER, REPO and YYYY before you publish.
Free tool · no sign-up
Can a coding agent read your changelog?
Paste your repository, a GitHub release or a CHANGELOG.md link. The free converter shows every version, breaking change, migration step and deprecation it can extract, as JSON plus an llms.txt summary.
No AI and nothing stored. Or paste a CHANGELOG.md instead
01Template 2: a GitHub release
People who watch your repository's releases get notified, so open with the highlights. A release is an announcement, so a Breaking changes heading near the top is fine here. If you click Generate release notes, GitHub fills in merged pull requests, contributors and a link to the full changelog; put your highlights and breaking changes above that list. Keep a Changelog 2.0.0 suggests starting from the version's CHANGELOG.md section, which is “already the draft”.
## Highlights
- One sentence per headline change, written for users.
- …
## ⚠ Breaking changes
- **What changed.** Who is affected. What to do instead.
## What's changed
### Features
- Short description (#123) @contributor
### Fixes
- Short description (#124) @contributor
## Upgrade
npm install my-lib@2.0.0
Migration guide: https://example.com/docs/migrate-to-v2
**Full changelog**: https://github.com/OWNER/REPO/compare/v1.9.0...v2.0.0To group the generated list under your own headings, add a .github/release.yml file. Keep a Changelog vs GitHub Releases has a ready-made one.
02Template 3: a major version with migration steps
A major release is where readers need the most help. Keep a Changelog 2.0.0 keeps each breaking change under its type with a **Breaking:** marker and a short upgrade note, and sends longer procedures to a migration guide. An optional summary before the typed sections tells upgraders what's coming.
## [3.0.0] - YYYY-MM-DD
Three breaking changes: `connect()` is now async, Python 3.10 or later is
required, and `Client.raw()` is gone. Migration guide: https://example.com/docs/migrate-to-v3
### Changed
- **Breaking:** `connect()` is now async. Replace `db = connect(url)`
with `db = await connect(url)`.
- **Breaking:** Python 3.10 or later is required. With `requires-python`
set, pip keeps installing 2.x on Python 3.9.
### Deprecated
- `Client.legacy_query()`: use `Client.query()`. It will be removed in 4.0.0.
### Removed
- **Breaking:** `Client.raw()`, deprecated since 2.4.0. Use `Client.query(raw=True)`.Put the numbered, step-by-step version in the migration guide, with an ‘Affects’ line per change so readers can skip what doesn't apply to them. Keep a Changelog's reason: a long procedure “buries what changed and turns a scannable record into a how-to”.
Deprecate in a minor release before you remove anything, so people see warnings while their code still works. How to announce breaking changes covers the timeline and has an announcement template.
03Template 4: a security fix
Lead with the CVE identifier when there is one: Keep a Changelog 2.0.0 asks for that “so readers and security tools can match the entry to the advisory.” Name the affected and fixed version ranges and link the advisory, so people can check their exposure in seconds. Keep reproduction details in the advisory and time the release with your disclosure process.
## [2.3.1] - YYYY-MM-DD
### Security
- CVE-YYYY-NNNNN: <vulnerability class, e.g. "path traversal in serveStatic()">.
Affected versions: >= 2.0.0, < 2.3.1. Fixed in: 2.3.1.
Advisory: <link to the GitHub security advisory or CVE>.
Action: upgrade to 2.3.1. If you can't, <workaround, if one exists>.
Credit: <reporter, if they want to be credited>.On GitHub, maintainers can draft and publish a repository security advisory and link it from the release.
04Template 5: several packages from one repository
When one repository publishes several packages, give each package its own heading and version. Readers care about the packages they depend on, not the repository. For one product split into packages, Keep a Changelog 2.0.0 suggests a changelog per package plus one central changelog, because readers “should not have to read a dozen component changelogs to understand what a release means.” This template is the central one.
## YYYY-MM-DD
### @scope/core 4.2.0
#### Added
- `retry` option on `request()` ([#881]).
### @scope/react 2.0.0
#### Changed
- **Breaking:** Requires @scope/core 4.2.0 or later and React 18 or later.
### @scope/cli 1.7.3
#### Fixed
- `init` no longer overwrites an existing config file ([#874]).
[#874]: https://github.com/OWNER/REPO/pull/874
[#881]: https://github.com/OWNER/REPO/pull/881Changesets automates this: contributors add a small change file in their pull request, and at release time it bumps each package's version and writes each package's CHANGELOG.md.
05Which template to use
| You're releasing… | Use | Must include |
|---|---|---|
| A routine minor or patch | Template 1, with the same text on GitHub | Version, date, grouped changes |
| Anything people get notified about | Template 2 | Highlights first |
| A new major version | Template 3 | Every breaking change with a migration step |
| A vulnerability fix | Template 4 | Affected and fixed versions, advisory link |
| Several packages from one repo | Template 5 | One heading and version per package |
See how real projects apply these patterns in the open-source release notes guide.
Before and after
Too vague
v2.0.0: lots of improvements, see the commits.
Specific and actionable
2.0.0. Breaking: requires Node.js 20+, and parse() now throws ParseError instead of returning null (catch it at your input boundary). Added: parseStream() for large inputs. Migration guide linked below.
Fictional example: use your own verified names, versions and behavior.
LogPulse
Generate release notes with LogPulse
LogPulse is a hosted changelog that people and coding agents can both read. Here's exactly what it can do for the steps above, and what it can't.
Check your changelog, free
Paste a CHANGELOG.md or a GitHub releases link. A deterministic parser (no AI, nothing stored) shows the versions, breaking changes, migration steps and deprecations an agent can extract.
Draft notes from GitHub
Connect a repository: merged pull requests, commits to your default branch and published GitHub releases collect in an inbox. AI drafts a note in the tone you pick, listing breaking changes and deprecations only when the changes clearly show them. Nothing is published until you approve it. 3 AI drafts on Free; unlimited on Open source and Pro. Pro opens soon: .
Publish once, read everywhere
Approved notes go to a hosted changelog and an in-app widget, to email subscribers on Open source and Pro (Pro opens soon), and to a JSON feed and MCP server coding agents can query. CI and agents can publish with an API key.
What it doesn't do: LogPulse doesn't tag releases, bump versions, publish to npm or PyPI, or write CHANGELOG.md back to your repository; keep your release tooling for those. AI drafts can miss context, so review them like a pull request.
Before you publish
- Placeholders replaced (search for <, OWNER, REPO and YYYY)
- The version matches the git tag and the registry
- Breaking entries are marked Breaking: in place, each with a migration step
- Empty headings deleted
- The compare link points at the previous version
- Security entries lead with the CVE and link an advisory, not exploit details
Common questions
What's the difference between release notes and a changelog?
A changelog is the cumulative file: every version, newest first. Release notes are the write-up for one release, such as a GitHub release or an announcement. Keep a Changelog 2.0.0's advice: “Keep the changelog as the record, and write the release notes from it rather than maintaining two.”
Should I use emoji in release notes?
Sparingly. In CHANGELOG.md, Keep a Changelog 2.0.0 uses a plain-text **Breaking:** marker, which reads well everywhere and which LogPulse's converter picks up. In a GitHub release, a single ⚠ next to the breaking changes heading helps people scan (the converter reads ⚠️ and 💥 too), but don't rely on the emoji alone.
Can I paste these templates into LogPulse?
Yes. LogPulse release notes are Markdown. Put breaking changes, migration steps and deprecations in their own fields when you publish, and they're also available to coding agents through the JSON feed and MCP server.
Where can I see real examples?
The open-source release notes guide links release notes from Django, Python, Node.js and Vite, and the open-source changelog template has an annotated example.
Sources
Facts last checked against these sources on .
Read next
How to write release notes for open-source libraries
How to write release notes: a copy-paste template, 3 examples (library, CLI, breaking change), a 7-point checklist and how Django and Node.js do it.
Read the guide Open-source libraries and packagesKeep a Changelog vs GitHub Releases
CHANGELOG.md or GitHub Releases? See them side by side, when to use each, and how to keep both in sync with release.yml. Includes a CHANGELOG.md skeleton.
Read the guide Breaking changes, deprecations and versioningHow to announce breaking changes
When and where to warn users about a breaking change: deprecate in a minor first, ship the major with migration steps, reach every channel. Template included.
Read the guide SaaS, APIs and appsHow to write release notes for SaaS
Write SaaS release notes that say who gets a feature, when it's live and what admins must do, with a before/after example and a pre-publish checklist.
Read the guide Open-source libraries and packagesCHANGELOG.md format, explained line by line
The CHANGELOG.md format most projects follow: version headings, YYYY-MM-DD dates, the six change types, Breaking markers, Unreleased, yanked versions and links.
Read the guideMore guides: open-source libraries and packages
- Changelog vs release notes: what's the difference?
- How to generate a changelog from git commits
- How to write release notes from commits (Conventional Commits)
- semantic-release vs release-please vs Changesets (and git-cliff)
- How to keep a changelog for an npm package
- How to keep a changelog for a Python package on PyPI
Tools and resources
- Release notes template for SaaS product updates
- Open-source changelog template, annotated
- Changelog vs release notes: what's the difference?
- Free tool: convert a CHANGELOG.md or GitHub release to JSON
- Free GitHub Action: release notes from your CHANGELOG.md on every tag
- kalmwerk/release-notes-action on GitHub: the Action's code and releases
- LogPulse developer docs: feed, API and MCP server
LogPulse
Changelogs coding agents can upgrade from.
Publish versions, breaking changes, migration steps and deprecations once. People get a widget and hosted changelog; agents get a JSON feed and MCP server. Free for open source.