# Release

> Cut a new agentd release. Suggests the next semver version from conventional commits (or accepts an explicit `x.y.z`), bumps the workspace version, regenerates the changelog with git-cliff, then commits, tags, and pushes the `v*` tag that triggers the Release workflow. Use when the user runs /release or asks to publish/cut/tag a new version. Use when this capability is needed.

- Skill: `tomevault-io/release-21` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/release-21`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/release-21/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/release-21

---


# 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` — use `x.y.z` as the new version explicitly (no leading `v`).

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)

1. **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.
2. **On a release-able branch** — releases are cut from `main`. Confirm with
   `git rev-parse --abbrev-ref HEAD`. If not on `main`, ask the user whether to
   switch (`git checkout main && git pull`) before continuing.
3. **Up to date with origin** — `git fetch --tags origin` then verify `main` is
   not behind `origin/main`.
4. **Tooling present** — `git cliff --version` (expect 2.x) and `cargo --version`.

## Step 1 — Determine the current and next version

Read the current version (single source of truth — all crates inherit it):

```bash
# 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.toml` at `0.2.0` but latest tag `v0.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:

```bash
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:

```bash
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`:

```toml
[workspace.package]
version = "X.Y.Z"   # NEW_VERSION
```

Then refresh the lockfile so the workspace package entries match:

```bash
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.json` is intentionally `0.0.0` and 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:

```bash
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 `--force` push or retag an existing release.

```bash
# 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:

```bash
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](https://github.com/geoffjay/agentd) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-06-15 -->

