diff --git a/.claude/settings.local.json.template b/.claude/settings.local.json.template index c1fe321c..06b86a73 100644 --- a/.claude/settings.local.json.template +++ b/.claude/settings.local.json.template @@ -8,7 +8,7 @@ "hooks": { "PreToolUse": [ { - "matcher": "Bash|Write|Edit", + "matcher": "Bash|Write|Edit|Replace", "hooks": [ { "type": "command", @@ -20,7 +20,7 @@ ], "PostToolUse": [ { - "matcher": "Write|Edit", + "matcher": "Write|Edit|Replace", "hooks": [ { "type": "command", diff --git a/scripts/deploy-hooks.js b/scripts/deploy-hooks.js index b6a4df14..bd4f8e1d 100644 --- a/scripts/deploy-hooks.js +++ b/scripts/deploy-hooks.js @@ -84,17 +84,43 @@ function deployTo(targetDir) { if (fs.existsSync(templateSrc)) { copyFile(templateSrc, path.join(targetClaude, SETTINGS_TEMPLATE)); - // settings.local.json を生成 (テンプレートの {{PROJECT_DIR}} を置換) + // settings.local.json を生成 (hooks のみ更新、既存 permissions 等は保持) const template = fs.readFileSync(templateSrc, "utf8"); const resolved = template.replace( /\{\{PROJECT_DIR\}\}/g, targetDir.replace(/\\/g, "\\\\") ); - fs.writeFileSync( - path.join(targetClaude, "settings.local.json"), - resolved - ); - console.log(" generated: settings.local.json"); + const newSettings = JSON.parse(resolved); + if ( + !newSettings || + typeof newSettings !== "object" || + Array.isArray(newSettings) || + !newSettings.hooks || + typeof newSettings.hooks !== "object" || + Array.isArray(newSettings.hooks) + ) { + throw new Error("Invalid settings template: `hooks` object is required"); + } + const settingsDest = path.join(targetClaude, "settings.local.json"); + + if (fs.existsSync(settingsDest)) { + try { + const parsed = JSON.parse(fs.readFileSync(settingsDest, "utf8")); + const existing = + parsed && typeof parsed === "object" && !Array.isArray(parsed) + ? parsed + : {}; + existing.hooks = newSettings.hooks; + fs.writeFileSync(settingsDest, JSON.stringify(existing, null, 2) + "\n"); + console.log(" updated: settings.local.json (hooks merged, permissions preserved)"); + } catch { + fs.writeFileSync(settingsDest, JSON.stringify(newSettings, null, 2) + "\n"); + console.log(" WARN: existing settings.local.json was invalid, regenerated"); + } + } else { + fs.writeFileSync(settingsDest, JSON.stringify(newSettings, null, 2) + "\n"); + console.log(" generated: settings.local.json"); + } } return true;