Skip to main content
ClaudeWave
Skill5.4k repo starsupdated today

release

This Claude Code skill automates Worktrunk's release workflow from version bump through publishing. Use it when a user requests to release a new version, cut a release, or publish to crates.io and GitHub. The workflow syncs with main, runs tests, checks semver compatibility, bumps the version number, updates the changelog, and manages the merge and tagging process.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/max-sixty/worktrunk /tmp/release && cp -r /tmp/release/.claude/skills/release ~/.claude/skills/release
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Release Workflow

## Steps

1. **Sync the release branch with `main`**: The release worktree's branch lags `main` between releases — it's only reset to `main` after a release lands. Cutting from a stale branch silently drops everything merged since. Fast-forward to the tip of `main` before anything else:
   ```bash
   git fetch origin
   git merge --ff-only origin/main
   ```
   `--ff-only` advances the branch when it's a strict ancestor of `origin/main` and **fails** (rather than creating a merge commit or discarding work) if it has diverged — reconcile manually before continuing. This is the release-branch equivalent of `wt up`, spelled out because the `up` alias rebases each branch onto its own upstream (`origin/release`), not `main`.
2. **Run tests**: `cargo run -- hook pre-merge --yes`
3. **Check current version**: Read `version` in `Cargo.toml`
4. **Review commits**: Check commits since last release to understand scope of changes. Audit the cumulative diff for the data-loss surface (see [Data-Loss Surface Review](#data-loss-surface-review)) before proceeding.
5. **Check library API compatibility**: Run `cargo semver-checks check-release -p worktrunk` (install with `cargo install cargo-semver-checks --locked` if missing). If it reports breaking changes, the bump must be minor (pre-1.0) or major (post-1.0). See "Library API Compatibility" below.
6. **Credit contributors**: Check for external PR authors and issue reporters (see "Credit External Contributors" and "Credit Issue Reporters" below)
7. **Determine release type**: Pick the bump from the changes (including semver-checks result). Ask the user only if the choice is genuinely ambiguous (see below).
8. **Bump version** (must run on a clean tree — before editing CHANGELOG):
   ```bash
   cargo release X.Y.Z -p worktrunk -x --no-publish --no-push --no-tag --no-verify --no-confirm && cargo check
   ```
   This bumps `Cargo.toml` and `Cargo.lock`, then auto-commits. We'll reset this commit in step 10 to fold in the CHANGELOG.
9. **Update CHANGELOG**: Add `## X.Y.Z` section at top with changes (see MANDATORY verification below)
10. **Commit**: Reset the auto-commit from step 8, stage everything, and create the final release commit:
    ```bash
    git reset --soft HEAD~1 && git add -A && git commit -m "Release vX.Y.Z"
    ```
11. **Merge to main**: `/gpk` — opens a PR, waits for CI, merges via PR (preserves worktree)
12. **Tag the merge commit and push**: After `/gpk` squash-merges, the local branch HEAD is not the commit on main. Tag the PR's merge commit explicitly so the tag is reachable from main:
    ```bash
    MERGE_SHA=$(gh pr view --json mergeCommit --jq '.mergeCommit.oid')
    git tag vX.Y.Z "$MERGE_SHA" && git push origin vX.Y.Z
    ```
13. **Wait for the release workflow**: The tag push triggers `release.yaml`. Launch a ci-reporter agent to monitor the run through to completion (avoid `gh run watch` — it can hang); the run ID comes from:
    ```bash
    gh run list --workflow=release.yaml --event=push --branch=vX.Y.Z --limit 1 --json databaseId --jq '.[0].databaseId'
    ```

`release.yaml` builds binaries and publishes to crates.io, Homebrew, and winget automatically.

## Data-Loss Surface Review

Worktrunk's worst failure is silently destroying a user's work. The per-PR review (`running-tend`, "Data-Loss Surface") is the first gate; the release is the second, where the whole diff since the last release is visible at once.

This review optimizes for recall: find every change that could touch the deletion surface, accept false positives, then adjudicate each candidate. Missing one real loss path costs far more than reviewing a false alarm.

A keyword grep alone is insufficient. It finds only what someone thought to pattern-match, and an agent handed the grep anchors on it and inherits its blind spots. So fan out independent finders, most of them without the grep, and analyze every candidate they surface.

### Find: independent finders, recall over precision

Launch 3-5 finder subagents in parallel over the cumulative diff (`git log v<last-version>..HEAD -p`) and the code it touches, including anything that calls into or is called by the changed code. Each works independently: do not let them share findings during this phase, and do not collapse them onto one method. Each returns candidate locations with a one-line reason, erring toward over-reporting.

Give each a distinct charter. At least two receive no grep and no keyword list, so they reason from the code instead of pattern-matching:

- **Behavioral (no grep):** read each change and ask what it could destroy: files, branches, worktrees, uncommitted or untracked work, committed-but-unpushed commits. Flag any change whose worst case is lost user data.
- **Blast-radius (no grep):** for every function and file the diff touches, trace callers and callees. Flag any path that can now reach a destructive primitive (branch deletion, worktree removal, filesystem removal, history rewrite), even when that call sits outside the diff.
- **Automation diff (no grep):** compare shipped automation before and after: `plugins/*/hooks/hooks.json`, `hooks/hooks.json`, `hooks/wt.sh`, and skill or alias examples users copy. Flag any new or altered invocation that removes or force-overwrites anything.
- **Keyword scan (grep):** one finder runs the pattern filter over the full diff as a cross-check, never as the primary method. It takes no pathspec; a path allowlist would recreate the blind spots the no-grep finders exist to avoid (the densest destructive code, the trash sweep in `src/commands/process.rs`, sits outside `src/git/`).
  ```bash
  git log v<last-version>..HEAD -p \
    | grep -nE -- '--force-delete|--force| -D| -f |branch -[dD]|worktree remove|reset --hard|checkout -f|clean -[fdx]|remove_dir_all|remove_file|rm -rf'
  ```

### Analyze: adjudicate each candidate

Pool the candidates, dedupe, and analyze each against the data-safety invariants in `CLAUDE.md` and the FAQ "What can W