ハーネス導入済みプロジェクトを最新版に安全アップデート(バージョン検出→バックアップ→非破壊更新)
Updates harness-installed projects to the latest version with safe backup and non-destructive merging.
/plugin marketplace add Chachamaru127/claude-code-harness/plugin install claude-code-harness@claude-code-harness-marketplaceoptional/既にハーネスが導入されているプロジェクトを、最新バージョンのハーネスに安全にアップデートします。 バージョン検出→バックアップ→非破壊更新の流れで、既存の設定やタスクを保持しながら最新機能を導入できます。
.claude-code-harness-version でバージョン検出.claude-code-harness-version ファイルを確認:
if [ -f .claude-code-harness-version ]; then
CURRENT_VERSION=$(grep "^version:" .claude-code-harness-version | cut -d' ' -f2)
echo "検出されたバージョン: $CURRENT_VERSION"
else
echo "⚠️ ハーネス未導入のプロジェクトです"
echo "→ /harness-init を使用してください"
exit 1
fi
ハーネス未導入の場合:
⚠️ このプロジェクトにはハーネスが導入されていません
/harness-updateは既にハーネス導入済みのプロジェクト用です。 新規導入には/harness-initを使用してください。
導入済みの場合: → Step 2 へ
プラグインの最新バージョンと比較:
PLUGIN_VERSION=$(cat "$CLAUDE_PLUGIN_ROOT/claude-code-harness/VERSION" 2>/dev/null || echo "unknown")
if [ "$CURRENT_VERSION" = "$PLUGIN_VERSION" ]; then
echo "ℹ️ バージョンは最新です (v$PLUGIN_VERSION)"
echo "→ ファイル内容のチェックを実行します..."
else
echo "📦 アップデート可能: v$CURRENT_VERSION → v$PLUGIN_VERSION"
fi
バージョンが異なる場合: → Step 3 へ
バージョンが同一の場合: → Step 2.5 へ(内容チェック)
⚠️ 重要: バージョンが同一でも、個別ファイルの内容が古い場合があります。 Step 2.5 で
template-tracker.sh checkを実行し、内容レベルでの更新を検出します。
バージョンは同じでも、ファイル内容が古い可能性をチェック:
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/claude-code-harness}"
# template-tracker.sh check で内容ベースの更新チェック
CHECK_RESULT=$(bash "$PLUGIN_ROOT/scripts/template-tracker.sh" check 2>/dev/null)
# JSON から更新件数を取得
NEEDS_CHECK=$(echo "$CHECK_RESULT" | jq -r '.needsCheck // false')
UPDATES_COUNT=$(echo "$CHECK_RESULT" | jq -r '.updatesCount // 0')
INSTALLS_COUNT=$(echo "$CHECK_RESULT" | jq -r '.installsCount // 0')
if [ "$NEEDS_CHECK" = "true" ]; then
echo "📦 ファイル内容の更新が必要です"
echo " - 更新対象: ${UPDATES_COUNT}件"
echo " - 新規作成: ${INSTALLS_COUNT}件"
else
echo "✅ 全てのファイルが最新です"
fi
更新が必要なファイルがある場合:
📦 ファイル内容の更新が検出されました
バージョンは v{{VERSION}} で同一ですが、以下のファイル内容が古くなっています:
ファイル 状態 対応 {{更新対象リスト}} 更新を続行しますか? (yes / no / 詳細を表示)
回答を待つ
template-tracker.sh status の詳細表示後、再度確認全ファイルが最新の場合:
✅ プロジェクトは完全に最新です
- バージョン: v{{VERSION}}
- 全ファイルの内容: 最新
更新の必要はありません。
template-tracker.sh status を実行して、テンプレート更新状況を表示:
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/claude-code-harness}"
bash "$PLUGIN_ROOT/scripts/template-tracker.sh" status
出力例:
=== テンプレート追跡状況 ===
プラグインバージョン: 2.5.25
最終チェック時: 2.5.20
ファイル 記録版 最新版 状態
-------- ------ ------ ----
CLAUDE.md 2.5.20 2.5.25 🔄 上書き可
AGENTS.md unknown 2.5.25 ⚠️ 要確認
Plans.md 2.5.20 2.5.25 🔧 マージ要
.claude/rules/workflow.md 2.5.20 2.5.25 ✅ 最新
凡例:
✅ 最新 : 更新不要
🔄 上書き可 : ローカライズなし、上書きで更新可能
🔧 マージ要 : ローカライズあり、マージが必要
⚠️ 要確認 : バージョン不明、確認推奨
更新対象ファイルを特定してユーザーに確認:
📦 アップデート: v{{CURRENT}} → v{{LATEST}}
更新されるファイル:
.claude/settings.json- セキュリティポリシーと最新構文に更新AGENTS.md/CLAUDE.md/Plans.md- 最新フォーマットに更新(既存タスクは保持).claude/rules/- 最新ルールテンプレートに更新.cursor/commands/- Cursor コマンド更新(2-Agent モードの場合).claude-code-harness-version- バージョン情報更新既存データは保持されます:
- ✅ Plans.md の未完了タスク
- ✅ .claude/settings.json のカスタム設定(hooks, env, model など)
- ✅ .claude/memory/ の SSOT データ
バックアップ:
- 変更前のファイルは
.claude-code-harness/backups/{{TIMESTAMP}}/に保存されますアップデートを実行しますか? (yes / no / カスタム)
カスタム: 特定のファイルだけ更新したい場合は「カスタム」を選択
回答を待つ
重要: アップデート実行前に、既存設定の問題を検出してユーザーに確認します。
既存の .claude/settings.json を読み込み、以下をチェック:
# settings.json が存在するか確認
if [ ! -f .claude/settings.json ]; then
echo "ℹ️ .claude/settings.json が存在しません(新規作成されます)"
# → Phase 2 へ(破壊的変更なし)
fi
# JSON パーサーで読み込み(jq または python)
if command -v jq >/dev/null 2>&1; then
SETTINGS_CONTENT=$(cat .claude/settings.json)
else
echo "⚠️ jq が見つかりません。手動確認が必要です"
fi
以下の問題を検出:
# 間違った構文のパターンを検索
WRONG_PATTERNS=(
'Bash\([^:)]+\s\*\)' # "Bash(npm run *)" のようなパターン
'Bash\([^:)]+\*\)' # "Bash(git diff*)" のようなパターン(:なし)
'Bash\(\*[^:][^)]*\*\)' # "Bash(*credentials*)" のようなパターン
)
FOUND_ISSUES=()
# 各パターンをチェック
if echo "$SETTINGS_CONTENT" | grep -E 'Bash\([^:)]+\s\*\)'; then
FOUND_ISSUES+=("incorrect_prefix_syntax_with_space")
fi
if echo "$SETTINGS_CONTENT" | grep -E 'Bash\([^:)]+\*\)' | grep -v ':'; then
FOUND_ISSUES+=("incorrect_prefix_syntax_no_colon")
fi
if echo "$SETTINGS_CONTENT" | grep -E 'Bash\(\*[^:][^)]*\*\)'; then
FOUND_ISSUES+=("incorrect_substring_syntax")
fi
# disableBypassPermissionsMode の存在確認
if echo "$SETTINGS_CONTENT" | grep -q '"disableBypassPermissionsMode"'; then
FOUND_ISSUES+=("deprecated_disable_bypass_permissions")
fi
# コマンドパスに "claude-code-harness" を含むフックのみを検出
# ユーザー独自のカスタムフック(パスが異なる)は対象外
PLUGIN_EVENTS=("PreToolUse" "SessionStart" "UserPromptSubmit" "PermissionRequest")
OLD_HARNESS_EVENTS=()
if command -v jq >/dev/null 2>&1; then
for event in "${PLUGIN_EVENTS[@]}"; do
if jq -e ".hooks.${event}" "$SETTINGS_FILE" >/dev/null 2>&1; then
# コマンドパスを抽出して "claude-code-harness" を含むかチェック
COMMANDS=$(jq -r ".hooks.${event}[]?.hooks[]?.command // .hooks.${event}[]?.command // empty" "$SETTINGS_FILE" 2>/dev/null)
if echo "$COMMANDS" | grep -q "claude-code-harness"; then
OLD_HARNESS_EVENTS+=("$event")
fi
fi
done
if [ ${#OLD_HARNESS_EVENTS[@]} -gt 0 ]; then
FOUND_ISSUES+=("legacy_hooks_in_settings")
echo "古いハーネスフック設定: ${OLD_HARNESS_EVENTS[*]}"
fi
fi
問題が見つかった場合、ユーザーに詳細を表示:
⚠️ 既存設定に問題が見つかりました
🔴 問題1: 間違ったパーミッション構文 (3件)
- "Bash(npm run *)" ❌ 間違い(スペース+アスタリスク) + "Bash(npm run:*)" ✅ 正しい(コロン+アスタリスク) - "Bash(pnpm *)" ❌ 間違い + "Bash(pnpm:*)" ✅ 正しい - "Bash(git diff*)" ❌ 間違い(コロンなし) + "Bash(git diff:*)" ✅ 正しい影響: 現在のパーミッション設定が正しく動作していません。 Claude Code がこれらのコマンドを実行できない可能性があります。
🔴 問題2: 非推奨設定 (1件)
- "disableBypassPermissionsMode": "disable" ❌ 非推奨(v2.5.0以降) (この設定を削除)理由: ハーネスは v2.5.0 以降、bypassPermissions を許可する運用に変更されました。 危険な操作のみを
permissions.deny/permissions.askで制御します。影響: 現在の設定では、Edit/Write の度に確認が出て生産性が低下します。
🔴 問題3: 古いフック設定 (N件)
- "hooks": { ... } ❌ プラグイン側 hooks.json と重複 (この設定を削除)理由: claude-code-harness プラグインは
hooks/hooks.jsonでフックを管理します。 プロジェクト側の.claude/settings.jsonにhooksがあると、意図しない重複動作が発生する可能性があります。推奨: プロジェクト側の
hooksセクションを削除し、プラグイン側のフックのみを使用してください。
これらの問題を自動修正しますか?
- yes - 上記の問題をすべて自動修正してアップデート続行
- 確認する - 各問題を個別に確認してから修正
- スキップ - 問題を修正せずにアップデート続行(非推奨)
- キャンセル - アップデートを中止
回答を待つ
各問題について個別に確認:
問題1/2: 間違ったパーミッション構文
以下の3件を修正しますか?
"Bash(npm run *)"→"Bash(npm run:*)""Bash(pnpm *)"→"Bash(pnpm:*)""Bash(git diff*)"→"Bash(git diff:*)"(yes / no)
回答を待つ → yes なら修正リストに追加
問題2/2: 非推奨設定
disableBypassPermissionsModeを削除しますか?(yes / no)
回答を待つ → yes なら削除リストに追加
すべての確認が完了したら → Phase 2 へ
設計方針: 更新対象リストを先に作成し、全ファイル処理完了まで継続。途中終了しない。
Phase 1 または Step 2.5 で検出した更新対象をリストとして管理し、全て処理するまで継続します:
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/claude-code-harness}"
# template-tracker.sh check の結果を取得
CHECK_RESULT=$(bash "$PLUGIN_ROOT/scripts/template-tracker.sh" check 2>/dev/null)
# 更新対象リストを作成
UPDATE_LIST=()
INSTALL_LIST=()
if command -v jq >/dev/null 2>&1; then
# 更新が必要なファイル
while IFS= read -r line; do
[ -n "$line" ] && UPDATE_LIST+=("$line")
done < <(echo "$CHECK_RESULT" | jq -r '.updates[]?.path // empty')
# 新規作成が必要なファイル
while IFS= read -r line; do
[ -n "$line" ] && INSTALL_LIST+=("$line")
done < <(echo "$CHECK_RESULT" | jq -r '.installs[]?.path // empty')
fi
TOTAL_COUNT=$((${#UPDATE_LIST[@]} + ${#INSTALL_LIST[@]}))
COMPLETED_COUNT=0
echo "📋 更新対象リスト: ${TOTAL_COUNT}件"
echo " - 更新: ${#UPDATE_LIST[@]}件"
echo " - 新規: ${#INSTALL_LIST[@]}件"
進捗管理:
更新対象リスト (5件)
├── [1/5] ⏳ CLAUDE.md - 待機中
├── [2/5] ⏳ AGENTS.md - 待機中
├── [3/5] ⏳ .claude/rules/workflow.md - 待機中
├── [4/5] ⏳ .claude/settings.json - 待機中
└── [5/5] ⏳ Plans.md - 待機中
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR=".claude-code-harness/backups/$TIMESTAMP"
mkdir -p "$BACKUP_DIR"
# バックアップ対象ファイルをコピー
[ -f .claude/settings.json ] && cp .claude/settings.json "$BACKUP_DIR/"
[ -f AGENTS.md ] && cp AGENTS.md "$BACKUP_DIR/"
[ -f CLAUDE.md ] && cp CLAUDE.md "$BACKUP_DIR/"
[ -f Plans.md ] && cp Plans.md "$BACKUP_DIR/"
[ -d .claude/rules ] && cp -r .claude/rules "$BACKUP_DIR/"
[ -d .cursor/commands ] && cp -r .cursor/commands "$BACKUP_DIR/"
echo "✅ バックアップ作成: $BACKUP_DIR"
.claude/settings.json の更新
Phase 1.5 で検出した問題を修正してから、generate-claude-settings スキルを実行します。
ユーザーが承認した修正を適用:
# settings.json を読み込み
SETTINGS_FILE=".claude/settings.json"
# 問題1: パーミッション構文の修正
if [ -f "$SETTINGS_FILE" ]; then
# スペース+アスタリスクをコロン+アスタリスクに置換
# 例: "Bash(npm run *)" → "Bash(npm run:*)"
sed -i.bak 's/Bash(\([^:)]*\) \*)/Bash(\1:*)/g' "$SETTINGS_FILE"
# コロンなしアスタリスクをコロン+アスタリスクに置換
# 例: "Bash(git diff*)" → "Bash(git diff:*)"
# (ただし既に : がある場合はスキップ)
sed -i.bak 's/Bash(\([^:)]*\)\*)/Bash(\1:*)/g' "$SETTINGS_FILE"
# 部分文字列マッチの修正
# 例: "Bash(*credentials*)" → "Bash(:*credentials:*)"
sed -i.bak 's/Bash(\*\([^:][^)]*\)\*)/Bash(:*\1:*)/g' "$SETTINGS_FILE"
echo "✅ パーミッション構文を修正しました"
fi
# 問題2: 非推奨設定の削除
if [ -f "$SETTINGS_FILE" ]; then
# disableBypassPermissionsMode を削除(jq を使用)
if command -v jq >/dev/null 2>&1; then
jq 'del(.permissions.disableBypassPermissionsMode)' "$SETTINGS_FILE" > "$SETTINGS_FILE.tmp"
mv "$SETTINGS_FILE.tmp" "$SETTINGS_FILE"
echo "✅ disableBypassPermissionsMode を削除しました"
else
# jq がない場合は Python で削除
python3 -c "
import json
with open('$SETTINGS_FILE', 'r') as f:
data = json.load(f)
if 'permissions' in data and 'disableBypassPermissionsMode' in data['permissions']:
del data['permissions']['disableBypassPermissionsMode']
with open('$SETTINGS_FILE', 'w') as f:
json.dump(data, f, indent=2)
" && echo "✅ disableBypassPermissionsMode を削除しました"
fi
fi
# 問題3: ハーネス由来のフック設定のみ削除(パスで判別)
# ユーザー独自のカスタムフックは保持
if [ -f "$SETTINGS_FILE" ]; then
PLUGIN_EVENTS=("PreToolUse" "SessionStart" "UserPromptSubmit" "PermissionRequest")
DELETED_EVENTS=()
if command -v jq >/dev/null 2>&1; then
for event in "${PLUGIN_EVENTS[@]}"; do
if jq -e ".hooks.${event}" "$SETTINGS_FILE" >/dev/null 2>&1; then
# コマンドパスに "claude-code-harness" が含まれる場合のみ削除
COMMANDS=$(jq -r ".hooks.${event}[]?.hooks[]?.command // .hooks.${event}[]?.command // empty" "$SETTINGS_FILE" 2>/dev/null)
if echo "$COMMANDS" | grep -q "claude-code-harness"; then
jq "del(.hooks.${event})" "$SETTINGS_FILE" > "$SETTINGS_FILE.tmp"
mv "$SETTINGS_FILE.tmp" "$SETTINGS_FILE"
DELETED_EVENTS+=("$event")
fi
fi
done
# .hooks が空になった場合は .hooks 自体を削除
if jq -e '.hooks | length == 0' "$SETTINGS_FILE" >/dev/null 2>&1; then
jq 'del(.hooks)' "$SETTINGS_FILE" > "$SETTINGS_FILE.tmp"
mv "$SETTINGS_FILE.tmp" "$SETTINGS_FILE"
fi
if [ ${#DELETED_EVENTS[@]} -gt 0 ]; then
echo "✅ 古いハーネスフック設定を削除: ${DELETED_EVENTS[*]}(プラグイン側 hooks.json を使用)"
fi
else
# jq がない場合は Python で削除
python3 -c "
import json
with open('$SETTINGS_FILE', 'r') as f:
data = json.load(f)
if 'hooks' in data:
plugin_events = ['PreToolUse', 'SessionStart', 'UserPromptSubmit', 'PermissionRequest']
deleted = []
for event in plugin_events:
if event in data['hooks']:
# コマンドパスに 'claude-code-harness' が含まれるかチェック
hooks_list = data['hooks'][event]
is_harness = any('claude-code-harness' in str(h) for h in hooks_list)
if is_harness:
del data['hooks'][event]
deleted.append(event)
if not data['hooks']:
del data['hooks']
if deleted:
print(f'✅ 古いハーネスフック設定を削除: {\" \".join(deleted)}')
with open('$SETTINGS_FILE', 'w') as f:
json.dump(data, f, indent=2)
"
fi
fi
env, model, enabledPlugins は保持(hooks は削除済み)permissions.allow|ask|deny は最新ポリシーとマージ + 重複排除テンプレート追跡状況に応じた更新処理:
各ファイルの状態に応じて処理を分岐:
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/claude-code-harness}"
# テンプレート追跡のチェック結果を取得
CHECK_RESULT=$(bash "$PLUGIN_ROOT/scripts/template-tracker.sh" check 2>/dev/null)
# jq で更新が必要なファイルを処理
if command -v jq >/dev/null 2>&1; then
echo "$CHECK_RESULT" | jq -r '.updates[]? | "\(.path)|\(.localized)"' | while IFS='|' read -r path localized; do
if [ "$localized" = "false" ]; then
# ローカライズなし → 上書き
echo "🔄 上書き: $path"
# テンプレートから生成して上書き
# → generate-* スキルを実行
else
# ローカライズあり → マージ支援
echo "🔧 マージ支援: $path"
# 差分を表示してユーザーに確認
fi
done
fi
ローカライズなし(🔄 上書き可)の場合:
自動で最新テンプレートに置き換え:
AGENTS.md / CLAUDE.md: 最新テンプレートで上書き.claude/rules/*.md: 最新ルールテンプレートで上書きローカライズあり(🔧 マージ要)の場合:
🔧
Plans.mdはローカライズされていますこのファイルにはプロジェクト固有の変更が含まれています。
オプション:
- 差分を表示 - テンプレートとの差分を確認
- マージ支援 - Claude がマージを提案
- スキップ - このファイルはスキップ
選択してください:
回答を待つ
マージ支援を選択した場合:
更新後の記録:
# 更新したファイルを generated-files.json に記録
bash "$PLUGIN_ROOT/scripts/template-tracker.sh" record "$path"
.claude/rules/ の更新:
マーカー + ハッシュ方式でローカライズ検出を行い、安全に更新します。
PLUGIN_PATH="${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/claude-code-harness}"
PLUGIN_VERSION=$(cat "$PLUGIN_PATH/VERSION" 2>/dev/null || echo "unknown")
SKILLS_CONFIG=".claude/state/skills-config.json"
# Skills Gate の状態を確認
SKILLS_GATE_ENABLED="false"
if [ -f "$SKILLS_CONFIG" ]; then
if command -v jq >/dev/null 2>&1; then
SKILLS_GATE_ENABLED=$(jq -r '.enabled // false' "$SKILLS_CONFIG")
fi
fi
# 各ルールテンプレートを処理
for template in "$PLUGIN_PATH/templates/rules"/*.template; do
[ -f "$template" ] || continue
rule_name=$(basename "$template" .template)
output_file=".claude/rules/$rule_name"
# 条件付きテンプレートのチェック(template-registry.json から condition を取得)
TEMPLATE_KEY="rules/$(basename "$template")"
CONDITION=""
if command -v jq >/dev/null 2>&1; then
CONDITION=$(jq -r ".templates[\"$TEMPLATE_KEY\"].condition // \"\"" "$PLUGIN_PATH/templates/template-registry.json" 2>/dev/null)
fi
# 条件付きテンプレートの評価
if [ -n "$CONDITION" ]; then
case "$CONDITION" in
"skills_gate.enabled")
if [ "$SKILLS_GATE_ENABLED" != "true" ]; then
# 条件を満たさない場合
if [ -f "$output_file" ]; then
echo "🗑️ 削除提案: $output_file(Skills Gate 無効)"
else
echo "⏭️ スキップ: $rule_name(Skills Gate 無効)"
fi
continue
fi
;;
esac
fi
# ファイルが存在しない場合は新規作成
if [ ! -f "$output_file" ]; then
cp "$template" "$output_file"
sed -i '' "s/{{VERSION}}/$PLUGIN_VERSION/g" "$output_file" 2>/dev/null || \
sed -i "s/{{VERSION}}/$PLUGIN_VERSION/g" "$output_file"
echo "🆕 作成: $output_file"
continue
fi
# マーカーをチェック(ハーネス由来かどうか)
if grep -q "^_harness_template:" "$output_file" 2>/dev/null; then
# ハーネス由来 → ローカライズ検出して更新
# フロントマター以降の内容のハッシュを比較
INSTALLED_VERSION=$(grep "^_harness_version:" "$output_file" | sed 's/_harness_version: "//;s/"//')
if [ "$INSTALLED_VERSION" != "$PLUGIN_VERSION" ]; then
# バージョンが異なる → 更新対象
# (ローカライズ検出は template-tracker.sh に任せる)
echo "🔄 更新: $output_file($INSTALLED_VERSION → $PLUGIN_VERSION)"
cp "$template" "$output_file"
sed -i '' "s/{{VERSION}}/$PLUGIN_VERSION/g" "$output_file" 2>/dev/null || \
sed -i "s/{{VERSION}}/$PLUGIN_VERSION/g" "$output_file"
else
echo "✅ 最新: $output_file"
fi
else
# マーカーなし → ユーザーカスタム、保護
echo "🛡️ 保護: $output_file(ユーザーカスタム)"
fi
done
判定ロジック:
| マーカー | 条件 | 処理 |
|---|---|---|
| あり | 条件なし / 条件満たす | 更新(ローカライズ検出) |
| あり | 条件満たさない | 削除提案 |
| なし | - | 保護(ユーザーカスタム) |
Skills Gate が無効で、skills-gate.md が存在しない場合、有効化を提案します。
# Skills Gate が無効な場合、有効化を提案
if [ "$SKILLS_GATE_ENABLED" != "true" ]; then
echo ""
echo "💡 Skills Gate を有効にしますか?"
echo ""
echo "Skills Gate は、コード編集前にスキルの使用を促す機能です。"
echo "- Rules: Claude に「スキルを使うべき」と認識させる"
echo "- Hooks: 忘れた場合の最終防衛線"
echo ""
echo "有効にすると:"
echo "- skills-gate.md ルールが追加されます"
echo "- スキル使用が習慣化され、作業品質が向上します"
echo ""
fi
回答を待つ
skills-gate.md を追加# ユーザーが yes を選択した場合
if [ "$USER_CHOICE" = "yes" ]; then
# skills-config.json を有効化
if [ -f "$SKILLS_CONFIG" ]; then
jq '.enabled = true' "$SKILLS_CONFIG" > tmp.json && mv tmp.json "$SKILLS_CONFIG"
else
mkdir -p .claude/state
cat > "$SKILLS_CONFIG" << EOF
{
"version": "1.0",
"enabled": true,
"skills": ["impl", "review"],
"updated_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
fi
# skills-gate.md を追加
cp "$PLUGIN_PATH/templates/rules/skills-gate.md.template" ".claude/rules/skills-gate.md"
sed -i '' "s/{{VERSION}}/$PLUGIN_VERSION/g" ".claude/rules/skills-gate.md" 2>/dev/null || \
sed -i "s/{{VERSION}}/$PLUGIN_VERSION/g" ".claude/rules/skills-gate.md"
echo "✅ Skills Gate を有効化しました"
echo "✅ 作成: .claude/rules/skills-gate.md"
fi
プラグイン側のスキルと、プロジェクト側の設定を比較して差分を検出・提案します。
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/claude-code-harness}"
SKILLS_CONFIG=".claude/state/skills-config.json"
mkdir -p .claude/state
# プラグイン側の利用可能スキル一覧を取得
AVAILABLE_SKILLS=()
if [ -d "$PLUGIN_ROOT/skills" ]; then
for skill_dir in "$PLUGIN_ROOT/skills"/*/; do
if [ -d "$skill_dir" ]; then
skill_name=$(basename "$skill_dir")
AVAILABLE_SKILLS+=("$skill_name")
fi
done
fi
echo "📦 プラグイン側の利用可能スキル: ${AVAILABLE_SKILLS[*]}"
if [ -f "$SKILLS_CONFIG" ]; then
# 既存設定からスキル一覧を取得
if command -v jq >/dev/null 2>&1; then
CURRENT_SKILLS=$(jq -r '.skills[]?' "$SKILLS_CONFIG" 2>/dev/null | tr '\n' ' ')
else
CURRENT_SKILLS=""
fi
echo "📋 プロジェクト側の登録スキル: $CURRENT_SKILLS"
else
CURRENT_SKILLS=""
echo "📋 プロジェクト側の登録スキル: (未設定)"
fi
NEW_SKILLS=()
REMOVED_SKILLS=()
# プラグインにあってプロジェクトにないスキル(新規追加候補)
for skill in "${AVAILABLE_SKILLS[@]}"; do
if ! echo "$CURRENT_SKILLS" | grep -qw "$skill"; then
NEW_SKILLS+=("$skill")
fi
done
# プロジェクトにあってプラグインにないスキル(削除候補)
for skill in $CURRENT_SKILLS; do
found=false
for avail in "${AVAILABLE_SKILLS[@]}"; do
if [ "$skill" = "$avail" ]; then
found=true
break
fi
done
if [ "$found" = false ]; then
REMOVED_SKILLS+=("$skill")
fi
done
新しいスキルが検出された場合:
🆕 新しいスキルが利用可能です
以下のスキルが追加されました: {{NEW_SKILLS のリストと説明}}
追加しますか?
- yes - すべて追加
- 選択 - 個別に選択
- スキップ - 今回は追加しない
回答を待つ
削除されたスキルが検出された場合:
⚠️ 以下のスキルはプラグインから削除されました
{{REMOVED_SKILLS のリスト}}
設定から削除しますか? (yes / no)
回答を待つ
if [ -f "$SKILLS_CONFIG" ]; then
# 既存設定を保持しつつ、新スキルを追加
if command -v jq >/dev/null 2>&1; then
# 承認された新スキルを追加
for skill in "${APPROVED_NEW_SKILLS[@]}"; do
jq --arg s "$skill" '.skills += [$s] | .skills |= unique' "$SKILLS_CONFIG" > tmp.json
mv tmp.json "$SKILLS_CONFIG"
done
# 削除されたスキルを除去
for skill in "${APPROVED_REMOVED_SKILLS[@]}"; do
jq --arg s "$skill" '.skills -= [$s]' "$SKILLS_CONFIG" > tmp.json
mv tmp.json "$SKILLS_CONFIG"
done
# バージョンとタイムスタンプを更新
jq '.version = "1.0" | .updated_at = "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"' "$SKILLS_CONFIG" > tmp.json
mv tmp.json "$SKILLS_CONFIG"
echo "✅ skills-config.json: 更新"
else
echo "⚠️ jq が見つかりません。Skills 設定の自動更新はスキップされます"
echo " 手動で /skills-update を実行するか、jq をインストールしてください"
fi
else
# 新規作成(デフォルトスキル + 承認された新スキル)
DEFAULT_SKILLS='["impl", "review"]'
cat > "$SKILLS_CONFIG" << SKILLSEOF
{
"version": "1.0",
"enabled": true,
"skills": $DEFAULT_SKILLS,
"updated_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
SKILLSEOF
echo "✅ skills-config.json: 新規作成"
fi
💡 Skills 差分検出について
- プラグイン更新で新しいスキルが追加された場合、自動的に検出・提案されます
- 既存のスキル設定は保持されます
- 個別のスキル追加/削除は
/skills-updateコマンドでも行えます
.cursor/commands/ が存在する場合のみ更新:
if [ -d .cursor/commands ]; then
PLUGIN_PATH="${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/claude-code-harness}"
# 最新のコマンドテンプレートをコピー
for cmd in "$PLUGIN_PATH/templates/cursor/commands"/*.md; do
if [ -f "$cmd" ]; then
cp "$cmd" .cursor/commands/
echo "✅ 更新: $(basename $cmd)"
fi
done
fi
.claude-code-harness-version を最新版に更新:
cat > .claude-code-harness-version <<EOF
# claude-code-harness version tracking
# This file is auto-generated by /harness-update
# DO NOT manually edit - used for update detection
version: $PLUGIN_VERSION
installed_at: $(grep "^installed_at:" .claude-code-harness-version | cut -d' ' -f2)
updated_at: $(date +%Y-%m-%d)
last_setup_command: harness-update
EOF
echo "✅ バージョン更新: v$CURRENT_VERSION → v$PLUGIN_VERSION"
📋 どのファイルを更新しますか?
.claude/settings.json- セキュリティポリシーとパーミッション構文AGENTS.md/CLAUDE.md/Plans.md- ワークフローファイル.claude/rules/- ルールテンプレート.cursor/commands/- Cursor コマンド(2-Agent モード)- すべて
番号で選択してください(複数可、カンマ区切り):
回答を待つ
選択されたファイルのみ Phase 2 の該当 Step を実行。
重要: 更新処理後に再度 template-tracker.sh check を実行し、全ファイルが最新になったことを確認します。
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/claude-code-harness}"
# 再検証
VERIFY_RESULT=$(bash "$PLUGIN_ROOT/scripts/template-tracker.sh" check 2>/dev/null)
REMAINING_UPDATES=$(echo "$VERIFY_RESULT" | jq -r '.updatesCount // 0')
REMAINING_INSTALLS=$(echo "$VERIFY_RESULT" | jq -r '.installsCount // 0')
REMAINING_TOTAL=$((REMAINING_UPDATES + REMAINING_INSTALLS))
if [ "$REMAINING_TOTAL" -gt 0 ]; then
echo "⚠️ 更新が完了していないファイルがあります: ${REMAINING_TOTAL}件"
echo " 再度更新を試行するか、手動対応が必要です"
else
echo "✅ 全ファイルが最新に更新されました"
fi
残りがある場合:
⚠️ 一部のファイルが更新されていません
ファイル 状態 理由 {{残りのファイルリスト}} 対応オプション:
- 再試行 - 更新処理を再実行
- 手動対応 - ローカライズされたファイルを手動マージ
- スキップ - 現状のまま終了(次回
/harness-updateで再検出)
回答を待つ
# settings.json の構文チェック
if command -v jq >/dev/null 2>&1; then
jq empty .claude/settings.json 2>/dev/null && echo "✅ settings.json: 有効" || echo "⚠️ settings.json: 構文エラー"
fi
# バージョンファイルの確認
[ -f .claude-code-harness-version ] && echo "✅ version file: 存在" || echo "⚠️ version file: なし"
処理結果のサマリー:
📊 更新レポート
処理結果:
├── 更新完了: N件
├── 新規作成: N件
├── スキップ: N件(理由付き)
└── 手動対応: N件
ファイル別結果:
├── [1/5] ✅ CLAUDE.md - 上書き完了
├── [2/5] ✅ AGENTS.md - 上書き完了
├── [3/5] ✅ .claude/rules/workflow.md - 上書き完了
├── [4/5] ✅ .claude/settings.json - マージ完了
└── [5/5] 🔧 Plans.md - 手動マージ推奨
✅ アップデートが完了しました!
更新内容:
- バージョン: v{{CURRENT}} → v{{LATEST}}
- 処理ファイル: {{処理件数}}/{{対象件数}}件
- 更新方法: 上書き {{N}}件 / マージ {{N}}件 / 手動 {{N}}件
- バックアップ:
.claude-code-harness/backups/{{TIMESTAMP}}/ファイル別結果:
ファイル 結果 方法 {{ファイル別結果リスト}} 次のステップ:
- 「
/sync-status」→ 現在の状態を確認- 「
/plan-with-agent〇〇を作りたい」→ 新しいタスクを追加- 「
/work」→ Plans.md のタスクを実行問題が発生した場合:
# バックアップから復元 cp -r .claude-code-harness/backups/{{TIMESTAMP}}/* .
ユーザーが選択したファイルのみ更新します。
/sync-status で状態確認A: バックアップから復元してください:
cp -r .claude-code-harness/backups/{{TIMESTAMP}}/* .
A: .claude/settings.json を手動で修正するか、再度 /harness-update を実行してください。
正しい構文: "Bash(npm run:*)" / 間違い: "Bash(npm run *)"
A: 「カスタム」を選択して、必要なファイルだけ選択してください。
/harness-init - 新規プロジェクトのセットアップ/sync-status - 現在のプロジェクト状態確認/validate - プロジェクト構造の検証