# Release

> リリース単位（単一パッケージか monorepo か）を判定し，SemVer でバージョンを上げ（マニフェストと全参照箇所を整合），bump コミット・タグ・push・About 欄・GitHub Release までの文面を提案．承認後に一気に実行する．「リリースして」「公開して」「バージョンを上げて」など版を公にすることを求められたときに使う．記録するだけなら /capstone:commit を使う．

- Skill: `tomoking2004/release` (Agent Skill)
- Install (CLI): `npx skillmds@latest add tomoking2004/release`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomoking2004/release/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomoking2004 (https://skillmd.com/u/tomoking2004)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/tomoking2004/release

---


対象：リリース単位（単一パッケージ，または独立にバージョン管理される monorepo の各パッケージ）と，その版を公にする一式——マニフェストのバージョン・bump コミット・タグ・GitHub Release・About 欄．

## 現在の状態

!`git rev-parse --git-dir >/dev/null 2>&1 || { echo "（git リポジトリではない）"; exit 0; }; s=$(git status --short); [ -n "$s" ] && echo "$s" || echo "（作業ツリーは清潔）"`

## 現在のブランチ

!`b=$(git branch --show-current 2>/dev/null); [ -n "$b" ] && echo "$b" || echo "（検出不可——git リポジトリでないか detached HEAD）"`

## デフォルトブランチ

!`d=$(gh repo view --json defaultBranchRef --jq .defaultBranchRef.name 2>/dev/null); [ -n "$d" ] && echo "$d" || echo "（取得不可——origin なしか gh が使えない）"`

## 既存タグ一覧（直近20件，命名規則の把握用）

!`t=$(git tag -l --sort=-v:refname 2>/dev/null | head -20); [ -n "$t" ] && echo "$t" || echo "（タグなし）"`

## 直近のタグ

!`t=$(git describe --tags --abbrev=0 2>/dev/null); [ -n "$t" ] && echo "$t" || echo "（タグなし）"`

## 前回タグ以降のコミットと変更ファイル

!`tag=$(git describe --tags --abbrev=0 2>/dev/null); if [ -n "$tag" ]; then r=$(git log --oneline --decorate --name-only "$tag..HEAD" 2>/dev/null); else r=$(git log --oneline --decorate --name-only -40 2>/dev/null); fi; [ -n "$r" ] && echo "$r" || echo "（コミットなし——初コミット前か，前回タグ以降に変更が無くリリース対象なし）"`

## About 欄の現状

!`a=$(gh repo view --json description,homepageUrl,repositoryTopics 2>/dev/null); [ -n "$a" ] && echo "$a" || echo "（取得不可——origin なしか gh が使えない）"`

## 直近の bump コミット本文（書式の手本）

!`tag=$(git describe --tags --abbrev=0 2>/dev/null); b=$([ -n "$tag" ] && git log -1 --format='%B' "$tag" 2>/dev/null); [ -n "$b" ] && echo "$b" || echo "（手本なし）"`

## 直近のリリースノート（様式の手本）

!`tag=$(git describe --tags --abbrev=0 2>/dev/null); n=$([ -n "$tag" ] && gh release view "$tag" 2>/dev/null); [ -n "$n" ] && echo "$n" || echo "（手本なし）"`

## 手順

1. **前提確認**：デフォルトブランチが判明し現在のブランチと異なれば，切り替えを促して中断する．作業ツリーが汚れていれば中断し /capstone:commit を促す．
2. **リリース単位の判定**：バージョンフィールドを持つマニフェスト（`package.json`・`pyproject.toml`・`Cargo.toml`・`plugin.json` 等）をリポジトリ内で探す．ルート直下に一つだけなら**単一パッケージ**として扱う．複数のディレクトリにそれぞれ独立したマニフェストがあれば**マルチパッケージ（monorepo）**とみなし，マニフェストを持つ各ディレクトリを独立したリリース単位とする——単位の粒度が自明でなければ問う．以降の手順は単一パッケージなら全体で一件として，マルチパッケージなら単位ごとに独立して行う．
3. **判定**：各リリース単位について，バージョンの実体（マニフェストの `version` ＋その単位配下の全参照箇所）を特定し，不一致は編集対象として提案に含める．「前回タグ以降のコミットと変更ファイル」を見て，その単位配下に変更が無ければリリース対象から外す（マルチパッケージで対象が一つも無ければ何もしない）．
   - **初版（タグなし）**：上げ幅判定は不要；マニフェストの現バージョンをそのまま初タグとする．バージョンが仮値（0.0.0・0.1.0 等）なら適切な初版番号を問う．
   - **既タグあり**：その単位の直近タグ以降で，その単位配下に触れた Conventional Commits から上げ幅を判定——破壊的→メジャー，`feat`→マイナー，`fix`/`perf`→パッチ；プレ 1.0 の破壊的はマイナーとする．1.0.0 昇格・割れる上げ幅は問う．複数単位にまたがるコミット（リネーム等）は触れた全単位の判定に算入する．マルチパッケージで単位ごとのタグの前例が無ければ，そのタグ以前の変更は当該単位の初版として扱ってよいか確認する．
4. **提案**：対象単位ごとに bump コミット（件名＋本文）とタグ名・リリースノート（タイトル＋本文）を全文で提案し，上げ幅・新バージョン・編集対象を示す．マルチパッケージでは対象外の単位（変更なしで見送り）も列挙し，見落としでないことを示す．About 欄（説明・website・topics）は現状を確定版と突き合わせ，差分があれば新しい全文も提案する——リポジトリに一つだけの設定なので対象単位の数によらず高々一度だけ扱う．既存の下書きを使う場合も全文を提示する——参照だけで承認を取らない．origin が無ければ，リモートリポジトリの作成（名前・About 欄・公開範囲）と origin 設定も提案に含める——承認前に作らない．「文面の基準」に従い，出す前に「固有の走査」を全件通し，**通した証跡を提案に添える**——照らした手本，裏取りした数値・URL，旧バージョンの残存を確かめた範囲を数行で．走査は成果物を残さない唯一の手順で，黙って飛ばしても外からは見えない；添えれば見える．
5. **承認**：平文の提案へのチャットの返信で受ける——選択式ダイアログは提案の表示を妨げるため使わない．承認まで書き込まない．修正指示は反映して再提案．
6. **実行**：承認後に一気に行う．マルチパッケージでは対象単位ごとに a〜c を繰り返し，全単位分が済んでから d 以降へ進む．
   a. その単位配下の全箇所を新バージョンに更新し，`git grep` でその単位配下の旧バージョン残存を確認（単一パッケージなら全体，マルチパッケージならその単位のディレクトリに絞る——他単位は無関係な一致がありうる）．
   b. その単位の対象パスだけステージして bump コミット（マルチパッケージでは件名の scope を単位名にする）．
   c. 既存タグの様式（接頭辞・注釈）に倣ってタグを打つ；前例なければ単一パッケージは `vX.Y.Z`，マルチパッケージは `<unit>-vX.Y.Z` を既定とする．
   d. origin へブランチと**今回打ったタグだけ**を push する（`git push origin <ブランチ>` に続けて `git push origin <タグ>…`）——`--tags` は今回のリリースと無関係な既存タグまで押し出す．origin が無ければ，承認済みの内容でリモートリポジトリを作成し origin に設定してから push する．
   e. About 欄に承認済みの差分があれば `gh repo edit --description "<説明>" --homepage "<URL>" --add-topic <topic>` で適用する（一度だけ）．
   f. `gh` が使えれば（導入・認証済み）対象単位ごとに `gh release create <タグ> --title "<タグ — 要点>" --notes "<本文>"` でノートを公開（非対話実行は notes 系フラグ必須）；使えなければタグ push で完了し理由を告げる．

## 文面の基準

声・用語・言語は既存文（手本，無ければ README 等）に倣う——**手本を読んでから書く**．本節と「固有の走査」が，美の基準（refine プラグインの BEAUTY.md）をリリース文面という媒体へ具体化したもの——**両者を満たせば足り，実行時に他所を参照しない**．

- **bump コミット**：件名は手本に倣う（単一パッケージの例 `chore(release): bump version to X.Y.Z`；マルチパッケージでは scope を単位名にする）；本文で上げ幅の根拠を簡潔に示す．書式はコミットの既定に従う——件名は末尾ピリオド無しで約50字以内，本文は約72字で折り返す；トレーラは付けず，ハーネスが `Co-Authored-By`・`Claude-Session` 等を注入する規約であっても件名と本文だけを残す．
- **リリースノート**：タイトル `<タグ> — <要点>`；冒頭1行サマリ；type 別セクション（Features / Fixes / Refactoring…）の各項目は「**太字リード語** — 詳細」；破壊的・挙動変更は `## ⚠️ Behavior change` 節；関連 PR は `#N`；末尾に `**Full Changelog**: <compare URL>`．載せるのは**利用者に見える変更**——`feat`・`fix`・`perf`・破壊的変更・挙動変更；`chore`・内部 `refactor`・`style`・`test`・開発者向けの `docs` は省く（この取捨は手本のノートだけを見ても復元できない——手本はどのコミットを前にして何を落としたかを示さないので，倣うのでなくこの規則で判定する）．
- **About 欄**：説明はマニフェスト等に既存の記述があれば全文一致させ（単一の真実），無ければ新たに提案する．topics はマニフェストの keywords 等に倣い GitHub の制約（小文字・数字・ハイフン）で揃える；website は実在の URL があるときだけ設定する．

## 固有の走査

- **リリース単位の正確性**：マルチパッケージで，上げる単位が実際に変更のあるものだけか，未変更の単位を巻き込んでいないか確かめる．
- **上げ幅は根拠を示す**：破壊的・`feat`・`fix`/`perf` の判定が，その単位に絞った実際のコミット種別（前回タグ以降の Conventional Commits）と一致することを確かめる．
- **単一の真実**：新バージョンがマニフェストと（その単位配下の）全参照箇所で一致する提案になっているか，実行前に照合する（手順6a の `git grep` は実行後の確認であり代わりにならない）．
- **事実照合**：件名・本文・リリースノート・About 欄の数値・URL・PR 番号は git/gh の実データで裏取りしてから書く．
- **様式踏襲**：書いた全文を手本（上の「直近の bump コミット本文」「直近のリリースノート」）と**並べて**，声・言語・書式・件名・タグ・構成が一致するか確かめる——記憶で照らさない．手本が無ければ既定に沿うかを確かめる．
- **取捨の説明責任**：「前回タグ以降のコミット」を一件ずつ辿り，ノートに載せたか，載せないなら「文面の基準」の省略規則のどれに当たるかを言えるか確かめる——ノートだけを見ても，落ちたものが規則によるのか見落としなのか区別できない．
- **列挙の対称**：リリースノートの type 別セクション・箇条書きは順序原則を定め，粒度とリード語の付け方を揃える．
- **機械的な項は実測**：bump コミットの件名の字数・本文の折り返し幅・トレーラの不在は，目分量でなく数えて確かめる．

## 失敗時

/heal:skill を呼ぶ．

