LogoPear Docs
How ToRelease & distribute your app

Publish a changelog for your app

Ship a CHANGELOG.md with your Pear app so users read release notes over peer-to-peer with the pear changelog command.

Any Pear application can ship a CHANGELOG.md. Stage it with the rest of your project and your users—or any third party—read your release notes straight from the app drive with pear changelog pear://<link>, semver-filtered and pretty-printed. It is the same command that prints the Pear platform's own changelog when you run pear changelog with no link (a known regression makes the no-link form error on some 3.0.x builds—pass an explicit pear://<link>, as this guide does throughout).

The changelog lives in the app's Hyperdrive, so it is versioned, replicated, and readable peer-to-peer with no server and no separate publishing step—it travels with every stage and provision.

This is your application's own changelog. It is distinct from the docs-team Release Overview, which is a curated view of changes across Pear and its modules. To publish release notes for your app, follow this guide.

How it works

pear changelog reads a single file at the root of your app drive: /CHANGELOG.md. Under the hood the pear-changelog module parses it into one entry per release, then the command filters by version and prints each entry's notes. The filename and drive-root location are the entire contract—there is no manifest field to set and nothing to register.

Write CHANGELOG.md

Create a CHANGELOG.md at your project root (next to package.json). The format is lightweight:

  • A header block at the top (typically a # Title)—everything before the first ## heading is ignored by the parser. Don't start the file with a ## heading: the parser only recognizes headings that follow a line, so the first release would be dropped.
  • One release per level-2 heading (## <version>), newest first.
  • The first space-separated token of each heading must be a SemVer version (a leading v is allowed and stripped). Everything under a heading until the next ## is free-form Markdown.
CHANGELOG.md
# Acme Chat Changelog

## v1.2.0

### Features
- Group threads with @mentions.

### Fixes
- Reconnect automatically after the sidecar restarts.

## v1.1.0

### Features
- Full-text message search.

## v1.0.0

Initial release.

Keep the version as the first word of the heading, followed by a space. Bracketed Keep a Changelog headings such as ## [1.2.0] - 2026-01-01 aren't valid versions—those releases drop out of the default view and of any --of range (only --full still shows them). Use ## v1.2.0 or ## 1.2.0 instead. You can still add a date after the version, for example, ## v1.2.0 — 2026-01-01.

Check the format locally

Before staging, confirm each release parses—with the same pear-changelog module the CLI uses. This checks that headings are recognized; it does not apply the SemVer filter, so keep the version-format rules above in mind too. Install it as a dev dependency:

npm install --save-dev pear-changelog

Create check-changelog.js next to the changelog:

check-changelog.js
const { readFileSync } = require('node:fs')
const { parse } = require('pear-changelog')

for (const [version] of parse(readFileSync('CHANGELOG.md'))) {
  console.log('release:', version)
}

Run it with Node:

node check-changelog.js

It prints one line per release the parser found, newest first:

release: v1.2.0
release: v1.1.0
release: v1.0.0

If a release is missing from the output, its heading didn't parse—pear changelog won't show it either. The reverse isn't guaranteed: a release can parse here yet still be filtered out by pear changelog when its version isn't valid SemVer (see the format warning above).

Stage and seed it with your app

A root CHANGELOG.md is staged like any other project file—no extra flags. Just make sure it is not excluded by a pear.stage.ignore entry or dropped by a pear.stage.only filter that omits it.

Deploying a desktop app? The deployment directory that pear build assembles contains only package.json and by-arch/—your project's CHANGELOG.md is not copied in. Add it before staging: cp CHANGELOG.md ../<name>-<version>/.

pear stage --dry-run pear://<link>   # confirm CHANGELOG.md appears in the diff
pear stage pear://<link>

Then pear seed the link so peers can fetch it. Once staged, the file is retrievable at pear://<link>/CHANGELOG.md. Bump CHANGELOG.md in the same commit as your version bump so each release carries its own notes—see Ship your app for the full stage → provision flow.

Read it back

Anyone with the link reads your changelog with:

pear changelog pear://<link>

By default this prints up to the 10 newest releases within the current major version, each with its full notes, separated by a divider. Tune it with the flags:

FlagEffect
--of <semver>Filter to a version range, for example, --of 1.x.x or --of '>=1.1.0 <2.0.0'. Defaults to the latest major.
--max, -m <n>Cap the number of entries shown (default 10).
--fullShow every release (overrides --max); without --of, it also widens the range to all majors.
--jsonEmit newline-delimited JSON—one tagged object per release plus a final status object. Filter on "tag": "changelog" when scripting.
pear changelog pear://<link> --of 1.x.x     # only the 1.x releases
pear changelog pear://<link> --full         # the entire history
pear changelog pear://<link> --json         # machine-readable

Use it for release announcements

Because the changelog is queryable by version range, it doubles as your source of truth for release notes. When you cut a release, pull the exact entries for the range you shipped and paste them into your announcement:

pear changelog pear://<link> --of '>=1.1.0'   # everything since 1.1.0

Relationship to pear dump

pear changelog is the structured view of the same file that pear dump returns raw:

pear dump pear://<link>/CHANGELOG.md -   # raw Markdown, unparsed, to stdout

Use pear dump when you want the exact file bytes; use pear changelog when you want it parsed, semver-filtered, and formatted.

See also

On this page