Skip to content
Productivity
Command

/promote-public-release

Build, refine, and publish cumulative public release notes, then promote the current alpha prerelease to stable

From plugin
nimbalyst
1.7k49 skills3 agents49 commands
Install
$ npx -y skills add nimbalyst/nimbalyst --agent claude-code

How it fires

How this command gets triggered: by you, by Claude, or both.

  • Fires itselfClaude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/promote-public-release

Context preview

What this command does when you run it.

Build, refine, and publish cumulative public release notes, then promote the current alpha prerelease to stable

Command definition

promote-public-release.md
description: Build, refine, and publish cumulative public release notes, then promote the current alpha prerelease to stable

Promote the current GitHub alpha prerelease to the public stable release.

This command's main job is to build the **proper cumulative public release notes** covering everything since the last stable public release, let the user edit them, then use the final text to update the existing GitHub release before making it public.

Contract: `PUBLIC_RELEASE_NOTES.md` is regenerated every run

Every invocation of `/promote-public-release` overwrites `PUBLIC_RELEASE_NOTES.md` from scratch.

The expected workflow is: 1. Generate a fresh cumulative draft from `CHANGELOG.md`, crediting every outside contributor inline. 2. Let the user edit that file directly. 3. Re-read exactly what is on disk. 4. Commit the file for repository history. 5. Update the existing GitHub release notes from that file. 6. Clear the prerelease flag on the existing release and mark it latest.

Do **not** merge with old `PUBLIC_RELEASE_NOTES.md` content. Always rebuild it from scratch.

PHASE 1: COLLECT RELEASE CONTEXT

1. **Get the version being promoted**:

   git describe --tags --abbrev=0

This should be the current `v*` tag to promote.

2. **Inspect the existing GitHub release for that tag**:

   gh release view [VERSION] --json name,url,isPrerelease,isDraft

Expectations:

  • the release already exists
  • `isPrerelease` should be `true`
  • `isDraft` should be `false`

If the release does not exist, stop and tell the user the alpha prerelease has not been published yet.

3. **Find the last stable public release before the current tag**:

   gh release list --limit 50 --json tagName,isPrerelease,isDraft,publishedAt \
     | jq '[.[] | select(.isDraft == false and .isPrerelease == false and .tagName != "[VERSION]")] | sort_by(.publishedAt) | reverse | .[0]'

Extract that `tagName`. This is the lower bound for cumulative notes.

If there is no prior stable release, tell the user this is the first public stable release and use all release sections up to `[VERSION]`.

4. **Build the contributor map for the range** — do this BEFORE drafting, so credit is written into the bullets rather than bolted on afterwards:

   git log [LAST_PUBLIC_VERSION]..[VERSION] --format='%h|%an|%s' --perl-regexp --author='^(?!Greg Hinkle)'

For each SHA, resolve the GitHub handle from the commit itself, not from the PR list:

   gh api repos/nimbalyst/nimbalyst/commits/<sha> --jq '.author.login'

This is authoritative. Do **not** derive the contributor list from `gh pr list` filtered by merge date — a contribution that landed by cherry-pick shows its PR as `CLOSED`, never `MERGED`, and is invisible to that query. In the v0.75.5 -> v0.76.2 range, PR #955 (@Yogitmeister) was exactly that case, and a merge-date query would have dropped them.

Record, per contributor commit: the handle, and the **GitHub issue** it fixes (from the commit body's `Fixes #N`, or the PR number if there is no issue). Never cite a `NIM-###` key in public notes — those are tracker-scoped and resolve to an unrelated item for any reader.

5. **Display the promotion summary and overwrite warning**: Show the user:

  • `Version to promote: [VERSION]`
  • `Current GitHub release: prerelease`
  • `Last stable public release: [LAST_PUBLIC_VERSION]` or `none`
  • `Contributors in range: @handle (#N), ...` or `none`
  • A warning that `PUBLIC_RELEASE_NOTES.md` will be overwritten with a fresh cumulative draft

PHASE 2: BUILD CUMULATIVE PUBLIC RELEASE NOTES

1. **Read `CHANGELOG.md` and extract cumulative notes**:

  • Include every release section after `[LAST_PUBLIC_VERSION]` through `[VERSION]`, inclusive.
  • Pull from `Added`, `Changed`, and `Fixed`.
  • Skip `Removed` unless it reflects a user-visible change that belongs in public notes.

2. **Reconcile the sections against the actual commit range.** Section boundaries and tag boundaries do not always agree: a commit that lands after a tag is cut often gets filed under the section that was just published, so its bullet belongs to this range even though its heading does not. Such a bullet is announced in **no** release unless you catch it here.

Diff the two views: every commit in `git log [LAST_PUBLIC_VERSION]..[VERSION]` should have a home in the notes. For any user-visible commit whose changelog bullet sits in an *already-published* section, check whether that bullet actually shipped:

   gh release view [LAST_PUBLIC_VERSION] --json body --jq '.body' | grep -i "<distinctive phrase>"

If it is not in the published body, pull the bullet forward into this release's notes and tell the user you did.

This happened to #1375 (@timscott-frogslayer, macOS accessibility) during the v0.76.2 promotion: committed after the v0.75.5 tag, filed under the `[0.75.5]` heading, absent from the published v0.75.5 notes, and only caught on a second pass.

3. **Transform into public-facing notes**:

  • Rewrite into concise user-facing language.
  • Group into:
  • `### New Features`
  • `### Improvements`
  • `### Fixed`
  • Remove internal-only items:
  • type fixes
  • refactors
  • tooling/CI
  • developer-only maintenance
  • Keep the notes cumulative across releases since the last stable public release.

4. **Credit every outside contributor, inline, in the bullet describing their work.** This is not optional and it is not a nice-to-have — an outside contributor's only public reward for the work is their name on the release. Getting it wrong is the one release mistake that costs us a contributor rather than a few minutes.

The format, matching v0.74.3:

   - A tool permission request that timed out or was dropped now says nobody answered it,
     instead of reporting a cancellation you never made (#1348, contributed by @forcewalk
Read more
Ships withnimbalyst

Nimbalyst - The open-source visual workspace for Claude Code, Codex, and OpenCode. Run multiple coding agents in parallel, edit their work visually in markdown, mockups, and diagrams, and track tasks. Free, MIT-licensed desktop app for macOS, Windows, Linux, with mobile companion for iOS and Android.

Get the whole plugin

Other commands on nimbalyst.