ワンクリックで
release
Cut a release: analyze unreleased work, propose semver bump, draft CHANGELOG, tag, and push
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Cut a release: analyze unreleased work, propose semver bump, draft CHANGELOG, tag, and push
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
| name | release |
| description | Cut a release: analyze unreleased work, propose semver bump, draft CHANGELOG, tag, and push |
| disable-model-invocation | true |
You are the release manager for this project. Your job is to take everything that's been merged to the base branch since the last tag and turn it into a clean, versioned release: the right semver bump, a well-written CHANGELOG entry, and a tagged commit that triggers the release pipeline.
You are the last gate before users see new features. Be deliberate.
/release — Full interactive release flow: analyze -> propose -> draft -> confirm -> tag
/release check — Dry-run only: show what's unreleased, proposed version, CHANGELOG preview
/release notes — Draft CHANGELOG entry only (no tagging, no commits)
The user may also provide a version override: /release v0.3.0
Read forge.toml at the repo root. Extract:
[project]
repo = "org/project" # Used for all gh commands
base_branch = "main" # Branch to release from
[stack]
release_tool = "..." # goreleaser, npm, cargo, pypi, docker, none
If forge.toml is missing, stop and tell the user to run /onboard first.
Read these files before doing anything else:
CHANGELOG.md — current release history and [Unreleased] sectionCLAUDE.md — release process section and project conventionsIf the release_tool from forge.toml has a config file (e.g., .goreleaser.yaml,
package.json, Cargo.toml, setup.py), read it to understand what the release
pipeline does.
Then collect live data:
# Last tag (current released version)
# If this is the first release and no tags exist yet, fall back to the initial commit.
if [ -n "$(git tag --list)" ]; then
LAST_TAG=$(git describe --tags --abbrev=0)
else
echo "No Git tags found; assuming first release. Using initial commit as LAST_TAG."
LAST_TAG=$(git rev-list --max-parents=0 HEAD)
fi
# All commits since last tag (or since initial commit for first release)
git log "${LAST_TAG}"..HEAD --oneline --no-merges
# Merged PRs since last tag — the authoritative source
gh pr list --repo $REPO \
--state merged \
--json number,title,body,mergedAt,labels \
--limit 50 | \
jq --arg since "$(git log --format=%aI -1 -- "${LAST_TAG}")" \
'[.[] | select(.mergedAt > $since)]'
# Any open PRs that might affect release readiness
gh pr list --repo $REPO --state open \
--json number,title,labels \
--label "human/blocked"
# Check if there's anything already in [Unreleased] in CHANGELOG.md
# (read the file — already done above)
Go through each merged PR since the last tag. Classify by conventional commit type (read the PR title prefix or infer from the content):
| Conventional type | CHANGELOG category |
|---|---|
feat: | Added |
fix: | Fixed |
refactor: | Changed |
docs: | Documentation (omit if trivial) |
chore:, ci:, test: | Omit unless user-visible |
perf: | Changed |
| Removal of a feature/command/flag | Removed |
| Announcement that a feature/flag will be removed | Deprecated |
Breaking change (! suffix or BREAKING CHANGE: in body) | Breaking |
For each PR, extract the user-facing impact — not the implementation detail. Write entries that describe what users can now do, not what code changed internally.
Breaking entries MUST carry a Migration: sub-bullet describing the exact
action a user needs to take (e.g., "rename --repo to --scope", "re-init the
graph from scratch"). Changed and Removed entries that require user action
should include one too. Without a migration line, a breaking change is not
releasable — stop and ask the user what the migration is.
Apply semver rules strictly:
Patch (v0.2.0 -> v0.2.1): Only bug fixes. No new commands, no new flags, no
behavior changes. Purely fix: PRs.
Minor (v0.2.0 -> v0.3.0): New features that are backwards-compatible. New
commands, new subcommands, new flags, new API endpoints. Any feat: PR.
Major (v0.2.0 -> v1.0.0): Breaking changes. Removed commands, changed flag
names, incompatible config format changes, breaking protocol changes.
Since we're pre-1.0, v0.x.y: breaking changes bump minor (not major), new features
bump minor, fixes bump patch. When in doubt, bump minor — underversioning (calling a
minor a patch) is the only real mistake.
Pre-release suffixes: If the changes are experimental or the feature set is
incomplete, propose a pre-release tag (e.g., v0.3.0-alpha.1).
State your proposed version and reasoning clearly before proceeding.
Work through this checklist and report the result of each item:
[ ] No open PRs with human/blocked label
[ ] All merged PRs in scope have conventional commit titles (can infer type)
[ ] [Unreleased] section in CHANGELOG.md is accurate (matches what's actually merged)
[ ] STATUS.md is not severely stale (last sync within ~5 PRs) — if STATUS.md exists
[ ] Tests pass on current HEAD (recommend running, but don't block if CI is green)
[ ] Every Breaking entry has a Migration: sub-bullet; every Removed entry that
requires user action has one too
[ ] No open PRs affect the public CLI surface (new commands, new flags, renamed
flags) that are unaccounted for in the CHANGELOG draft
For each failing item, note it but do not abort. The human decides what's a blocker.
Advisory checks (warn but never block):
/product sync if STATUS.md exists and wasn't updated recentlyThe engine exposes ENGINE_VERSION from
packages/engram-core/src/format/version.ts. --version, the last_seen_engine_version
metadata, the GitHub update check, and the engram update asset URL all read
from there. If it doesn't match the tag we're about to push, users will see
stale version strings and the update-available nudge will be wrong.
Run bun run check:versions. It verifies every workspace package.json agrees
with ENGINE_VERSION. It must exit 0.
Before moving on:
ENGINE_VERSION in packages/engram-core/src/format/version.ts to the
proposed tag version (drop the leading v).version field in every workspace package.json to the same value.bun run check:versions again — must pass.Do not tag until this step is green.
Draft the new version section following the existing format in CHANGELOG.md:
## [X.Y.Z] - YYYY-MM-DD
### Added
- **Feature Name** — One sentence describing what users can now do.
Keep it user-facing, not implementation-focused.
### Fixed
- Bug description — what was wrong and what it does now instead.
### Changed
- Changed behavior — old behavior -> new behavior.
### Breaking
- **Feature name** — What changed and what users need to update.
Rules for the draft:
chore:, ci:, test: PRs unless they change observable behavior[Unreleased] already has content in CHANGELOG.md, merge it with what you found
from the PR list (de-duplicate)Show the user everything before touching any files:
Release Summary
---------------
Current version: v0.2.0
Proposed version: v0.3.0
PRs in scope: 12 (10 feat, 2 fix)
Last tag date: 2026-02-18
Pre-release checklist:
[pass] No human/blocked PRs
[pass] All PRs have conventional commit titles
[warn] STATUS.md may be stale (advisory)
[skip] Tests not run (CI was green on last merge)
Proposed CHANGELOG entry:
<draft entry>
Proposed tag: v0.3.0
Tag command: git tag v0.3.0 && git push origin v0.3.0
Proceed? (y to continue, or specify a different version)
Wait for explicit confirmation before proceeding. Do not tag or commit without it.
If the user provides a different version, use that instead. If they say the CHANGELOG needs changes, make them and re-present before continuing.
Move the drafted section into CHANGELOG.md:
## [Unreleased] section content with an empty [Unreleased] stub[Unreleased]The resulting top of CHANGELOG.md should look like:
## [Unreleased]
## [X.Y.Z] - YYYY-MM-DD
### Added
...
Also update docs/whats-new.json. This file is the typed source of truth
for engram whats-new and must be written from the same draft as the
CHANGELOG entry — otherwise users who upgrade will see stale or missing notes.
Schema is documented in docs/whats-new.schema.json. Prepend a new entry to
the top of the versions array:
{
"version": "X.Y.Z",
"date": "YYYY-MM-DD",
"headline": "One-line TL;DR of the release.",
"added": [
{
"title": "engram <new-command>",
"command": "engram <new-command>",
"summary": "User-facing description. What can a user now do?"
}
],
"changed": [],
"deprecated": [],
"breaking": [
{
"title": "...",
"summary": "...",
"migration": "Required for every breaking entry. One sentence of action."
}
],
"removed": [],
"fixes_summary": "N fixes across <areas>."
}
Only include user-facing items. Internal refactors, CI changes, and test improvements belong in CHANGELOG.md (if at all) but not in whats-new. The mental test: "would this entry help a user who just upgraded decide whether to try something new or update a script?"
git add \
CHANGELOG.md \
docs/whats-new.json \
packages/engram-core/src/format/version.ts \
packages/engram-core/package.json \
packages/engram-cli/package.json \
packages/engram-web/package.json \
packages/plugins/*/package.json
git commit -m "chore: release v${VERSION}
Co-Authored-By: Claude <noreply@anthropic.com>"
The release commit should include (a) the CHANGELOG update, (b) the whats-new entry, and (c) the synchronized version bumps from Step 4a. Do not include unrelated changes — it keeps release archaeology easy.
git tag "v${VERSION}"
git push origin $BASE_BRANCH
git push origin "v${VERSION}"
Describe what happens next based on the release_tool from forge.toml:
npm publish or describe the CI pipeline.cargo publish or describe the CI pipeline.Print a clean summary:
Released v${VERSION}
Tag: v${VERSION}
Changelog: CHANGELOG.md updated
Pipeline: https://github.com/$REPO/actions
Release: https://github.com/$REPO/releases/tag/v${VERSION}
Next steps:
- /product sync — update STATUS.md to reflect what shipped (if applicable)
- Monitor https://github.com/$REPO/actions for release pipeline completion
/release check)Run Steps 0-5 only. After the summary in Step 6, stop. Do not modify any files, do not commit, do not tag. Present the full picture — version proposal, checklist, CHANGELOG draft — and exit. This mode is safe to run at any time.
/release notes)Run Steps 0-5. Write the CHANGELOG draft to /tmp/release-notes-draft.md and display
it. Do not update CHANGELOG.md. Do not commit. Do not tag. Useful for reviewing what
the entry would look like before committing to a release.
v0.2.0-alpha.1),
the next release could be another pre-release or a stable release. Ask the user which
they intend unless it's obvious from context.[Unreleased] already has accurate content,
use it. Don't discard it in favor of auto-generated content from PR titles.| Situation | Action |
|---|---|
| Tag already exists | Stop. Show existing tag. Ask if user wants a different version. |
| No PRs since last tag | Report "nothing to release" and exit |
| Push fails (auth) | Show exact error. Never retry with --force. |
| Release pipeline fails | Link to the Actions run. Don't attempt manual recovery. |
| User wants to undo | Provide the exact commands to delete the tag locally and remotely, but do not run them — tagging is reversible but the release pipeline may have already published |
Audit README and STATUS against shipped code — surface documentation drift, then apply targeted edits on approval
Clean up stale git state — remove merged branches (local and remote), prune remote tracking refs, remove stale worktrees, and land on a clean main. Use this whenever the repo feels messy after forge-loop sessions, before starting new work, or when asked to tidy/clean up branches or worktrees. Also triggers for: 'what local work is out of sync?', 'I have stale branches', 'clean up after merging', 'remove old worktrees'.
Guide the creation of a high-quality engram enrichment plugin — js-module or executable transport — with correct manifest, auth, scope, vocab, aliases, cursor, and tests
Run the full forge pipeline end-to-end within this Claude Code session, processing multiple issues autonomously until a stop condition is met