From pippin
Cut a new pippin release — bump version, tag, push, update Homebrew tap, verify install. Use when the user says "release vX.Y.Z", "ship pippin", "cut a release", or "bump pippin".
How this skill is triggered — by the user, by Claude, or both
Slash command
/pippin:releaseThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Prescriptive end-to-end release procedure. Every step matters; skipping the tap update or the dual-install verify leaves users on a stale binary.
Prescriptive end-to-end release procedure. Every step matters; skipping the tap update or the dual-install verify leaves users on a stale binary.
User says: "release pippin", "ship vX.Y.Z", "cut a release", "bump pippin to X.Y.Z", or anything equivalent. Confirm the target version with the user before starting if not specified.
main (git status shows nothing).bd ready shows no in-progress release work).swift test passed locally./opt/homebrew/..., accessible from anywhere, but releases should land on main).Edit pippin/Version.swift — bump the version constant. Semantic versioning: patch for fixes, minor for new commands/features, major for breaking CLI/agent-JSON changes.
## [X.Y.Z] - YYYY-MM-DD section with the changes.[Unreleased] comparison link's base to the new version tag.[X.Y.Z]: https://github.com/mattwag05/pippin/compare/vPREV...vX.Y.Z.If new commands or subcommands shipped, add them to the README's command table or examples.
make test
Must pass with 0 failures. If anything red, stop and fix before continuing.
git add pippin/Version.swift CHANGELOG.md README.md
git commit -m "chore: bump to vX.Y.Z"
git tag -a vX.Y.Z -m "vX.Y.Z"
The annotated tag (-a) is required — bare git tag vX.Y.Z fails with "no tag message" in the Homebrew tap update step.
git push origin main --tags
Before tagging, run make ci (or make ci-vm) locally and confirm green — the GitHub ci.yml build/test workflow is disabled, so nothing on push catches build/test failures.
The GitHub release.yml workflow is also disabled (pippin-6qi — its macos-15 runner kept cancelling). The tag push fires the self-hosted .forgejo/workflows/release.yaml (publishes to the tailnet Forgejo), but the GitHub release is published locally — do it now:
make tarball # → .build/release-artifacts/pippin-X.Y.Z-arm64-macos.tar.gz
awk "/^## \[X.Y.Z\]/{f=1;next} f&&/^## \[/{exit} f{print}" CHANGELOG.md > /tmp/notes.md
gh release create vX.Y.Z --title "vX.Y.Z — pippin" --notes-file /tmp/notes.md --verify-tag \
.build/release-artifacts/pippin-X.Y.Z-arm64-macos.tar.gz
This reproduces exactly what the old release.yml produced (title, changelog body, arm64 asset, not a pre-release). Verify with gh release view vX.Y.Z.
The formula installs the pre-signed release tarball (not a from-source build) so brew binaries carry a stable Developer ID signature. Step 6 must have run first — the asset has to exist on the GitHub release before the formula points at it. Edit /opt/homebrew/Library/Taps/mattwag05/homebrew-tap/Formula/pippin.rb and update:
Note (pippin-6sf, corrects pippin-jt9): the signature gives a stable code identity, but brew TCC grants do NOT persist across upgrades — macOS keys a bare-CLI grant on the binary's resolved path, and brew's path is the versioned
Cellar/<ver>/bin/pippin, so each upgrade re-prompts. The durable, TCC-granted home is~/.local/bin/pippin(stable copied path viamake install— step 10). Agents/scheduled tasks point there, not at brew.
url → https://github.com/mattwag05/pippin/releases/download/vX.Y.Z/pippin-X.Y.Z-arm64-macos.tar.gzversion → X.Y.Zsha256 → shasum -a 256 .build/release-artifacts/pippin-X.Y.Z-arm64-macos.tar.gz (must match the uploaded asset)assert_match version string → the new versionThen lint: brew style mattwag05/tap/pippin (must be clean). The test do block asserts both the version and a Developer ID Application signature — if the asset is ad-hoc, the formula test fails by design.
cd /opt/homebrew/Library/Taps/mattwag05/homebrew-tap
git add Formula/pippin.rb
git commit -m "pippin vX.Y.Z"
git push
brew upgrade pippin && pippin --version
Expected: prints the new version.
If this machine has both /opt/homebrew/bin/pippin and ~/.local/bin/pippin (from make install), ~/.local/bin sits earlier on PATH and shadows brew. brew upgrade pippin alone leaves which pippin pointing at the stale local copy.
which pippin && pippin --version
If which returns ~/.local/bin/pippin, also run:
make install
The claude-plugins pippin plugin's .mcp.json uses bare pippin, so the shadowed version is what Claude Code actually spawns as the MCP server — both must be current.
release.yml is disabled (pippin-6qi — macos-15 runner kept cancelling), so a tag push never auto-creates the GitHub release. This is expected — publishing it locally is step 6, not a recovery action. If you skipped it, run the make tarball + gh release create recipe in step 6.cd /opt/homebrew/Library/Taps/mattwag05/homebrew-tap && git pull --rebase && git push.brew upgrade says "already up to date": brew update first, then retry.pippin --version still shows old version: see step 10 — almost always the dual-install shadow.bd close the release issue until step 10 is verified green.Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub mattwag05/mw-plugins --plugin pippin