Release Process
This is the canonical Squad release runbook. Squad has three release channels and two long-lived branches:
| Source | Version | GitHub | npm | Standalone | Homebrew/WinGet |
|---|---|---|---|---|---|
Insider dispatch from dev |
Generated X.Y.Z-insider.N |
Prerelease | insider |
Yes | Yes |
Release dispatch from dev |
X.Y.Z-preview.N |
Prerelease | preview |
Yes | Yes |
Push to main by promotion workflow |
X.Y.Z |
Stable/latest | latest |
Yes | Yes |
The repository does not use a staging preview branch. Preview is a release
channel, not a branch.
Non-negotiable rules
- Never create release tags or GitHub Releases manually.
squad-release.ymlcreates both. - Never reuse a version. A preview such as
0.14.0-preview.1and stable0.14.0are separate immutable releases. - Keep the root, SDK, and CLI versions identical.
- Set the CLI's SDK dependency floor to
>=VERSION; prerelease workspaces do not match an older stable range. - Add an exact
## [VERSION]entry toCHANGELOG.md. - Merge release preparation to
devand wait for CI before dispatching. - Keep separate Homebrew casks and WinGet identifiers for each channel.
Required credentials
Configure these GitHub Actions secrets:
NPM_TOKEN: an automation-capable npm publish token that does not require an interactive OTP.HOMEBREW_TAP_TOKEN: a classic GitHub PAT withpublic_repo, owned by an account that has write access tobradygaster/homebrew-squad.WINGET_CREATE_GITHUB_TOKEN: a classic GitHub PAT withpublic_repo, owned by the account that maintainstamirdresher/winget-pkgs.
Human release-trigger boundary
Agents may prepare versions, run validation, and recommend exact commands, but
agents must never execute or dispatch live publication, promotion, or recovery
workflows. Only a human executes the real trigger for these live workflows:
squad-release.yml, squad-agents-ai-release.yml, squad-insider-publish.yml,
squad-promote.yml with dry_run=false, squad-version-promote.yml,
squad-npm-publish.yml, or squad-standalone-release.yml.
Treat squad-promote.yml --ref dev -f dry_run=true as human-only too: the
workflow still has actions: write and contents: write, checks out dev
with the workflow token, installs dependencies, and runs the release build and
tests. Do not describe any GitHub Actions release workflow as agent-safe once
it has write-capable credentials or a dispatch path. Stop with verified
commands and evidence for a human to run; human approval alone does not
authorize an agent to fire the trigger.
Prepare a release
Verify dev and main share ancestry before changing versions:
git fetch origin dev main
git merge-base origin/dev origin/main
If that command returns no commit, stop and repair ancestry in a separate PR.
Choose a unique SemVer version and update all package manifests:
VERSION=0.14.0-preview.1
npm version "$VERSION" --workspaces --include-workspace-root --no-git-tag-version
npm pkg set "dependencies.@bradygaster/squad-sdk=>=$VERSION" \
--workspace @bradygaster/squad-cli
npm install --package-lock-only
This updates the root package, both workspaces, and the lockfile. Confirm:
node -p "require('semver').valid('$VERSION')"
grep '"version"' package.json packages/squad-sdk/package.json packages/squad-cli/package.json
grep -F "## [$VERSION]" CHANGELOG.md
SKIP_BUILD_BUMP=1 npm run build
npx vitest run
The validation build must not mutate package versions or the lockfile; check
git diff -- package.json packages/squad-sdk/package.json packages/squad-cli/package.json package-lock.json afterward and stop if any version-only change appears.
Release preparation lands through a normal PR to dev. Do not push directly to
main.
Publish a preview release
Preview versions must contain a prerelease suffix, for example
0.14.0-preview.1.
After the release-preparation PR is merged and dev CI is green:
Human-only reference command: this live publish workflow must be run by a human. Agents must stop, hand off, and not execute it directly.
VERSION=0.14.0-preview.1
gh workflow run squad-release.yml \
--ref dev \
-f confirm_tag="v$VERSION"
gh run watch
The workflow:
- Requires the dispatch ref to be
dev. - Rejects a stable
X.Y.Zversion. - Creates
v$VERSIONand a GitHub prerelease. - Publishes both npm packages with
--tag preview. - Uploads six standalone archives and
SHA256SUMS.txt. - Updates the
squad-previewHomebrew cask andbradygaster.Squad.PreviewWinGet package.
Install the resulting preview:
npm install -g @bradygaster/squad-cli@preview
The same preview is available through brew install --cask squad-preview and
winget install --id bradygaster.Squad.Preview --exact.
Publish an insider release
Start an on-demand snapshot from dev:
Human-only reference command: this live publish workflow must be run by a human. Agents must stop, hand off, and not execute it directly.
gh workflow run squad-insider-publish.yml --ref dev -f dry_run=false
gh run watch
The workflow computes the next immutable X.Y.Z-insider.N version, publishes
npm insider, creates a GitHub prerelease, uploads standalone bundles, updates
the squad-insider Homebrew cask, and opens or reuses the
bradygaster.Squad.Insider WinGet PR.
Publish a stable release
Stable versions must be exactly X.Y.Z. Prepare and merge the stable version
to dev, then human-only validate the sanitized merge without changing
main:
gh workflow run squad-promote.yml --ref dev -f dry_run=true
gh run watch
Do not treat this as an agent-safe command. It still checks out dev with
workflow credentials and runs repository build/test logic. Only a human should
fire it. Start the real promotion:
Human-only reference command: this live publish workflow must be run by a human. Agents must stop, hand off, and not execute it directly.
gh workflow run squad-promote.yml --ref dev -f dry_run=false
gh run watch
squad-promote.yml:
- Merges
origin/devdirectly intomain. - Removes
.ai-team/,.squad/,.ai-team-templates/,team-docs/, anddocs/proposals/from the release tree. - Rejects unresolved conflicts, prerelease versions, mismatched package versions, and missing changelog entries.
- Installs dependencies, builds, and runs release tests.
- Pushes
mainand explicitly dispatchessquad-release.yml.
The explicit dispatch is required because GitHub suppresses push-triggered
workflow runs for commits authenticated with GITHUB_TOKEN. The release
workflow creates the stable tag and GitHub Release, publishes npm latest,
uploads standalone archives, updates Homebrew, and opens or reuses the WinGet
PR.
Verify publication
Use insider, preview, or latest for DIST_TAG:
VERSION=0.14.0
DIST_TAG=latest
npm view @bradygaster/squad-sdk "dist-tags.$DIST_TAG"
npm view @bradygaster/squad-cli "dist-tags.$DIST_TAG"
gh release view "v$VERSION"
The npm values must equal VERSION. The GitHub Release must contain:
squad-linux-x64.tar.gz
squad-linux-arm64.tar.gz
squad-darwin-x64.tar.gz
squad-darwin-arm64.tar.gz
squad-win32-x64.zip
squad-win32-arm64.zip
SHA256SUMS.txt
For every release, also verify the channel's Homebrew cask (squad,
squad-preview, or squad-insider) and WinGet identifier
(bradygaster.Squad, .Preview, or .Insider) reference the new version.
Recovery
The top-level release workflow intentionally does not republish after its tag already exists. Rerun the failed child job, or dispatch the reusable workflow from the branch that owns that release channel while building from the immutable tag.
Stable recovery:
Human-only reference command: this live publish workflow must be run by a human. Agents must stop, hand off, and not execute it directly.
VERSION=0.14.0
gh workflow run squad-npm-publish.yml --ref main \
-f version="$VERSION" -f source_ref="v$VERSION"
gh workflow run squad-standalone-release.yml --ref main \
-f upload=true -f release_tag="v$VERSION" -f source_ref="v$VERSION"
Preview recovery:
Human-only reference command: this live publish workflow must be run by a human. Agents must stop, hand off, and not execute it directly.
VERSION=0.14.0-preview.1
gh workflow run squad-npm-publish.yml --ref dev \
-f version="$VERSION" -f source_ref="v$VERSION"
gh workflow run squad-standalone-release.yml --ref dev \
-f upload=true -f release_tag="v$VERSION" -f source_ref="v$VERSION"
Publication is idempotent. Existing package versions and release assets are
verified rather than overwritten. npm publication fails instead of silently
moving latest or preview away from an existing version.
After a stable release
Prepare the next development version in a normal PR to dev:
NEXT_VERSION=0.15.0-preview.1
npm version "$NEXT_VERSION" --workspaces --include-workspace-root --no-git-tag-version
npm pkg set "dependencies.@bradygaster/squad-sdk=>=$NEXT_VERSION" \
--workspace @bradygaster/squad-cli
npm install --package-lock-only
Do not merge main back into dev; the promotion commit already has dev as
its parent, while the stripped internal state intentionally remains only on
dev.