This document describes the complete release process for beads, including GitHub releases, Homebrew, PyPI (MCP server), and npm packages.
- Overview
- Prerequisites
- Release Checklist
- 1. Prepare Release
- 2. GitHub Release
- 3. Homebrew Update
- 4. PyPI Release (MCP Server)
- 5. npm Package Release
- 6. Verify Release
- Hotfix Releases
- Rollback Procedure
A beads release involves multiple distribution channels:
- GitHub Release - Binary downloads for all platforms
- Homebrew - macOS/Linux package manager
- PyPI - Python MCP server (
beads-mcp) - npm - Node.js package for Claude Code for Web (
@beads/bd)
gitwith push access to steveyegge/beadsgoreleaserfor building binariesnpmwith authentication (for npm releases)python3andtwine(for PyPI releases)ghCLI (GitHub CLI, optional but recommended)
- GitHub: Write access to repository and ability to create releases
- PyPI: Maintainer access to
beads-mcppackage - npm: Member of
@beadsorganization
# Check git
git remote -v # Should show steveyegge/beads
# Check goreleaser
goreleaser --version
# Check GitHub CLI (optional)
gh auth status
# Check npm
npm whoami # Should show your npm username
# Check Python/twine (for MCP releases)
python3 --version
twine --versionBefore starting a release:
- All tests passing (
go test ./...) - npm package tests passing (
cd npm-package && npm run test:all) - CHANGELOG.md updated with release notes (see format below)
- No uncommitted changes
- On
mainbranch and up to date with origin
IMPORTANT: Do this FIRST before running bump-version script.
Add release notes to CHANGELOG.md:
## [0.22.0] - 2025-11-04
### Added
- New feature X
- New command Y
### Changed
- Improved performance of Z
### Fixed
- Bug in component A
### Breaking Changes
- Changed behavior of B (migration guide)Commit the CHANGELOG changes:
git add CHANGELOG.md
git commit -m "docs: Add CHANGELOG entry for v0.22.0"
git push origin mainUse the version bump script to update all version references and create the release tag:
# Dry run - shows what will change
./scripts/bump-version.sh 0.22.0
# Full release with all local installations
./scripts/bump-version.sh 0.22.0 --commit --tag --push --allAvailable flags:
| Flag | Description |
|---|---|
--commit |
Create a git commit with version changes |
--tag |
Create annotated git tag (requires --commit) |
--push |
Push commit and tag to origin (requires --tag) |
--install |
Build and install bd to ~/go/bin AND ~/.local/bin |
--mcp-local |
Install beads-mcp from local source via uv/pip |
--upgrade-mcp |
Upgrade beads-mcp from PyPI (after PyPI publish) |
--restart-servers |
Restart all Dolt servers to pick up new version |
--all |
Shorthand for --install --mcp-local --restart-servers |
This updates:
cmd/bd/version.go- CLI version constantintegrations/beads-mcp/pyproject.toml- MCP server versionintegrations/beads-mcp/src/beads_mcp/__init__.py- MCP Python versionclaude-plugin/.claude-plugin/plugin.json- Plugin version.claude-plugin/marketplace.json- Marketplace versionnpm-package/package.json- npm package versioncmd/bd/templates/hooks/*- Git hook versionsREADME.md- Documentation versionPLUGIN.md- Version requirementsCHANGELOG.md- Creates release entry from [Unreleased]
The --commit --tag --push flags will:
- Create a git commit with all version changes
- Create an annotated tag
v0.22.0 - Push both commit and tag to origin
This triggers GitHub Actions to build release artifacts automatically.
Recommended workflow:
# 1. Update CHANGELOG.md and cmd/bd/info.go with release notes (manual step)
# 2. Bump version and install everything locally
./scripts/bump-version.sh 0.22.0 --commit --all
# 3. Test locally, then tag and push
git tag -a v0.22.0 -m "Release v0.22.0"
git push origin main
git push origin v0.22.0Alternative (step-by-step):
# Just commit
./scripts/bump-version.sh 0.22.0 --commit
# Then manually tag and push
git tag -a v0.22.0 -m "Release v0.22.0"
git push origin main
git push origin v0.22.0GoReleaser automates binary building and GitHub release creation:
# Clean any previous builds
rm -rf dist/
# Create release (requires GITHUB_TOKEN)
export GITHUB_TOKEN="your-github-token"
goreleaser release --clean
# Or use gh CLI for token
gh auth token | goreleaser release --cleanThis will:
- Build binaries for all platforms (macOS, Linux, Windows - amd64/arm64)
- Create checksums
- Generate release notes from CHANGELOG.md
- Upload everything to GitHub releases
- Mark as latest release
If goreleaser doesn't work:
# Build for all platforms
./scripts/build-all-platforms.sh
# Create GitHub release
gh release create v0.22.0 \
--title "v0.22.0" \
--notes-file CHANGELOG.md \
dist/*.tar.gz \
dist/*.zip \
dist/checksums.txt- Visit https://github.com/steveyegge/beads/releases
- Verify v0.22.0 is marked as "Latest"
- Check all platform binaries are present:
beads_0.22.0_darwin_amd64.tar.gzbeads_0.22.0_darwin_arm64.tar.gzbeads_0.22.0_linux_amd64.tar.gzbeads_0.22.0_linux_arm64.tar.gzbeads_0.22.0_windows_amd64.zipchecksums.txt
Homebrew formula is now in homebrew-core. Updates are handled automatically via GitHub Release artifacts.
After the GitHub Release is published, verify the Homebrew package:
# Update Homebrew
brew update
# Install/upgrade
brew upgrade beads # or: brew install beads
# Verify
bd version # Should show 0.22.0The MCP server is a Python package published separately to PyPI.
# Install build tools
pip install build twine
# Verify PyPI credentials
cat ~/.pypirc # Should have token or credentials# Navigate to MCP server directory
cd integrations/mcp/server
# Verify version was updated
cat pyproject.toml | grep version
# Clean old builds
rm -rf dist/ build/ *.egg-info
# Build package
python -m build
# Verify contents
tar -tzf dist/beads-mcp-0.22.0.tar.gz
# Upload to PyPI (test first)
twine upload --repository testpypi dist/*
# Verify on test PyPI
pip install --index-url https://test.pypi.org/simple/ beads-mcp==0.22.0
# Upload to production PyPI
twine upload dist/*# Check package page
open https://pypi.org/project/beads-mcp/
# Install and test
pip install beads-mcp==0.22.0
python -m beads_mcp --versionUpdate the Claude Code marketplace metadata files:
# Update .claude-plugin/marketplace.json
# Change version to match current release
vim .claude-plugin/marketplace.json
# Update claude-plugin/.claude-plugin/plugin.json if needed
vim claude-plugin/.claude-plugin/plugin.json
# Commit changes
git add .claude-plugin/ claude-plugin/.claude-plugin/
git commit -m "chore: Update Claude Code marketplace to v0.22.0"Note: These files define how beads appears in Claude Code's plugin marketplace. Version should match the release version.
The npm package wraps the native binary for Node.js environments.
# Verify npm authentication
npm whoami # Should show your username
# Verify you're in @beads org
npm org ls beads# Navigate to npm package
cd npm-package
# Version should already be updated by bump-version.sh
cat package.json | grep version
# Run all tests
npm run test:all
# Should see:
# ✅ All unit tests passed
# ✅ All integration tests passed# Pack the package
npm pack
# Install globally from tarball
npm install -g ./beads-bd-0.22.0.tgz
# Verify binary downloads correctly
bd version # Should show 0.22.0
# Test in a project
mkdir /tmp/test-npm-bd
cd /tmp/test-npm-bd
git init
bd init
bd create "Test issue" -p 1
bd list
# Cleanup
npm uninstall -g @beads/bd
rm -rf /tmp/test-npm-bd
cd -
rm beads-bd-0.22.0.tgz# IMPORTANT: Ensure GitHub release with binaries is live first!
# The postinstall script downloads from GitHub releases
# Publish to npm (first time use --access public)
npm publish --access public
# Or for subsequent releases
npm publish# Check package page
open https://www.npmjs.com/package/@beads/bd
# Install and test
npm install -g @beads/bd
bd version # Should show 0.22.0
# Test postinstall downloaded correct binary
which bd
bd --helpAfter all distribution channels are updated, verify each one:
# Download and test binary
wget https://github.com/steveyegge/beads/releases/download/v0.22.0/beads_0.22.0_darwin_arm64.tar.gz
tar -xzf beads_0.22.0_darwin_arm64.tar.gz
./bd versionbrew update
brew upgrade beads
bd versionpip install --upgrade beads-mcp
python -m beads_mcp --versionnpm install -g @beads/bd
bd version# Test quick install script
curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
bd versionFor urgent bug fixes:
# Create hotfix branch from tag
git checkout -b hotfix/v0.22.1 v0.22.0
# Make fixes
# ... edit files ...
# Bump version to 0.22.1
./scripts/bump-version.sh 0.22.1 --commit
# Tag and release
git tag -a v0.22.1 -m "Hotfix release v0.22.1"
git push origin hotfix/v0.22.1
git push origin v0.22.1
# Follow normal release process
goreleaser release --clean
# Merge back to main
git checkout main
git merge hotfix/v0.22.1
git push origin mainIf a release has critical issues:
gh release edit v0.22.0 --prereleaseFollow hotfix procedure above to release 0.22.1.
npm deprecate @beads/bd@0.22.0 "Critical bug, please upgrade to 0.22.1"# Can't delete, but can yank (hide from pip install)
# Contact PyPI support or use web interfaceCreate .github/workflows/release.yml:
name: Release
on:
push:
tags:
- 'v*'
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
- uses: goreleaser/goreleaser-action@v4
with:
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
npm:
needs: goreleaser
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
registry-url: 'https://registry.npmjs.org'
- run: cd npm-package && npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
pypi:
needs: goreleaser
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- run: |
cd integrations/mcp/server
pip install build twine
python -m build
twine upload dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}After a successful release:
-
Upgrade local beads-mcp installation to the new version:
# Option 1: Use the bump-version.sh script (recommended during version bump) ./scripts/bump-version.sh <version> --upgrade-mcp # Option 2: Manual upgrade via pip (if installed globally) pip install --upgrade beads-mcp # Option 3: Manual upgrade via uv tool (if installed as a tool) uv tool upgrade beads-mcp # Verify the new version pip show beads-mcp | grep Version # Restart Claude Code or MCP session to pick up the new version # The MCP server will load the newly installed version
Note: The
--upgrade-mcpflag can be combined with other flags:# Update versions, commit, install bd binary, and upgrade beads-mcp all at once ./scripts/bump-version.sh 0.24.3 --commit --install --upgrade-mcp -
Verify the upgraded CLI:
bd version bd doctor quick
-
Announce on relevant channels (Twitter, blog, etc.)
-
Update documentation if needed
-
Close milestone on GitHub if using milestones
-
Update project board if using project management
-
Monitor for issues in the first 24-48 hours
# Delete tag locally and remotely
git tag -d v0.22.0
git push origin :refs/tags/v0.22.0
# Recreate
git tag -a v0.22.0 -m "Release v0.22.0"
git push origin v0.22.0# Version already published, bump version
npm version patch
npm publish# Ensure GitHub release is published first
# Check binary URL is correct
# Verify version matches in package.json and GitHub release# Check .goreleaser.yml syntax
goreleaser check
# Test build locally
goreleaser build --snapshot --cleanBeads follows Semantic Versioning:
- MAJOR (x.0.0): Breaking changes
- MINOR (0.x.0): New features, backwards compatible
- PATCH (0.0.x): Bug fixes, backwards compatible
Examples:
0.21.5→0.22.0: New features (minor bump)0.22.0→0.22.1: Bug fix (patch bump)0.22.1→1.0.0: Stable release (major bump)
- Minor releases: Every 2-4 weeks (new features)
- Patch releases: As needed (bug fixes)
- Major releases: When breaking changes are necessary
- Open an issue: https://github.com/steveyegge/beads/issues
- Check existing releases: https://github.com/steveyegge/beads/releases