release-setup
Set up automated cross-platform binary releases for a Go project
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Set up automated cross-platform binary releases for a Go project
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Build a lightweight single-file web application with no external dependencies
Walk through project setup improvements for efficient AI-assisted development
Work through a project's bug list autonomously, fixing bugs in priority order
Generate or update project README documentation
Evaluate code quality with letter grades across multiple dimensions
Discover and import Claude Code skills into this shared repo
| name | release-setup |
| description | Set up automated cross-platform binary releases for a Go project |
Set up automated binary releases for a Go CLI project. Every push to main builds and publishes cross-platform binaries. No tags, no manual release steps.
Before starting, read the project to determine:
git remote get-url originAsk the user which platforms to target. Default: macOS ARM, Linux x86_64, Linux ARM. Optional: Windows x86_64.
Work through each step, implementing immediately. Show what you're creating and why.
The version string format is: YYYY-MM-DD HH:MM <branch> <short-sha> <dev|release>
Examples:
2026-04-10 14:22 main fa431a dev2026-04-10 14:22 main fa431a releaseIn the source code, find where the version is defined. Replace any hardcoded version string with a var that defaults to "dev" and is set at build time via ldflags:
For Go:
// version is set at build time via -ldflags "-X main.version=..."
var version = "dev"
For Rust (in build.rs + env!):
let version = option_env!("BUILD_VERSION").unwrap_or("dev");
In the Makefile (or equivalent build config), set VERSION and pass it via ldflags:
For Go:
VERSION = $(shell date -u +'%Y-%m-%d %H:%M') $(shell git rev-parse --abbrev-ref HEAD) $(shell git rev-parse --short HEAD) dev
GOFLAGS = -trimpath -ldflags="-s -w -X 'main.version=$(VERSION)'"
If the project has an existing hardcoded version constant, remove it. If there's a make release target that manages tags, remove it.
Create .github/workflows/release.yml:
name: Release
on:
push:
branches:
- main
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Build binaries
run: |
SHA=$(git rev-parse --short HEAD)
DATE=$(TZ=UTC date +'%Y-%m-%d %H:%M')
VERSION="${DATE} main ${SHA} release"
LDFLAGS="-s -w -X 'main.version=${VERSION}'"
GOOS=darwin GOARCH=arm64 go build -trimpath -ldflags="$LDFLAGS" -o dist/<BINARY>-darwin-arm64 .
GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="$LDFLAGS" -o dist/<BINARY>-linux-amd64 .
GOOS=linux GOARCH=arm64 go build -trimpath -ldflags="$LDFLAGS" -o dist/<BINARY>-linux-arm64 .
- name: Create or update release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release delete latest --yes 2>/dev/null || true
git push origin :refs/tags/latest 2>/dev/null || true
gh release create latest \
dist/<BINARY>-darwin-arm64 \
dist/<BINARY>-linux-amd64 \
dist/<BINARY>-linux-arm64 \
--title "Latest" \
--notes "Built from main at $(git rev-parse --short HEAD)" \
--latest
Replace <BINARY> with the actual binary name. If Windows is requested, add:
GOOS=windows GOARCH=amd64 go build -trimpath -ldflags="$LDFLAGS" -o dist/<BINARY>-windows-amd64.exe .
and include it in the gh release create assets list.
Adapt the setup step for non-Go projects (e.g. actions/setup-node, rustup, etc.).
Check if the user has a homebrew tap repo. Look for ../homebrew-tap or ask. If they have one, create a formula.
Create Formula/<binary>.rb in the tap repo:
class <BinaryClass> < Formula
desc "<project description>"
homepage "https://github.com/<owner>/<repo>"
version "latest"
license "<license>"
on_macos do
on_arm do
url "https://github.com/<owner>/<repo>/releases/download/latest/<binary>-darwin-arm64"
end
end
on_linux do
on_arm do
url "https://github.com/<owner>/<repo>/releases/download/latest/<binary>-linux-arm64"
end
on_intel do
url "https://github.com/<owner>/<repo>/releases/download/latest/<binary>-linux-amd64"
end
end
def install
bin.install Dir.glob("<binary>-*").first => "<binary>"
end
test do
assert_match "<binary>", shell_output("#{bin}/<binary> --version")
end
end
Commit and push the formula to the tap repo.
Add or update the Install section in the project's README.md. Place it near the top, after the project description and any quick-start examples:
## Install
### Homebrew (macOS/Linux)
\`\`\`sh
$ brew install <owner>/tap/<binary>
\`\`\`
### Download binary
Download the latest binary for your platform:
\`\`\`sh
# macOS (Apple Silicon)
$ curl -Lo <binary> https://github.com/<owner>/<repo>/releases/latest/download/<binary>-darwin-arm64
# Linux (x86_64)
$ curl -Lo <binary> https://github.com/<owner>/<repo>/releases/latest/download/<binary>-linux-amd64
# Linux (ARM)
$ curl -Lo <binary> https://github.com/<owner>/<repo>/releases/latest/download/<binary>-linux-arm64
\`\`\`
Then make it executable and move it to your PATH:
\`\`\`sh
$ chmod +x <binary>
$ sudo mv <binary> /usr/local/bin/
\`\`\`
### From source
Requires Go 1.21+:
\`\`\`sh
$ go install <module>@latest
\`\`\`
If Windows was included, add a Windows section to the download instructions.
Skip the Homebrew subsection if no tap was set up. Skip "From source" if not applicable.
After implementing all steps:
make build and check <binary> --version shows the dev version stringgh run watch to confirm the workflow succeedscurl -Lo <binary> https://github.com/<owner>/<repo>/releases/latest/download/<binary>-<platform> and verify the downloaded binary runs and shows the release version stringbrew install <owner>/tap/<binary>latest GitHub release is replaced on every push to main.<binary>-<os>-<arch> (e.g. myapp-linux-amd64). Windows gets .exe suffix.