| name | clawdapus-release |
| description | Automates cutting a Clawdapus release: runs pre-release checks, coordinates with cllama submodule releases if needed, determines the next semver version, backfills any missing changelog entries, sweeps docs (CLI reference, README, manifesto) for updates tied to the release, writes the new version entry in the site changelog, updates the nav dropdown and Latest badge, pushes the release-prep commit to master, prepublishes the pinned infra image refs the release workflow verifies, then tags and pushes the release. Use this skill whenever the user says "release", "cut a release", "new version", "update the changelog and tag", "prepare a release", or anything about shipping a new version of the claw CLI.
|
Release
This skill automates the full release pipeline for Clawdapus. The release
workflow is tag-driven: pushing a semver tag on master triggers
.github/workflows/release.yml (goreleaser builds binaries and creates the
GitHub release) and .github/workflows/deploy-site.yml deploys the updated
site to clawdapus.dev.
cllama and the infra Docker images (cllama, clawdash, claw-wall,
claw-api, hermes-base) are on separate release cycles with manual steps —
this skill covers both sides.
Your job is to prepare everything locally, push the release-prep commit to
master, prepublish whatever pinned images the release verifier needs, then
push the release tag.
Step 1: Pre-release sanity checks
Before touching anything, verify the working tree, auth, and local build:
git status
git fetch --tags
gh auth status -t
go vet ./...
go test ./...
If the working tree is dirty, decide with the user whether those changes are
part of this release or should be stashed/committed separately. Don't mix
unrelated changes into the release commit.
If go vet or go test fails, stop and fix it — goreleaser will fail too.
If the release touched runtime docs or image lifecycle behavior, consider
running the heavier repo checks as well:
go test -tags integration ./...
go test -tags spike -run TestQuickstartDocsRunInFreshDockerContainer ./cmd/claw/...
Step 2: Determine cllama coordination
The cllama/ submodule has its own tags, GitHub releases, and Docker image
(ghcr.io/mostlydev/cllama:latest). If a clawdapus release depends on cllama
changes, release cllama FIRST so the submodule pointer references a tagged,
released commit.
Check whether cllama moved since its last release:
git -C cllama rev-parse HEAD
gh -R mostlydev/cllama release list --limit 3
git -C cllama tag --sort=-v:refname | head -3
git -C cllama log <last-cllama-tag>..HEAD --oneline
Decision tree:
- No cllama changes since last release → skip to Step 3.
- Submodule moved but all commits are already in a released cllama tag →
skip to Step 3.
- Submodule moved past the latest cllama release → cut a cllama release
first (see "Cllama release sub-workflow" below), then continue.
- A cllama tag exists locally/remotely but has no GitHub release → backfill
that release (even if you're also cutting a new one) so the GitHub release
history matches the tag history.
Cllama release sub-workflow
- Pick the next cllama semver (patch / minor) based on the commits.
- If not already tagged, tag in the submodule:
git -C cllama tag v0.X.Y
git -C cllama push origin v0.X.Y
- Create the GitHub release with synthesized notes grouped by theme (not raw
commit list):
gh -R mostlydev/cllama release create v0.X.Y \
--title "v0.X.Y — <short headline>" \
--notes "$(cat <<'EOF'
## Highlights
- **Feature** — user-facing description.
## Fixes
- Fix: brief description.
EOF
)"
- Build and push the multi-arch Docker image (see Step 10). Do this BEFORE the
clawdapus release so the clawdapus image fallback (
docker pull ghcr.io/mostlydev/cllama:latest) picks up the new image.
- Update the submodule pointer in the clawdapus repo if cllama HEAD moved past
the tag you just released, then
git add cllama && git commit.
Step 3: Determine the clawdapus release version
git tag --sort=-v:refname | head -1
gh release list --limit 1
git log <latest-tag>..HEAD --oneline
Analyze the commits and propose a version bump:
- patch (0.x.Y) — bug fixes, doc updates, dependency bumps, diagnostic
additions, internal refactors
- minor (0.X.0) — new features, new commands, new drivers, capability
additions, new pod YAML directives, new CLI flags
- major (X.0.0) — breaking changes (not yet applicable pre-1.0)
Present the proposed version to the user and wait for confirmation. If the
user already specified a version (e.g. "cut v0.5.0"), use that.
Step 4: Backfill missing changelog entries
The site changelog (site/changelog.md) may be behind GitHub releases. Check:
grep '^## v' site/changelog.md
gh release list --limit 20
For each release that exists on GitHub but not in the changelog, fetch its
notes and the underlying PRs/issues so you can write user-facing prose:
gh release view <tag> --json tagName,body,publishedAt
git log <prev-tag>..<tag> --oneline
Insert synthesized entries in descending order between "Unreleased" and the
most recent existing entry. Use the same style as existing entries:
## v0.X.Y {#v0-X-Y}
*YYYY-MM-DD*
- **Feature name** — concise description of what changed and why it matters.
- Fix: brief description of bug fix.
Don't just dump commit hashes — synthesize user-facing prose grouped by theme.
Pull context from referenced PRs/issues (gh pr view N, gh issue view N)
when the commit message alone doesn't explain the "why".
Step 5: Write the new version entry
Convert the ## Unreleased section (if present) into the new version heading.
If there's no Unreleased section, write one from the commits since the last
tag and from the PRs/issues they reference.
The new version gets the <Badge> and anchor:
## v0.X.Y <Badge type="tip" text="Latest" /> {#v0-X-Y}
*YYYY-MM-DD*
- **Feature** — description.
Remove the <Badge type="tip" text="Latest" /> from whichever older version
currently has it. Only one version should have the Latest badge.
Add a fresh empty ## Unreleased section at the top (above the new version)
so there's always a place for future notes:
## Unreleased
<!-- Nothing yet -->
Keep entries deployment-agnostic
Do not name specific deployments or their agents in the changelog. Clawdapus
is a general tool; downstream deployments (Tiverton, the trading desk pod,
individual claws like Boulton/Logan/Westin/etc.) are use cases. Describe the
symptom and the fix generically — "Hermes runners", "Anthropic-format runners",
"Discord-channel-consuming agents", "production deployments", "downstream
operators". The internal investigation that surfaced the bug (talking-stick
rooms, private repos, agent memory) is where deployment-specific context lives.
The same rule applies to GitHub release notes, public issue comments, and
generated docs. Leave historical entries alone unless the maintainer explicitly
asks for a rewrite, but never add a new entry that names a downstream
deployment.
Step 6: Docs sweep
Release changes often ripple into non-changelog docs. Sweep each of these:
CLI reference — site/guide/cli.md
If the release added, removed, or modified anything observable via the CLI,
update the reference. Check every change category:
- New subcommands or flags — add a new section or update the flags table
- Changed default behavior — update the "What it does" description
- New JSON output fields in
claw audit, claw inspect, claw ps,
claw health, claw doctor — document them
- New error conditions or exit codes — add to the command's description
- Removed/renamed things — remove or rename in the docs
Grep for anything that looks stale:
grep -n '<flag-or-command>' site/guide/cli.md
Clawdapus CLI skill — skills/clawdapus/SKILL.md
This file is the canonical CLI skill that Claude agents load when they help
users with claw. It is embedded into the claw binary via go:embed (the
mirror at cmd/claw/skill_data/SKILL.md is regenerated from it) and it also
seeds the clawdapus-cli skill that users install into their
~/.claude/skills/. Any CLI surface change that alters the user-visible
behavior of claw needs to be reflected here, otherwise every agent using
the skill will give out-of-date guidance.
Update whenever the release changes:
- The CLI command list — the top-level table of subcommands (
claw pull,
claw up, claw compose, etc.). Add new commands; remove deleted ones.
- Flag behavior on any covered command.
- Pod YAML directives the skill references (
x-claw.cllama,
x-claw.surfaces, feed subscription syntax, etc.).
- Runtime artifacts the skill describes (
compose.generated.yml,
.claw-runtime/..., CLAWDAPUS.md, AGENTS.generated.md layout).
- New first-class capabilities the skill should teach agents about (new
drivers, new observability endpoints, new skill/feed mechanisms).
After editing, regenerate the embedded mirror so both copies stay in sync:
go generate ./cmd/claw/...
git diff cmd/claw/skill_data/SKILL.md
Commit both files together in the release-prep commit. cmd/claw/skill_data/SKILL.md
is a tracked mirror — if it's left stale, go vet and goreleaser's prehooks
will still pass locally but users who install the skill via the embedded
artifact will get the old content.
Grep for freshness:
diff <(grep -oE 'claw [a-z-]+( [a-z-]+)?' site/guide/cli.md | sort -u) \
<(grep -oE 'claw [a-z-]+( [a-z-]+)?' skills/clawdapus/SKILL.md | sort -u)
The per-user global copy at ~/.claude/skills/clawdapus-cli/SKILL.md is
NOT updated by the release — it's a local convenience copy that users
re-install after the release lands. The release commit only touches the
repo-canonical skills/clawdapus/SKILL.md and its embedded mirror.
README — README.md
Patch releases rarely need README changes. Minor/major releases often do.
Check:
- Quickstart commands still accurate (flags, image names, example paths)
- Feature list / supported drivers list reflects reality
- Version numbers mentioned anywhere (installer, docker image tags)
Manifesto — site/manifesto.md and root MANIFESTO.md
Update only when a release changes the project's scope, vision, or core
mechanics (compiled tools, memory plane, fleet governance, etc.). Most
patch releases leave this untouched.
Guide pages — site/guide/*.md
New features often need a new guide page or updates to an existing one:
- New pod YAML directive → update
claw-pod-yml.md or similar
- New capability (tools, memory, schedule, surfaces) → may need dedicated page
- ADRs in
docs/decisions/ → link from the relevant guide page if the ADR
changes user-visible behavior
Other locations to grep
grep -rn "v0\.X\.Y" site/ README.md examples/ --include='*.md' --include='*.mts'
(Package-lock files, go.sum, and generated artifacts are noise — filter them
out.)
Step 7: Bump pinned runtime infra image tags
internal/infraimages/release_manifest.go holds the image tags that the
released claw binary pulls at runtime. If you don't bump these, users install
the new claw, run claw pull / claw up, and still get the previous
release's clawdash/claw-api/claw-wall/cllama images — the new features in
those images are invisible.
const (
DefaultClawInfraTag = "v0.X.Y"
DefaultClawAPITag = DefaultClawInfraTag
DefaultClawdashTag = DefaultClawInfraTag
DefaultClawWallTag = DefaultClawInfraTag
DefaultClawMCPStdioTag = DefaultClawInfraTag
DefaultCllamaTag = "v0.A.B"
DefaultHermesBaseTag = "v<upstream>-claw.N"
)
Decide which pins to move based on what the release actually touches:
- Release includes new code in
cmd/clawdash/, cmd/claw-api/,
cmd/claw-wall/, or cmd/claw-mcp-stdio/ → bump DefaultClawInfraTag to the new clawdapus release
tag. These images publish in lockstep from the clawdapus tag, so this is
a single value.
- Release includes new cllama code (submodule moved) → bump
DefaultCllamaTag to the cllama release you just cut in Step 2.
- Release rebuilds
hermes-base → bump DefaultHermesBaseTag to the new
published image tag. Use an upstream-derived Clawdapus patch tag
(v<upstream>-claw.N) when rebuilding against the same Hermes upstream
release.
- Pure
claw CLI release (no infra code changes, no submodule move) →
leave the pins at their existing values. The release-prep commit won't touch
release_manifest.go.
Even if the image code didn't change, the corresponding published tag still
needs to exist at the new release version for anything covered by
DefaultClawInfraTag, because the release verifier in
scripts/check-release-infra-tags/ checks
ghcr.io/mostlydev/{claw-api,clawdash,claw-wall,claw-mcp-stdio}:<release-tag> exist. That
prepublish happens in Step 10. The point of Step 7 is to make the released
claw binary actually use those tags.
internal/infraimages/release_manifest_test.go references the constants by
name, so the test doesn't need updating. Running go test ./internal/infraimages/...
after the edit still catches typos.
Step 8: Update the nav dropdown version
In site/.vitepress/config.mts, find the version string in the nav array:
{
text: 'v0.X.Y',
items: [
Replace it with the new version.
Step 9: Commit and push master first
Stage the changed files explicitly — don't use git add -A:
git add site/changelog.md site/.vitepress/config.mts
git add internal/infraimages/release_manifest.go
git add site/guide/cli.md README.md
git add skills/clawdapus/SKILL.md cmd/claw/skill_data/SKILL.md
git add cllama
Commit:
git commit -m "site: release v0.X.Y
Backfill v0.A.B–v0.C.D changelog entries. Add v0.X.Y with [brief summary].
Update nav dropdown and CLI reference."
Push master before creating the release tag. The tag workflow's release job
verifies pinned infra refs immediately, so you need the release-prep commit on
the remote default branch before you start tagging.
git push origin master
If local SSH auth is flaky, switch git to GitHub credential helper and push via
HTTPS instead:
gh auth setup-git
git push https://github.com/mostlydev/clawdapus.git master:master
After the push, wait for the master workflows you just touched to settle:
gh run list --branch master --limit 5
If the push is rejected because the remote is ahead, pull with rebase and push
master again before doing any tag work:
git pull --rebase origin master
git push origin master
Step 10: Prepublish pinned image refs and verify registry visibility
Clawdapus release binaries now hard-fail on missing pinned infra tags. Before
you push the release tag, make sure every required image ref exists in ghcr.io.
The release workflow checks these refs before goreleaser runs:
ghcr.io/mostlydev/claw-api:v0.X.Y
ghcr.io/mostlydev/clawdash:v0.X.Y
ghcr.io/mostlydev/claw-wall:v0.X.Y
ghcr.io/mostlydev/claw-mcp-stdio:v0.X.Y
- whatever fixed refs are currently pinned in
internal/infraimages/release_manifest.go (today: cllama and
hermes-base)
The tag-triggered image workflows for claw-api, clawdash, claw-wall, and claw-mcp-stdio
run too late to satisfy that verifier. If the versioned refs do not already
exist, publish them manually before creating the release tag.
Prerequisite: docker buildx create --name multiarch-builder --use (one-time
setup). Authenticate to ghcr.io: gh auth token | docker login ghcr.io -u <user> --password-stdin.
cllama
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t ghcr.io/mostlydev/cllama:latest \
-t ghcr.io/mostlydev/cllama:v0.X.Y \
--push cllama/
clawdash
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t ghcr.io/mostlydev/clawdash:latest \
-t ghcr.io/mostlydev/clawdash:v0.X.Y \
--push \
-f dockerfiles/clawdash/Dockerfile .
claw-wall
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t ghcr.io/mostlydev/claw-wall:latest \
-t ghcr.io/mostlydev/claw-wall:v0.X.Y \
--push \
-f dockerfiles/claw-wall/Dockerfile .
claw-api
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t ghcr.io/mostlydev/claw-api:latest \
-t ghcr.io/mostlydev/claw-api:v0.X.Y \
--push \
-f dockerfiles/claw-api/Dockerfile .
claw-mcp-stdio
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t ghcr.io/mostlydev/claw-mcp-stdio:latest \
-t ghcr.io/mostlydev/claw-mcp-stdio:v0.X.Y \
--push \
-f dockerfiles/claw-mcp-stdio/Dockerfile .
hermes-base
Tagged per upstream Hermes version, not per clawdapus release:
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t ghcr.io/mostlydev/hermes-base:v<upstream>-claw.N \
--push dockerfiles/hermes-base/
Verify the built image contract before publishing or immediately after pulling
the published tag:
go test -tags spike -run '^TestSpikeHermesBaseImageContract$' ./cmd/claw/...
Verify refs before tagging
Run the release manifest verifier locally before git tag:
go run ./scripts/check-release-infra-tags --release-tag v0.X.Y
Do not stop at the local verifier. If your local Docker client is authenticated
to ghcr.io, private packages can still appear healthy locally while the public
release workflow or end users fail.
Check package visibility explicitly for anything newly pushed:
gh api /users/mostlydev/packages/container/claw-api
gh api /users/mostlydev/packages/container/clawdash
gh api /users/mostlydev/packages/container/claw-wall
gh api /users/mostlydev/packages/container/claw-mcp-stdio
gh api /users/mostlydev/packages/container/hermes-base
For a public package, the JSON should show "visibility":"public".
For the package most likely to have just been created, also verify anonymous
pull token issuance:
curl -fsS 'https://ghcr.io/token?service=ghcr.io&scope=repository:mostlydev/hermes-base:pull'
If GitHub created a new package as private, flip it to public in the GitHub UI
before shipping the release.
Step 11: Tag and push the release
Only after master is pushed and the pinned refs are public and verifiably
present should you create the release tag:
git tag -a v0.X.Y -m "v0.X.Y"
git push origin refs/tags/v0.X.Y
If local SSH auth is broken, use the same HTTPS fallback:
gh auth setup-git
git push https://github.com/mostlydev/clawdapus.git refs/tags/v0.X.Y
Step 12: Verify
After pushing the clawdapus tag, confirm the workflows started:
gh run list --limit 5
Watch the Release workflow through completion:
gh run watch <release-run-id> --exit-status
Then check the GitHub release object and assets:
gh release view v0.X.Y
Also make sure the tag-triggered claw-api Image, clawdash Image,
claw-wall Image, and claw-mcp-stdio Image workflows finished green. They are confirmation that the CI
publishing path still works, but they are not the thing the release job
depended on.
Report the status to the user with links:
- Release:
https://github.com/mostlydev/clawdapus/releases/tag/v0.X.Y
- Site:
https://clawdapus.dev/changelog#v0-X-Y
Edge cases