release

release is a skill for Claude Code from Jebel-Quant/rhiza-claude. It costs 56 tokens per session (9,830 once invoked), scanned A, original, MIT.

A release-preparation command that updates a project's version, rebuilds its changelog, and opens a pull request. On a later run after the pull request is merged, it tags the merged commit.

In plain words
What is it for?
Use it to prepare a release pull request and then publish its version tag after the request is merged.
Why use it?
It handles the two-stage release process required when a pull request is squash-merged, so the tag points to the code that actually landed.

Skill for Claude Code

Written for Claude Code: allowed-tools in frontmatter. Also seen: names the AskUserQuestion tool.

Runs only inside its plugin — its command needs a path that Claude Code sets for a plugin’s own hooks and for nothing else. Install the plugin, not this.

Part of the rhiza plugin — 10 skills, 1 hook shipped together

Good fit Use it to prepare a release pull request and then publish its version tag after the request is merged.

Compare 6 skills from other repositories ↓
Install

Getting it into your agent

This one installs as part of its plugin. Adding the marketplace and installing the plugin brings it with everything else the plugin ships.

Claude Code
/plugin marketplace add Jebel-Quant/rhiza-claude
Claude Code
/plugin install rhiza

Made for: Claude Code.

Or install rhiza, the plugin that ships this one along with the rest of its 10 skills, 1 hook.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for release

