pm-changelog
v2026.9.18
Published
Generate CHANGELOG.md files from pm-cli items for local and CI usage
Downloads
5,815
Maintainers
Readme
pm-changelog
Generate CHANGELOG.md from pm-cli items.
Install
pm install npm:pm-changelog --projectpm changelog generate --mode prepend --output CHANGELOG.mdRebuild a full project changelog from git release tags:
pm changelog generate --all-release-tags --mode replace --output CHANGELOG.mdTag-derived flags (--all-release-tags, --since-previous-tag,
--until-release-tag) require complete git tag history: in a shallow clone
they fail with an actionable E_MISSING_TAG_HISTORY diagnostic instead of
deriving an incomplete window. The diagnostic names the exact recovery for the
detected state — git fetch --tags --unshallow for a plain shallow clone, or
git config --unset remote.origin.tagOpt && git fetch --tags --unshallow when
the clone is also --no-tags; follow all commands it lists (see
Release and CI).
Standalone npm usage:
npm install --save-dev pm-changelog @unbrained/pm-cli
npx pm-changelog --mode prepend --output CHANGELOG.mdThe standalone CLI accepts both --flag value and --flag=value for value
options, and supports --release-version as a compatibility alias for
--version (matching pm changelog generate syntax).
Date precedence is explicit: --date is an unconditional override, then an
existing release tag supplies its commit date, then --date-fallback or
--date-from-version applies only while that tag is absent. With none of those,
generation uses the current UTC calendar date. Release-gated CalVer packages can
therefore use --date-from-version (for example 2026.8.8 becomes
2026-08-08) without masking the authoritative tag date after publication.
--date-fallback and --date-from-version are mutually exclusive. Explicit
and fallback date text is rendered verbatim; use YYYY-MM-DD for a conventional
changelog heading.
npx pm-changelog --release-version-from-package --date-from-version
npx pm-changelog --version 1.2.0 --date-fallback 2026-08-08Opt-in extras
These flags are strictly additive — omitting them keeps output byte-for-byte identical to the default:
npx pm-changelog --stdout --section-by type # group by type/status/label instead of categories
npx pm-changelog --stdout --conventional # Features / Bug Fixes / ... headings
npx pm-changelog --stdout --contributors # per-release contributor list
npx pm-changelog --all-release-tags --limit 10 # keep only the newest N releases
npx pm-changelog --all-release-tags --since-version 2.0.0
npx pm-changelog --all-release-tags --changelog-json > changelog.json
npx pm-changelog --stdout --breaking-changes # add a Breaking Changes section
npx pm-changelog --suggest-semver # print a suggested semver bump as JSON
npx pm-changelog --stdout --body-preview 80 # append first 80 chars of each item body
npx pm-changelog --stdout --emoji-prefix # prefix headings with emoji (Added 🎉, Fixed 🐛, ...)
npx pm-changelog --stdout --include-metadata # append type/status/priority/release/milestone per item
npx pm-changelog --stdout --json --explain # emit selection diagnostics (counts + exclusion hints) for agents
npx pm-changelog --stdout --item-ref-style github # link item IDs to public GitHub issues/PRs, not .agents/pm blobs
npx pm-changelog --stdout --item-ref-style label # neutral (id) labels — safe for a published/public changelog
npx pm-changelog --stdout --respect-item-release # honor each item's release field, not just closed_at
npx pm-changelog --stdout --exclude-tag changelog:ignore # keep tagged items out of the changelog entirely--item-ref-style controls how pm item IDs render as references:
auto(default) — an internal.toonblob link when--item-url-baseis set, otherwise a neutral(id)label. Byte-for-byte identical to prior behavior.label— always a neutral(id)label, never a link. Use for changelogs published to a public registry, where.agents/pm/...blob URLs leak tracker structure and may 404.toon— force the internal.toonblob link (requires--item-url-base; falls back to a label when it is unset).github— render a public GitHub issue/PR link derived from the item'sgh:owner/repo#numberprovenance tag (written by pm-github); items without a valid provenance tag fall back to a neutral label.
See Usage for details.
Release attribution: work that shipped before its tracker was closed
By default an item lands in the release window that contains its authoritative completion time — completed_at (recorded by pm-cli ≥ 2026.7.29 separately from tracker close time). When completed_at is absent, generation falls back to closed_at, then updated_at, then created_at; those fallbacks are inferred, not authoritative. In multi-agent workflows an agent often ships the fix in one release and closes the tracker during a later one, which would date months-old work as new — and is why shipped-but-unclosed trackers pile up: closing them corrupts the changelog.
Record where the work actually landed and generation stops trusting closed_at:
pm update <id> --release 2026.6.1 # the release the fix actually shipped in
npx pm-changelog --stdout --release-version 2026.7.24 --respect-item-releaseWith --respect-item-release, an item that declares a release (top-level field or
metadata.release) is pinned to it: kept when it matches the generated version regardless of
timestamps, dropped otherwise (including from an unversioned Unreleased window — it already
shipped). Items without a declared release keep the plain time-window behavior, so output is
unchanged for workspaces that never set the field. --all-release-tags already honors the field and
is unaffected; the flag makes the single-window path (--since-previous-tag --until-release-tag,
changelog:check, release notes) agree with it. --explain reports what attribution dropped.
Inferred-attribution report
--explain also reports attribution provenance: how many visible items were placed in their
release window from the authoritative completed_at versus an inferred fallback (closed_at,
updated_at, or created_at), plus a bounded sample of the inferred item ids. This is how a
maintainer catches a shipped-but-late-closed item — one whose completed_at is missing so its
placement fell back to a closed_at recorded in a later release. Inspect the inferred sample, set
completed_at (or pin the item with --release), and regenerate.
Excluding items
--exclude-tag <tags> (repeatable, comma-separated) omits items carrying any listed tag from every
generation path — an ignore convention for pm items that are legitimately tracked but are not
user-facing package changes (upstream issue mirrors, internal chores, superseded work):
pm update <id> --add-tags changelog:ignore
npx pm-changelog --stdout --exclude-tag changelog:ignoreMatching is case-insensitive and trims whitespace. The item stays in the tracker with its full history — only the generated changelog skips it.
Docs
Multi-agent merge safety
This repo tracks its project management in .agents/pm/ and ships a committed .gitattributes
that maps those tracker artifacts to pm-cli's field-aware Git merge drivers, so concurrent-branch
tracker edits merge cleanly instead of hard-conflicting. The driver definitions live in
per-clone Git config; npm install / npm ci wires them automatically via the prepare script (a portable, erasable-TypeScript Node guard, scripts/prepare-merge-driver.ts: it runs
pm merge install only when the pm CLI is on PATH, and no-ops cleanly otherwise so
production / --omit=dev installs are not broken; being Node-based it behaves identically
on POSIX shells and Windows cmd.exe). To (re)run manually: npm run merge:install.
After merging a branch that touched .agents/pm/, reconcile any residual history-hash drift with
pm merge reconcile (pm-cli ≥ 2026.7.22): preview with pm merge reconcile --dry-run, apply with
pm merge reconcile --message "post-merge reconcile", then confirm with pm validate, which scans the
whole tracker and flags remaining history drift across every affected item (pm merge reconcile
itself lists each affected stream in its output; pm history --verify <id> spot-checks one item). The field-aware driver already unions every author's
content, so reconcile only re-greens the hash chain (no data loss) — see the authoritative
pm-cli merge-safety guide. The
older blunt pm history-repair --all remains available as a lower-level primitive.
