Shape: CLI
A CLI tool typically ships TWO ways at once: a tarball on GitHub Releases (with platform-specific binaries) AND a package on a system package manager (Homebrew for macOS, with extension points for Cargo / Scoop / Snap / etc.). The release surface is a tag push -- the GitHub Releases page + the Homebrew tap update happen on the same trigger.
When this shape applies
- You author a command-line tool that users install rather than visit.
- You want a GitHub Release with cross-platform binaries AND a Homebrew tap update on the same tag push.
- Optionally, you also publish to other ecosystems (cargo, nuget, rubygems) via the
customadapter pattern.
project-config.yaml
For the primary channels (Homebrew + GitHub Releases), pick one as the canonical
distribution.channel and use the GitHub Releases workflow to drive both.
Homebrew first since it's the user-facing install vector for the macOS audience:
environments:
- id: release
kind: branch-only
branch: main
distribution:
channel: homebrew
registry: https://github.com/myorg/homebrew-tap
manifest: Formula/mytool.rb
release_workflow: gaia-release.yml
tap: myorg/homebrew-tap
The homebrew channel requires the tap sub-field.
For a tool that publishes to GitHub Releases AND tap, the GitHub Releases publish runs first
inside release_workflow; the Homebrew tap update is a downstream job that runs
after the release exists.
Alternatively, if GitHub Releases IS the primary surface:
distribution:
channel: github-releases
registry: https://github.com/myorg/mytool
manifest: Cargo.toml
release_workflow: gaia-release.yml
repo: myorg/mytool
The github-releases channel requires the repo sub-field.
Phase 5 routing
With kind: branch-only + distribution:, the Phase 5 router emits
publish-primary and suggests /gaia-publish. /gaia-deploy
and /gaia-post-deploy both refuse (the tool ships as an artifact, not as a
deployed service).
CI overlays
CLI projects often need a matrix build (Linux + macOS + Windows). Add the matrix job via
gaia-ci.user-jobs.yml:
jobs:
build-matrix:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- run: cargo build --release
Publish to homebrew + github-releases
/gaia-publish
The orchestrator dispatches the channel-matching adapter
(publish-homebrew or publish-github-releases), which invokes the
configured release_workflow. For the combined homebrew + GitHub Releases case,
structure your workflow as a sequence:
- Build cross-platform binaries -> upload as GitHub Release assets.
- Compute SHA-256 hashes of the binaries.
- Update the Homebrew Formula in the tap repo with the new version + hashes.
Other ecosystems (the custom channel)
Ecosystems not first-class in this iteration -- cargo (Rust),
nuget (.NET), cran (R), rubygems (Ruby),
hex (Elixir), helm-chart (Kubernetes) -- use the
custom channel and point at a custom adapter:
distribution:
channel: custom
registry: https://crates.io
manifest: Cargo.toml
release_workflow: gaia-release.yml
adapter_name: cargo-publish
Then create .gaia/custom/adapters/publish-cargo-publish/ with an
adapter-manifest.yaml + a run.sh that drives cargo publish.
See the custom-adapter extension contract for the full schema.
You'll know it worked when
/gaia-config-validateexits 0; the channel-specific sub-field (tapfor homebrew,repofor github-releases) is present./gaia-helpsuggests/gaia-publishon the Phase 5 row.- A
/gaia-publishrun creates a GitHub Release at the version inmanifestand updates the Homebrew tap (or runs the custom adapter for non-first-class channels). - End users can install via
brew install myorg/tap/mytool(homebrew) or download the release tarball directly.