LogPulse / guides

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.

CHANGELOG.md
## [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/91

Every 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”.

GitHub release body
## 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.0

To 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.

CHANGELOG.md, major release
## [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.

CHANGELOG.md, security patch
## [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.

Monorepo release notes
## 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/881

Changesets 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…UseMust include
A routine minor or patchTemplate 1, with the same text on GitHubVersion, date, grouped changes
Anything people get notified aboutTemplate 2Highlights first
A new major versionTemplate 3Every breaking change with a migration step
A vulnerability fixTemplate 4Affected and fixed versions, advisory link
Several packages from one repoTemplate 5One 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.

  1. 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.

    Open the converter

  2. 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: .

    Free for open source

  3. 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.

    Read the docs

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 .

More guides: open-source libraries and packages

All release notes guides

Tools and resources

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.