Releasing
August 1, 2026 · View on GitHub
Releases are produced by .github/workflows/release.yml,
triggered when a v* tag is pushed. The workflow builds every binary for all
supported targets, bundles them into per-platform tarballs with SHA-256
checksums, and publishes a GitHub Release with auto-generated release notes.
Versioning
The single source of truth is version under [workspace.package] in the
root Cargo.toml. construct --version always reports the workspace version.
Use semver (MAJOR.MINOR.PATCH).
The release workflow's verify job refuses to build unless the pushed tag
(minus its leading v) exactly matches the Cargo version — a mistyped tag can
never publish a mislabelled binary.
Cutting a release
-
Bump the version in
Cargo.toml:[workspace.package] version = "0.2.0"Commit it (and run
cargo buildonce soCargo.lockupdates), open a PR, and merge it tomainas usual. -
Tag the merge commit and push the tag:
git checkout main && git pull git tag v0.2.0 git push origin v0.2.0 -
The workflow runs. When it finishes, a GitHub Release for
v0.2.0exists with these assets:construct-aarch64-apple-darwin.tar.gz(macOS, Apple Silicon)construct-x86_64-apple-darwin.tar.gz(macOS, Intel)construct-x86_64-unknown-linux-musl.tar.gz(Linux x86_64, static)construct-aarch64-unknown-linux-gnu.tar.gz(Linux arm64)SHA256SUMS
The tarballs use
construct-<target>names (whichinstall.shandconstruct upgradeexpect).Each tarball contains the single
constructbinary plusREADME.md,LICENSE, andTHIRD_PARTY_NOTICES.md. All adapter and MCP functionality is built intoconstruct(construct __adapter <name>,construct __mcp). -
Review the release notes. The workflow passes
generate_release_notes: trueto the release step, so GitHub fills the release body automatically from the pull requests merged since the previousv*tag — a categorized changelog with contributor credits and a "Full Changelog" compare link. Two consequences worth knowing:- PR titles are the changelog. Each line comes from a merged PR's
title, so clear, conventional titles (
feat(cli): …,fix(daemon): …) produce clean notes. This is also why we squash-merge — one tidy line per change. - You can edit after publishing. Open the release on the releases page, click Edit, and add a summary, highlights, breaking-change callouts, or upgrade notes on top of the generated list.
To group the auto-generated notes into sections (Features / Fixes / …) or exclude certain labels, add a
.github/release.ymlwith category rules; the release step picks it up with no workflow change. - PR titles are the changelog. Each line comes from a merged PR's
title, so clear, conventional titles (
What ships
A single construct binary. All adapter harnesses (shell, claude, codex,
antigravity, smith) and the MCP server are compiled in and dispatched via
hidden subcommands (construct __adapter <name>, construct __mcp). The daemon
calls the same construct binary it was started from when it spawns adapters.
Testing the build without releasing
Run the workflow manually from the Actions tab (workflow_dispatch). It runs
the full build matrix and uploads the tarballs as workflow artifacts, but the
release job is skipped (it only runs for v* tags), so nothing is published.
Homebrew formula
Formula/construct.rb is the macOS Homebrew package. It installs the same
architecture-specific release tarballs produced by the build matrix rather
than compiling the workspace again. Update its version and both macOS
sha256 values in the same PR that bumps the workspace version. The checksums
are available in the generated SHA256SUMS asset after the release workflow
finishes.
Before merging the formula change, run the local style check:
brew style Formula/construct.rb
After installing the repository as a tap, Homebrew's full new-formula audit
can be run with brew audit --new --tap construct-worlds/construct.
Until the formula is accepted into Homebrew Core, macOS users can install it from this repository as a custom tap:
brew tap construct-worlds/construct https://github.com/construct-worlds/construct.git
brew install construct
Once the formula is in Homebrew Core, the tap command is no longer needed.