Release
Cut a new release of agentd. Releases are tag-driven: pushing a v* tag to
GitHub triggers .github/workflows/release.yml, which cross-compiles the
binaries and publishes a GitHub Release with notes generated by git cliff.
This skill prepares the version bump and changelog, then performs the tag push that kicks off CI.
Invocation
/release— inspect commits since the last tag and suggest the next version (the agent proposes it and asks the user to confirm before proceeding)./release x.y.z— usex.y.zas the new version explicitly (no leadingv).
The argument, if present, is the target version. Validate it matches
^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.]+)?$. Reject anything else and ask the
user to restate it.
Preconditions (check first, stop on any failure)
- Clean working tree — run
git status --porcelain. If there are uncommitted changes, stop and report them; do not bundle unrelated work into a release commit. - On a release-able branch — releases are cut from
main. Confirm withgit rev-parse --abbrev-ref HEAD. If not onmain, ask the user whether to switch (git checkout main && git pull) before continuing. - Up to date with origin —
git fetch --tags originthen verifymainis not behindorigin/main. - Tooling present —
git cliff --version(expect 2.x) andcargo --version.
Step 1 — Determine the current and next version
Read the current version (single source of truth — all crates inherit it):
# Current workspace version
grep -m1 '^version' Cargo.toml # [workspace.package].version
# Latest released tag
git tag -l 'v*' | sort -V | tail -1
[!IMPORTANT] These two can disagree (e.g.
Cargo.tomlat0.2.0but latest tagv0.3.0). If they differ, surface the mismatch to the user and ask which is the true baseline before suggesting a bump. Do not silently pick one.
If a version argument was given: use it as NEW_VERSION. Sanity-check it is
strictly greater than both the current Cargo.toml version and the latest tag.
If it is not greater, warn and ask the user to confirm.
If no argument was given (suggest mode): let git-cliff infer the bump from conventional commits since the last tag:
git cliff --bumped-version # prints e.g. v0.4.0 based on feat/fix/breaking commits
Map the result to NEW_VERSION (strip the leading v). Also show the user a
short summary of what changed so the suggestion is justified:
git cliff --unreleased --bump # preview of the changelog section for the new version
Present the suggested version + the changelog preview and ask the user to confirm or override before making any changes. Do not proceed unprompted.
Step 2 — Bump the workspace version
Only the root Cargo.toml needs editing — every crate uses
version.workspace = true, so the bump propagates automatically.
Edit Cargo.toml:
[workspace.package]
version = "X.Y.Z" # NEW_VERSION
Then refresh the lockfile so the workspace package entries match:
cargo update --workspace # rewrites the agentd-* versions in Cargo.lock
If cargo update --workspace does not update them, run cargo check --workspace
(a build resolves and rewrites Cargo.lock). Confirm Cargo.lock now shows the
new version for the workspace crates.
[!NOTE]
ui/package.jsonis intentionally0.0.0and is not part of the release version. Leave it untouched unless the user explicitly asks.
Step 3 — Regenerate the changelog
The committed CHANGELOG.md is produced by git-cliff (config in cliff.toml).
Regenerate it for the new tag from full history:
git cliff --tag vX.Y.Z --output CHANGELOG.md
Review the diff. Only feat, fix, refactor/perf, chore(deps), and
docs commits appear (per cliff.toml); style/chore/ci/test/build
are skipped. If the new section is empty or obviously wrong, stop and report —
it usually means there are no release-worthy commits since the last tag.
Step 4 — Commit, tag, push
[!CAUTION] Pushing a
v*tag is outward-facing and hard to reverse — it immediately triggers the Release workflow and publishes a public GitHub Release. Show the user exactly what will be committed and pushed, and get explicit confirmation before running the push. Never--forcepush or retag an existing release.
# Stage the release artifacts
git add Cargo.toml Cargo.lock CHANGELOG.md
# Commit (use a release-type message; it is skipped from the changelog by cliff)
git commit -m "chore(release): vX.Y.Z"
# Push the release commit to main
git push origin main
# Create an annotated tag and push it — THIS triggers the Release workflow
git tag -a vX.Y.Z -m "Release vX.Y.Z"
git push origin vX.Y.Z
If the project's branch policy (see CLAUDE.md) blocks pushing the release
commit directly to main, instead open a PR for the chore(release) commit,
get it merged, then create and push the tag from the updated main. Ask the
user which path they want when in doubt.
Step 5 — Verify the release ran
After pushing the tag, confirm CI picked it up:
gh run list --workflow=release.yml --limit 3
gh release view vX.Y.Z # once the workflow completes
The workflow builds binaries for x86_64-unknown-linux-musl,
x86_64-apple-darwin, and aarch64-apple-darwin, then publishes a GitHub
Release with git cliff --current notes and the binaries attached. Report the
release URL (or the in-progress run) back to the user.
Rollback
If something is wrong before the tag is pushed: git reset --soft HEAD~1
and discard the changelog/version edits.
If the tag was already pushed and the release is bad, do not delete or move the tag yourself — that is a destructive, gated operation. Surface the problem to the user and let them decide (typically: cut a new patch release rather than retag).
Source: geoffjay/agentd — distributed by TomeVault.