Eforge release
Release a new version of eforge with release notes, changelog, and GitHub Release - supports patch, minor, and major release typesFrom its SKILL.md
npx -y skills add eforge-build/eforge --skill eforge-releaseAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
SKILL.md
7.0 KB, as published. Nobody here has run it
/eforge-release
Release a new version of eforge. Parses the release type from arguments, checks git status, optionally commits staged changes, generates release notes from the git log, updates CHANGELOG.md, bumps the version on a release PR, tags merged main, pushes the tag, and creates a GitHub Release.
Workflow
Step 1: Parse Release Type
Read $ARGUMENTS to determine the release type:
--patchor empty/unrecognized - patch (default)--minor- minor--major- major
Store the resolved bump type (one of patch, minor, major) for use in later steps.
Step 2: Check Git Status
Run git status --porcelain to determine the repo state.
Three possible outcomes:
- Clean (no output) - proceed to Step 4
- All changes staged (all lines start with
M,A,D,R- no??orMorDlines) - proceed to Step 3 - Unstaged or untracked changes exist (any
??,M,D, orMMlines) - STOP. Tell the user there are unstaged/untracked changes and they need to stage or stash them first. List the problematic files.
Step 3: Commit Staged Changes
Use the /git:commit-message-policy skill to create a commit for the staged changes. Follow the standard commit workflow:
- Run
git diff --cachedto see what's staged - Run
git log --oneline -5for recent commit style - Draft a commit message following Conventional Commits format
- Create the commit
Step 4: Generate Release Notes
Generate release notes from the git log between the previous tag and HEAD.
Find the previous tag:
git describe --tags --abbrev=0
If no tags exist, fall back to the root commit:
git rev-list --max-parents=0 HEAD
Collect commits:
git log <PREV_TAG>..HEAD --oneline
Filter noise - remove any lines matching these patterns:
- Version bump messages: lines matching
^\w+ \d+\.\d+\.\d+$(e.g.,0.2.5) - Contains
enqueue((eforge queue entries) - Contains
cleanup((eforge cleanup commits) - Contains
plan((eforge planning artifacts) - Contains
Merge(merge commits) - Contains
bump plugin version
Clean up commit messages:
- Strip the leading commit hash
- Strip
plan-NN-andhardening-NN-prefixes from conventional commit scopes (e.g.,feat(plan-01-foo): barbecomesfeat(foo): bar,feat(hardening-03-foo): barbecomesfeat(foo): bar) - Extract the scope (text inside parentheses) and the description (text after
:) - Normalize the scope: if it maps to a known package/module, use that; if no scope, use
core
Known scope → package mappings:
engine→ engineclient→ clientmonitor→ monitormonitor-ui→ monitor-uieforge→ eforge (CLI)pi-eforge→ pi-eforgeplugin→ plugin (Claude Code plugin)mcp→ mcpbackends→ backendsdeps,dependencies→ depsqueue→ queuerevert-*orrevert→ coregap-close→ corecleanup→ skip these commits entirely (they're PRD cleanup)- Any other scope → use as-is (e.g.,
backend-new→ backend-new) - No scope → core
Deduplicate by description text - keep only the first occurrence of each description.
Group by conventional commit type into markdown sections:
feat-### Featuresfix-### Bug Fixesrefactor-### Refactoringperf-### Performancedocs-### Documentationchore,ci,build,test-### Maintenance- Anything else -
### Other
Within each section, format entries as:
- **<package>**: <description>
For example:
- **pi-eforge**: add searchable overlays for provider and model selection
- **engine**: subprocess-per-build with crash-safe reconciler
- **core**: Parent scheduler owns sessionId and emits session:start at spawn
Sort entries alphabetically by package name within each section.
Omit empty sections. If no meaningful commits remain after filtering, use "Maintenance release" as the release notes.
Store the generated markdown for use in Steps 5 and 7.
Step 5: Update CHANGELOG.md
Compute the new version before bumping by reading the source-of-truth version from packages/eforge/package.json and incrementing the appropriate component:
node -e "
const v = require('./packages/eforge/package.json').version.split('.');
const bump = '$BUMP_TYPE';
if (bump === 'major') { v[0]++; v[1]=0; v[2]=0; }
else if (bump === 'minor') { v[1]++; v[2]=0; }
else { v[2]++; }
console.log(v.join('.'));
"
(Where $BUMP_TYPE is the resolved bump type from Step 1.)
Note: the root package.json has no version field - this is a pnpm workspace and packages/eforge/package.json is the lockstep source of truth.
Create or update CHANGELOG.md:
- If
CHANGELOG.mddoes not exist, create it with a# Changelogheading - Prepend a new entry immediately after the
# Changelogheading line:
## [X.Y.Z] - YYYY-MM-DD
<release notes from Step 4>
- Trim to a maximum of 20
## [sections. If entries are removed, ensure this footer exists at the bottom of the file:
---
For older releases, see [GitHub Releases](https://github.com/eforge-build/eforge/releases).
Commit the changelog:
git add CHANGELOG.md
git commit -m "docs: update CHANGELOG.md for vX.Y.Z"
Step 6: Bump Version, Open PR, and Tag Merged Main
Use the protected-main flow. Create a release branch, bump without tagging, open a PR, and enable auto-merge:
git checkout -b release/v<version>
pnpm release <bump-type> --no-tag
git push -u origin release/v<version>
gh pr create --base main --head release/v<version> --title "release: v<version>" --body-file <notes-file>
gh pr merge release/v<version> --auto --merge --delete-branch
(Where <bump-type> is the resolved bump type from Step 1.)
pnpm release --no-tag (scripts/bump-version.mjs) bumps packages/eforge/package.json (source of truth), propagates the version to the other lockstep packages (client, engine, monitor, pi-eforge), and commits the lockstep package/version surfaces with message X.Y.Z, but does not create a tag.
After the PR merges, update main, verify the version, create the annotated tag on the merged main commit, and push only that tag:
git checkout main
git pull --ff-only origin main
git tag -a v<version> -m "v<version>"
git push origin refs/tags/v<version>
Step 7: Create GitHub Release and Summary
Create a GitHub Release from the generated release notes:
gh release create v<version> --title "v<version>" --notes-file <notes-file>
Report:
- The new version number
- The release type (patch, minor, or major)
- Link to the GitHub Release
- Remind the user that npm publish is handled by the tag-triggered GitHub Action