From claude-code-harness
Automates end-to-end releases for Keep a Changelog + GitHub projects: detects version bumps from [Unreleased], promotes CHANGELOG, creates git tags and GitHub Releases after single confirmation gate. Use for release/version bump/publish triggers.
npx claudepluginhub chachamaru127/claude-code-harness --plugin claude-code-harnessThis skill is limited to using the following tools:
Keep a Changelog + GitHub を使う**あらゆるプロジェクト向け**の汎用リリース自動化スキル。
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Keep a Changelog + GitHub を使うあらゆるプロジェクト向けの汎用リリース自動化スキル。
設計原則: 単一確認ゲート。ユーザーは 1 回だけ全体計画を見て承認する。承認後はファイル書き換え → commit → push → tag → GitHub Release までを中断なく実行する。
Literal invocation note: この skill の入口は
/release,/release patch,/release --dry-runのような slash をそのまま使う。
/release # [Unreleased] から bump level を自動推定、確認ゲートへ
/release patch # bump を patch に明示指定
/release minor # bump を minor に明示指定
/release major # bump を major に明示指定
/release --dry-run # 計画の表示のみ、実行しない
このスキルが動くプロジェクトは以下を満たす必要があります:
CHANGELOG.md が Keep a Changelog 形式[Unreleased] セクションが存在するVERSION (単独ファイル)package.json (npm)pyproject.toml (Python, [project] または [tool.poetry])Cargo.toml (Rust, [package])gh CLI がインストール済みで、認証済みorigin が GitHub を指すclaude CLI が plugin tag をサポートしているこれらが満たされない場合、Preflight で detect して abort します。
prUrlTemplate による multi-host review URL は将来候補として認識するが、
このスキルの release automation は今も gh CLI と GitHub remote を primary path とする。
owner / branch / release asset / CI metadata の自動取得は host ごとの差が大きいため、Phase 56.2.3 では docs-only に留める。
[Pre-Gate: 情報収集のみ、ファイル未変更]
↓
1. Preflight (working tree clean / CHANGELOG / gh 等の確認)
2. Version file 自動検出
3. 現在バージョンの読み取り
4. Claude plugin tag preflight (plugin project の場合のみ)
5. [Unreleased] 内容の解析 → bump level 推定
6. 新バージョン算出
7. CHANGELOG 差分ドラフト作成 (メモリ上)
8. GitHub Release notes ドラフト作成 (メモリ上)
★━━━━━━ 単一確認ゲート ━━━━━━★
ユーザーに全計画を 1 回だけ提示:
- 検出された version file
- 現バージョン → 新バージョン
- bump 判定理由 ("[Unreleased] に ### Added があるため minor" 等)
- CHANGELOG 変更プレビュー
- GitHub Release notes ドラフト
- コミット対象ファイル一覧
- 最終アクション (push + tag + release publish)
ユーザー応答:
"yes" → Post-Gate へ進む
"<修正指示>" → 指示に応じて draft を再生成、再確認
"cancel/no" → 何もせず終了
★━━━━━━━━━━━━━━━━━━━━━━━★
↓
[Post-Gate: 承認後、中断なし]
9. Version file 書き換え
10. CHANGELOG.md 書き換え ([Unreleased] → [X.Y.Z] 昇格 + compare link)
11. git add + commit
12. Claude plugin tag validation + tag (plugin project の場合のみ)
13. GitHub Release 用 semver tag (必要な project のみ)
14. git push origin <branch> --tags
15. gh release create vX.Y.Z
16. 完了報告
# 必須ツール
command -v gh >/dev/null || { echo "gh CLI がありません"; exit 1; }
command -v python3 >/dev/null || { echo "python3 が必要です"; exit 1; }
# working tree
if [ -n "$(git status --porcelain)" ]; then
echo "working tree に未コミット変更があります"; exit 1;
fi
# CHANGELOG
[ -f CHANGELOG.md ] || { echo "CHANGELOG.md がありません"; exit 1; }
grep -q "^## \[Unreleased\]" CHANGELOG.md || { echo "[Unreleased] セクションがありません"; exit 1; }
以下を優先順で探索。最初に見つかったものを正本とする:
# Python snippet to run inline
import os, json, re
import tomllib # Python 3.11+
def detect_version_file():
if os.path.exists("VERSION"):
with open("VERSION") as f:
return ("VERSION", f.read().strip(), None)
if os.path.exists("package.json"):
with open("package.json") as f:
data = json.load(f)
return ("package.json", data["version"], None)
if os.path.exists("pyproject.toml"):
with open("pyproject.toml", "rb") as f:
data = tomllib.load(f)
if "project" in data:
return ("pyproject.toml", data["project"]["version"], "[project]")
if "tool" in data and "poetry" in data["tool"]:
return ("pyproject.toml", data["tool"]["poetry"]["version"], "[tool.poetry]")
if os.path.exists("Cargo.toml"):
with open("Cargo.toml", "rb") as f:
data = tomllib.load(f)
return ("Cargo.toml", data["package"]["version"], "[package]")
raise RuntimeError("No supported version file found")
詳細: version-files.md
.claude-plugin/plugin.json が存在する project では、通常の GitHub Release tag とは別に Claude plugin release tag も作る。
ひとことで言うと、git tag -a を手で組み立てる前に、Claude Code 本体の plugin validation に通してから {plugin-name}--v{version} tag を作る。
Pre-Gate ではファイルを書き換えず、以下を確認する:
command -v claude >/dev/null || { echo "claude CLI がありません"; exit 1; }
claude plugin validate .claude-plugin/plugin.json
[ -f VERSION ] || { echo "Claude plugin tag flow では VERSION が必要です"; exit 1; }
VERSION_VALUE="$(tr -d '[:space:]' < VERSION)"
PLUGIN_VERSION="$(python3 -c 'import json; print(json.load(open(".claude-plugin/plugin.json"))["version"])')"
if [ "${VERSION_VALUE}" != "${PLUGIN_VERSION}" ]; then
echo "VERSION と .claude-plugin/plugin.json が不一致なら tag に進まない: VERSION=${VERSION_VALUE}, plugin.json=${PLUGIN_VERSION}"
exit 1
fi
claude plugin tag .claude-plugin --dry-run
この check は 2 つの事故を防ぐためにある:
VERSION と .claude-plugin/plugin.json の version がずれたまま tag を切る事故--dry-run では claude plugin tag が実際に作る tag 名と内部の git tag -a / push 相当コマンドが見える。ここで見えた command を Confirmation Gate の plan に含める。
[Unreleased] 直下の見出しを解析して bump level を決定:
| [Unreleased] 内の見出し | 推定 bump |
|---|---|
### Breaking Changes または ### Removed を含む | major |
### Added を含む (Removed/Breaking なし) | minor |
### Fixed / ### Changed / ### Security のみ | patch |
| 空セクション | error: リリース対象なし |
ユーザーが /release patch|minor|major で明示指定した場合はそちらを優先。
詳細: bump-detection.md
以下を計算、まだ書き込まない:
## [Unreleased] の本文を切り出し## [Unreleased] と ## [<previous>] の間に ## [<new>] - YYYY-MM-DD を挿入した形を作成[Unreleased]: .../compare/v<prev>...HEAD → v<new>...HEAD[<new>]: .../compare/v<prev>...v<new> を追加[Unreleased]: 行から動的抽出## [<new>] セクションの内容を元に、GitHub Release 用のマークダウンを生成:
## What's Changed
**<リリーステーマ(1行)>**
### Before / After
<テーブル>
### Added / Changed / Fixed / Removed
<該当セクションをコピー>
---
🤖 Generated with [Claude Code](https://claude.com/claude-code)
詳細: release-notes.md
すべてのドラフトが揃ったら、ユーザーに 1 回だけ提示:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Release Plan: v<old> → v<new> (<bump>)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Version file: <detected file>
Bump reason: <why this level was chosen>
CHANGELOG changes:
[Unreleased] に <N> 項目の変更を検出
[<new>] - YYYY-MM-DD として確定
Compare link を追加
GitHub Release notes preview:
<最初の 10 行>
...
Files to modify:
- <version file>
- CHANGELOG.md
Final actions:
- git commit -m "chore: release v<new>"
- claude plugin tag .claude-plugin --push --remote origin # plugin project の場合
- git tag -a v<new> # GitHub Release 用 semver tag が必要な場合
- git push origin <branch> --tags
- gh release create v<new>
Proceed? [yes / cancel / <修正指示>]
承認後は中断なしで実行。失敗時は以下の方針:
| 失敗箇所 | 復旧 |
|---|---|
| ファイル書き換え失敗 | そこで abort、ローカルは dirty なまま人間が判断 |
| commit 失敗 | hook 拒否等。ユーザーに原因を提示して修正を促す |
| plugin tag validation 失敗 | VERSION / .claude-plugin/plugin.json / marketplace entry の不一致を修正し、tag 作成には進まない |
| push 失敗 | リモート側の問題。ローカル commit/tag は残す |
gh release create 失敗 | tag は push 済みなので、既存の release.yml セーフティネットが発火するか、手動で gh release create |
.claude-plugin/plugin.json がある project では、commit 後にもう一度 version sync を確認してから plugin tag を作る:
[ -f VERSION ] || { echo "Claude plugin tag flow では VERSION が必要です"; exit 1; }
VERSION_VALUE="$(tr -d '[:space:]' < VERSION)"
PLUGIN_VERSION="$(python3 -c 'import json; print(json.load(open(".claude-plugin/plugin.json"))["version"])')"
if [ "${VERSION_VALUE}" != "${PLUGIN_VERSION}" ]; then
echo "VERSION と .claude-plugin/plugin.json が不一致なら tag に進まない: VERSION=${VERSION_VALUE}, plugin.json=${PLUGIN_VERSION}"
exit 1
fi
claude plugin tag .claude-plugin --dry-run
claude plugin tag .claude-plugin --push --remote origin
claude plugin tag が作る tag は {plugin-name}--v{version} 形式。既存の GitHub Release workflow が vX.Y.Z tag を前提にしている project では、plugin tag とは別に git tag -a v<new> を作る。plugin 配布の tag は claude plugin tag に任せ、GitHub Release 用 semver tag は release automation の互換 surface として扱う。
--dry-run モードPre-Gate 全てを実行し、Confirmation Gate までの内容を表示するが、gate で止まり Post-Gate に進まない。
Claude plugin project の場合、dry-run でも claude plugin tag .claude-plugin --dry-run を実行し、実際に作られる plugin tag 名と push 対象を表示する。ここで VERSION と .claude-plugin/plugin.json が不一致なら、dry-run の時点で止める。
プロジェクトごとの調整に使用:
| 変数 | 説明 |
|---|---|
HARNESS_RELEASE_PROJECT_ROOT | リポジトリルート (デフォルト: $(pwd)) |
HARNESS_RELEASE_BRANCH | push 対象ブランチ (デフォルト: 現在のブランチ) |
HARNESS_RELEASE_HEALTHCHECK_CMD | Preflight で追加実行するコマンド |
HARNESS_RELEASE_SKIP_GH | 1 で GitHub Release 作成をスキップ |
[Unreleased] セクションは必ず以下のいずれかのサブセクションを持つ:
## [Unreleased]
### Added ← minor
### Changed ← patch
### Deprecated ← minor
### Removed ← major
### Fixed ← patch
### Security ← patch
### Breaking Changes ← major (Keep a Changelog 非標準だが一般的)
このスキルはこれらの見出しを機械的に解析するため、見出しの表記揺れ(### Fix / ### Bug Fixes 等)は認識できません。KaCL 標準の見出しを使用してください。
harness-release-internal - 本体 claude-code-harness のリリース時に追加で走らせる harness 固有 preflight/finalization(配布対象外)harness-plan - Plans.md 管理harness-review - リリース前のコードレビューharness-release-internal に分離