/promote-public-release
Build, refine, and publish cumulative public release notes, then promote the current alpha prerelease to stable
$ npx -y skills add nimbalyst/nimbalyst --agent claude-codeHow 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.mddescription: 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 @forcewalkRead more
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 @forcewalkNimbalyst - 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.
Repo: nimbalyst/nimbalyst
Other commands on nimbalyst.
analyze-sessions
Audit recent AI coding sessions to find repeated mistakes, speed losses, and missed Nimbalyst tool usage — then propose harness improvements
audit-updates
Triage npm audit findings and produce a prioritized, supply-chain-cautious package-update plan, then apply approved batches
autofix-issues
Survey recently triaged GitHub issues, propose the ones safe to fix without a product decision, and fan the selected ones out to independent sessions.

