release-sidecar
The release-sidecar skill automates the complete release workflow for the sidecar Go project, including semantic versioning, dependency updates via `go get`, go.mod validation, CHANGELOG management, and GoReleaser integration for automated binary distribution. Use this skill when preparing a new version for public release after verifying prerequisites like passing tests, clean git state, and proper credential configuration.
git clone --depth 1 https://github.com/marcus/sidecar /tmp/release-sidecar && cp -r /tmp/release-sidecar/.claude/skills/release-sidecar ~/.claude/skills/release-sidecarSKILL.md
# Releasing a New Version ## Prerequisites - Go installed matching go.mod version - Clean working tree (`git status` shows no changes) - All tests passing (`go test ./...`) - GitHub CLI authenticated (`gh auth status`) - No `replace` directives in go.mod - GoReleaser configured (`.goreleaser.yml` in repo root) - `HOMEBREW_TAP_TOKEN` secret exists in GitHub repo settings **Beware of go.work**: A parent `go.work` file can silently use local dependencies instead of published versions. Always use `GOWORK=off` when updating dependencies and testing builds. ## Release Process ### 1. Determine Version Follow semantic versioning: - **Major** (v2.0.0): Breaking changes - **Minor** (v0.2.0): New features, backward compatible - **Patch** (v0.1.1): Bug fixes only ```bash git tag -l | sort -V | tail -1 ``` ### 2. Update td Dependency Sidecar embeds td as a Go module. Always update to latest before releasing: ```bash GOWORK=off go get github.com/marcus/td@latest GOWORK=off go mod tidy ``` ### 3. Verify go.mod Ensure no `replace` directives (they break `go install`): ```bash grep replace go.mod && echo "ERROR: Remove replace directives before releasing!" && exit 1 ``` ### 4. Verify Build Without go.work ```bash GOWORK=off go build ./... ``` If this fails with "undefined" errors, the required dependency version hasn't been published yet. ### 5. Update CHANGELOG.md ```markdown ## [vX.Y.Z] - YYYY-MM-DD ### Features - New feature description ### Bug Fixes - Fix description ### Dependencies - Dependency update description ``` ```bash git add CHANGELOG.md git commit -m "docs: Update changelog for vX.Y.Z" ``` ### 6. Create and Push Tag ```bash git tag vX.Y.Z -m "Brief description of release" git push origin main && git push origin vX.Y.Z ``` ### 7. GitHub Release + Homebrew Tap (Both Automated) Pushing the tag triggers `.github/workflows/release.yml`, which has **two jobs**: 1. **`goreleaser`** — creates the GitHub Release, builds/attaches binaries for darwin/linux (amd64/arm64), and generates `checksums.txt`. The GitHub release notes are auto-generated by GoReleaser from commit subjects (excluding `docs:`/`test:`/`ci:`/`chore:`) — these are separate from the hand-written `CHANGELOG.md`, which is bundled into the archives. 2. **`update-homebrew-tap`** — runs after `goreleaser`, computes the source tarball's sha256, and rewrites the tag URL + sha256 in `Formula/sidecar.rb` in `marcus/homebrew-tap`, then commits and pushes. > GoReleaser-the-tool does not publish the formula (there is no `brews:` block, > because the formula builds from source to dodge macOS Gatekeeper warnings). > The bump is done by the **`update-homebrew-tap` job**, not by GoReleaser. > Earlier versions of this skill said the tap had to be bumped by hand — that is > no longer true for `sidecar.rb`. ### 7b. Manual Homebrew Steps (only when needed) For a normal sidecar-only release you do **nothing** here — the `update-homebrew-tap` job bumps `Formula/sidecar.rb` for you. The job is a no-op if the formula is already current (it checks `git diff --cached --quiet`). You only touch the tap by hand in two cases: - **The job failed** (e.g. token/permission error). Re-run the `update-homebrew-tap` job from the Actions UI, or bump it manually: ```bash curl -sL "https://github.com/marcus/sidecar/archive/refs/tags/vX.Y.Z.tar.gz" | shasum -a 256 cd /opt/homebrew/Library/Taps/marcus/homebrew-tap # or clone marcus/homebrew-tap # Edit Formula/sidecar.rb — update the URL tag and sha256 git add Formula/sidecar.rb && git commit -m "sidecar: bump to vX.Y.Z" && git push ``` - **Co-releasing td and/or nightshift.** The job only touches `sidecar.rb`. If this release also bumps the td dependency (step 2) or nightshift, update `Formula/td.rb` / `Formula/nightshift.rb` by hand the same way. ### 8. Verify ```bash # Check workflow succeeded gh run list --workflow=release.yml --limit=1 # Check release exists with binaries gh release view vX.Y.Z # Test Homebrew install brew install marcus/tap/sidecar sidecar --version # Test go install (critical!) GOWORK=off go install github.com/marcus/sidecar/cmd/sidecar@vX.Y.Z sidecar --version # Should output: sidecar version vX.Y.Z # Test update notification go build -ldflags "-X main.Version=v0.0.1" -o /tmp/sidecar-test ./cmd/sidecar /tmp/sidecar-test # Should show toast: "Update vX.Y.Z available!" ``` ## Version in Binaries Version is embedded at build time via ldflags: ```bash go build -ldflags "-X main.Version=v0.2.0" ./cmd/sidecar go install -ldflags "-X main.Version=v0.2.0" ./cmd/sidecar ``` Without ldflags, version falls back to: 1. Go module version (if installed via `go install`) 2. Git revision (`devel+abc123`) 3. `devel` ## Update Mechanism On startup, sidecar checks `https://api.github.com/repos/marcus/sidecar/releases/latest`, compares `tag_name` against current version, and shows a toast if newer. Results cached for 3 hours. Pre-release suffixes (`-rc1`, `-beta`) are stripped for comparison. Dev versions skip the check. ## Recovery: Fixing a Bad Release 1. Publish a new patch release with fixes 2. For critical bugs, release immediately 3. Delete unpublished GitHub release: `gh release delete vX.Y.Z` 4. Keep git tags to preserve history 5. If GoReleaser workflow fails, re-run locally: `goreleaser release --clean` ## Install Methods 1. **Setup script**: `curl -fsSL https://raw.githubusercontent.com/marcus/sidecar/main/setup.sh | bash` 2. **Homebrew**: `brew install marcus/tap/sidecar` 3. **Download binary**: from GitHub Releases page 4. **From source**: `go install github.com/marcus/sidecar/cmd/sidecar@latest` ## Checklist - [ ] Tests pass - [ ] Working tree clean - [ ] td dependency updated (`GOWORK=off go get github.com/marcus/td@latest`) - [ ] No `replace` directives in go.mod - [ ] Build works without go.work (`GOWORK=off go build ./...`) - [ ] CHANGELOG.md updated - [ ] Version follows semver - [ ] Tag created and pushed - [ ] Git
>
Create declarative modals using the modal library API. Covers modal types (confirm, input, select, form), sections (Text, Buttons, Input, Textarea, Checkbox, List, When, Custom), rendering with OverlayModal, and keyboard/mouse handling. Use when adding modals or dialogs to the application.
>
Create prompts for sidecar workspaces. Covers prompt structure (name, ticketMode, body), template variables (ticket with fallbacks), config file locations (global vs project), and scope overrides. Use when creating or modifying prompts in sidecar config files.
>
>
Creating and using feature flags in sidecar for gating experimental functionality. Covers flag registration, checking flags in code, config file and CLI overrides, and priority resolution. Use when adding feature flags, toggling features, or gating new functionality behind flags.
>