README.md
[![agentmods](https://agentmods.dev/badge/skills/jebel-quant/rhiza-claude/release.svg)](https://agentmods.dev/skills/jebel-quant/rhiza-claude/release)
Your own site
<a href="https://agentmods.dev/skills/jebel-quant/rhiza-claude/release"><img src="https://agentmods.dev/badge/skills/jebel-quant/rhiza-claude/release.svg" alt="Measured on agentmods" height="20"></a>
Per session 56 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 9,830 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00056 $0.09830
Opus 5 $0.00028 $0.04915
Sonnet 5 $0.00011 $0.01966
Haiku 4.5 $0.00006 $0.00983

Measured today against content hash ea2040aee2fb, method: parsed. Prices are Anthropic first-party input rates as of 2026-09-08, from the pricing page.

Security

Grade A, and why

release scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured today.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

plugin/skills/release/SKILL.md · 671 lines

How it starts

The opening of the file, as written. The whole thing — 671 lines — stays where its author put it; the contents beside it link to each section on GitHub.

You are running /release in the current working directory's repo. Goal: land the version bump on the default branch through a pull request, like every other change, and tag the commit that actually merged — in one run.

A tag still cannot be cut before the merge, which is why there is a wait in the middle. A tag must point at a commit that exists on the branch you publish from; a squash-merge replaces the branch's commits with a new one, so a tag created before the merge names a SHA that never lands. No reordering of the steps fixes that — the commit to tag does not exist until the request merges. So the run goes through the merge instead of stopping in front of it: it hands the merge to the forge, waits for the bump to appear on the default branch, and tags what landed.

Stage Steps Ends with
Prepare 2–9 the version chosen, the bump and changelog committed on a pushed branch, an open release PR
Land 10–11 auto-merge handed to the forge, and the bump on the default branch
Tag 12–13 the merged commit tagged, the tag pushed, release CI running

phase A and phase B — what step 1a's script reports — name the repo's state, not two runs of this command. Phase A is "nothing pending"; phase B is "a bump is committed that no tag names". An ordinary run starts in A, and steps 10–11 are what put the repo into B; step 12 then tags it. A run that starts in B is one finishing a release whose wait had expired.

The wait can time out, and then the run hands back rather than half-finishing. Review takes as long as it takes and a session does not outlive a weekend; when the wait expires the run reports the open PR and stops, having created no tag. Re-running /rhiza:release finishes the release — step 1a reports phase B and goes straight to step 12. That is not a special case: it is steps 12–13 entered later, and it is why an expired wait leaves nothing to undo.

Never push to the default branch, and never move an existing tag. The run pushes one release branch — the same thing /rhiza:init and /rhiza:update do — and then one tag, onto the commit the forge merged.

The human decision is the version; the checks are the gate. Step 3 stops and makes a person choose the bump, because that is the judgement nothing here can make. What follows is mechanical, so the run carries it through rather than handing back a command to re-type. What keeps that safe is not a second pair of hands, it is step 12's guard: a version that does not strictly increase, or a tag that already exists, stops the run before anything is created. If anything is ambiguous, stop and report.

Be honest about what auto-merge waits for: --auto defers to the required checks the branch has, so a repo with none configured merges the release PR immediately. On such a repo one run really is one run, start to published, and the review window is whatever branch protection actually enforces — not the pause this command used to create by accident. Say so in the report, and if a repo wants a longer look at its release PR, the fix is a required check, not a slower command.

The repo declares where its version lives; you don't guess. bump-my-version reads [tool.bumpversion] (in .bumpversion.toml or pyproject.toml) and rewrites only the explicit search/replace patterns listed there. That is what makes it safe to bump a pyproject.toml version, a plugin manifest and a CI stub pin in one step without touching a dependency that happens to share the current version number. Never hand-edit a version to "help" — if a location is missing, the fix is a config entry.

Argument (optional): $ARGUMENTS — an explicit version like v1.4.0, which skips the menu. Anything that isn't semver-shaped is not a target: note it and offer the menu anyway (step 3).

1. Preconditions

  • A git repo with tags reachable. That's the only structural requirement. /release deliberately does not check for .rhiza/ — nothing in this flow comes from the template: the version locations are repo-owned config, git-cliff reads conventional commits, and tags are tags. (Contrast /quality, where every gate is a synced make target, so its rhiza-managed check is load-bearing.) This is what lets /release release the plugin repo itself as well as a managed application.
  • Clean tree. git status --porcelain; if dirty, stop and show the files. A release is cut from committed work.
  • Releasing what will actually ship. The tag must point at a commit that exists on the branch you publish from. If HEAD is a feature branch whose commits aren't on the default branch yet, stop and say so — that includes a release branch a previous run opened, which is not tagged until it merges. Every run starts from the default branch; the only branch this command is ever on is the one it created in step 8.
  • Version config. [tool.bumpversion] must exist, in .bumpversion.toml or pyproject.toml:
    uvx bump-my-version show current_version
    
    If that fails, stop — the repo hasn't declared where its version lives, and guessing is exactly what this command refuses to do. Report what's needed: a .bumpversion.toml with current_version and one [[tool.bumpversion.files]] entry per location (see step 6 for the stub-pin case). Hold the value as CURRENT.
  • Unless the config is tag-derived, which is how Go and Rust declare it — and any Python project on hatch-vcs, whose [project] carries dynamic = ["version"] and so has no version in a file either. Both go-core and rust-core ship a .bumpversion.toml that deliberately omits current_version: the file is synced, so it must not carry a value only the consuming repo can own — the next /rhiza:update would reset it. Each therefore derives the current version from the newest matching tag, and on a repo that has not been tagged yet the command above fails with "Unable to determine the current version" — a declared version location with nothing to read yet, which is not the same fact as no config at all and must not be reported as one. Tell them apart:
grep -lq '^\[tool\.bumpversion\]' .bumpversion.toml pyproject.toml 2>/dev/null

Hold whether the config is tag-derived, as TAG_DERIVED — step 1a needs it and the command above does not answer it. A missing current_version is the test, not a failing show: on a repo that has been tagged, show succeeds by deriving the version from the tag, so the failure only appears before the first release. Read the key instead:

grep -rn '^current_version' .bumpversion.toml pyproject.toml 2>/dev/null

No match, with a [tool.bumpversion] table present → tag-derived; pass --tag-derived in step 1a. This is the case where phase B has no other evidence, so getting it wrong is what strands the tag. A config that exists and no tags → this is the repo's first release. Hold CURRENT as whatever that language's declared location actually carries, and pass it explicitly in step 6 — 0.0.0 is right for Go only, and passing it to a crate fails the bump:

Read the full file on GitHub · 671 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. today Changed · +191 lines · +6 tokens per session ea2040aee2fb
  2. 8d ago First seen · 480 lines · 50 tokens per session scan A b813235c4607

Subscribe to this mod's changes

release is a skill published in the GitHub repository Jebel-Quant/rhiza-claude (4 stars, last pushed today), licensed MIT. It adds 56 tokens to every session and 9,830 once invoked, about $0.0003 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.