From a7b023dde74448620b44e4a888d4dc7f63ffc15a Mon Sep 17 00:00:00 2001 From: Michael Ramos Date: Thu, 5 Mar 2026 18:47:42 -0800 Subject: [PATCH 1/3] fix: validate plugin hooks.json on install to ensure correct timeout The Claude Code plugin marketplace can leave stale hooks.json with incorrect timeout values (e.g. 1800 instead of 345600). Install scripts now check for and overwrite the plugin's hooks.json if it exists. Co-Authored-By: Claude Opus 4.6 --- scripts/install.cmd | 28 ++++++++++++++++++++++++++++ scripts/install.ps1 | 24 ++++++++++++++++++++++++ scripts/install.sh | 24 ++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/scripts/install.cmd b/scripts/install.cmd index f15a135005..49ab469603 100644 --- a/scripts/install.cmd +++ b/scripts/install.cmd @@ -127,6 +127,34 @@ if !ERRORLEVEL! neq 0 ( echo set PATH=%%PATH%%;!INSTALL_DIR! ) +REM Validate plugin hooks.json if plugin is already installed +if defined CLAUDE_CONFIG_DIR ( + set "PLUGIN_HOOKS=%CLAUDE_CONFIG_DIR%\plugins\marketplaces\plannotator\apps\hook\hooks\hooks.json" +) else ( + set "PLUGIN_HOOKS=%USERPROFILE%\.claude\plugins\marketplaces\plannotator\apps\hook\hooks\hooks.json" +) +if exist "!PLUGIN_HOOKS!" ( + ( +echo { +echo "hooks": { +echo "PermissionRequest": [ +echo { +echo "matcher": "ExitPlanMode", +echo "hooks": [ +echo { +echo "type": "command", +echo "command": "plannotator", +echo "timeout": 345600 +echo } +echo ] +echo } +echo ] +echo } +echo } + ) > "!PLUGIN_HOOKS!" + echo Updated plugin hooks at !PLUGIN_HOOKS! +) + REM Install /review slash command if defined CLAUDE_CONFIG_DIR ( set "CLAUDE_COMMANDS_DIR=%CLAUDE_CONFIG_DIR%\commands" diff --git a/scripts/install.ps1 b/scripts/install.ps1 index 8a44de0b6e..99ee140a3d 100644 --- a/scripts/install.ps1 +++ b/scripts/install.ps1 @@ -82,6 +82,30 @@ if ($userPath -notlike "*$installDir*") { Write-Host "Added to PATH. Restart your terminal for changes to take effect." } +# Validate plugin hooks.json if plugin is already installed +$pluginHooks = if ($env:CLAUDE_CONFIG_DIR) { "$env:CLAUDE_CONFIG_DIR\plugins\marketplaces\plannotator\apps\hook\hooks\hooks.json" } else { "$env:USERPROFILE\.claude\plugins\marketplaces\plannotator\apps\hook\hooks\hooks.json" } +if (Test-Path $pluginHooks) { + @' +{ + "hooks": { + "PermissionRequest": [ + { + "matcher": "ExitPlanMode", + "hooks": [ + { + "type": "command", + "command": "plannotator", + "timeout": 345600 + } + ] + } + ] + } +} +'@ | Set-Content -Path $pluginHooks + Write-Host "Updated plugin hooks at $pluginHooks" +} + # Clear OpenCode plugin cache Remove-Item -Recurse -Force "$env:USERPROFILE\.cache\opencode\node_modules\@plannotator" -ErrorAction SilentlyContinue Remove-Item -Recurse -Force "$env:USERPROFILE\.bun\install\cache\@plannotator" -ErrorAction SilentlyContinue diff --git a/scripts/install.sh b/scripts/install.sh index 4684e5ae99..56b349a848 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -83,6 +83,30 @@ if ! echo "$PATH" | tr ':' '\n' | grep -qx "$INSTALL_DIR"; then echo " source ${shell_config}" fi +# Validate plugin hooks.json if plugin is already installed +PLUGIN_HOOKS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/plugins/marketplaces/plannotator/apps/hook/hooks/hooks.json" +if [ -f "$PLUGIN_HOOKS" ]; then + cat > "$PLUGIN_HOOKS" << 'HOOKS_EOF' +{ + "hooks": { + "PermissionRequest": [ + { + "matcher": "ExitPlanMode", + "hooks": [ + { + "type": "command", + "command": "plannotator", + "timeout": 345600 + } + ] + } + ] + } +} +HOOKS_EOF + echo "Updated plugin hooks at ${PLUGIN_HOOKS}" +fi + # Clear any cached OpenCode plugin to force fresh download on next run rm -rf "$HOME/.cache/opencode/node_modules/@plannotator" "$HOME/.bun/install/cache/@plannotator" 2>/dev/null || true From 0b615b65e6a7d8474b13324c6b8f362c6a7440a3 Mon Sep 17 00:00:00 2001 From: Michael Ramos Date: Thu, 5 Mar 2026 19:07:51 -0800 Subject: [PATCH 2/3] fix: warn about duplicate hook when plugin and settings.json both configure plannotator Detects "command".*plannotator in settings.json (only matches hook configs, not enabledPlugins) and only warns when the plugin is also installed. Co-Authored-By: Claude Opus 4.6 --- scripts/install.cmd | 19 +++++++++++++++++++ scripts/install.ps1 | 20 ++++++++++++++++++++ scripts/install.sh | 17 +++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/scripts/install.cmd b/scripts/install.cmd index 49ab469603..18e14f5c43 100644 --- a/scripts/install.cmd +++ b/scripts/install.cmd @@ -206,5 +206,24 @@ echo /plugin marketplace add backnotprop/plannotator echo /plugin install plannotator@plannotator echo. echo The /plannotator-review and /plannotator-annotate commands are ready to use! + +REM Warn if plannotator is configured in both settings.json hooks AND the plugin (causes double execution) +REM Only warn when the plugin is installed — manual-only users won't have overlap +if exist "!PLUGIN_HOOKS!" if exist "!CLAUDE_SETTINGS!" ( + findstr /r /c:"\"command\".*plannotator" "!CLAUDE_SETTINGS!" >nul 2>&1 + if !ERRORLEVEL! equ 0 ( + echo. + echo WARNING: DUPLICATE HOOK DETECTED + echo. + echo plannotator was found in your settings.json hooks: + echo !CLAUDE_SETTINGS! + echo. + echo This will cause plannotator to run TWICE on each plan review. + echo Remove the plannotator hook from settings.json and rely on the + echo plugin instead ^(installed automatically via marketplace^). + echo. + ) +) + echo. exit /b 0 diff --git a/scripts/install.ps1 b/scripts/install.ps1 index 99ee140a3d..91277600b6 100644 --- a/scripts/install.ps1 +++ b/scripts/install.ps1 @@ -196,3 +196,23 @@ Write-Host " /plugin marketplace add backnotprop/plannotator" Write-Host " /plugin install plannotator@plannotator" Write-Host "" Write-Host "The /plannotator-review and /plannotator-annotate commands are ready to use after you restart Claude Code!" + +# Warn if plannotator is configured in both settings.json hooks AND the plugin (causes double execution) +# Only warn when the plugin is installed — manual-only users won't have overlap +$claudeSettings = if ($env:CLAUDE_CONFIG_DIR) { "$env:CLAUDE_CONFIG_DIR\settings.json" } else { "$env:USERPROFILE\.claude\settings.json" } +if ((Test-Path $pluginHooks) -and (Test-Path $claudeSettings)) { + $settingsContent = Get-Content -Path $claudeSettings -Raw -ErrorAction SilentlyContinue + if ($settingsContent -match '"command".*plannotator') { + Write-Host "" + Write-Host "⚠️ ⚠️ ⚠️ WARNING: DUPLICATE HOOK DETECTED ⚠️ ⚠️ ⚠️" + Write-Host "" + Write-Host " plannotator was found in your settings.json hooks:" + Write-Host " $claudeSettings" + Write-Host "" + Write-Host " This will cause plannotator to run TWICE on each plan review." + Write-Host " Remove the plannotator hook from settings.json and rely on the" + Write-Host " plugin instead (installed automatically via marketplace)." + Write-Host "" + Write-Host "⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️" + } +} diff --git a/scripts/install.sh b/scripts/install.sh index 56b349a848..cfc70ef9cd 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -196,3 +196,20 @@ echo " /plugin marketplace add backnotprop/plannotator" echo " /plugin install plannotator@plannotator" echo "" echo "The /plannotator-review and /plannotator-annotate commands are ready to use after you restart Claude Code!" + +# Warn if plannotator is configured in both settings.json hooks AND the plugin (causes double execution) +# Only warn when the plugin is installed — manual-only users won't have overlap +CLAUDE_SETTINGS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json" +if [ -f "$PLUGIN_HOOKS" ] && [ -f "$CLAUDE_SETTINGS" ] && grep -q '"command".*plannotator' "$CLAUDE_SETTINGS" 2>/dev/null; then + echo "" + echo "⚠️ ⚠️ ⚠️ WARNING: DUPLICATE HOOK DETECTED ⚠️ ⚠️ ⚠️" + echo "" + echo " plannotator was found in your settings.json hooks:" + echo " $CLAUDE_SETTINGS" + echo "" + echo " This will cause plannotator to run TWICE on each plan review." + echo " Remove the plannotator hook from settings.json and rely on the" + echo " plugin instead (installed automatically via marketplace)." + echo "" + echo "⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️" +fi From 27196239da45052e58d8570a055d81b4c1ffe1df Mon Sep 17 00:00:00 2001 From: Michael Ramos Date: Thu, 5 Mar 2026 19:17:31 -0800 Subject: [PATCH 3/3] fix: define CLAUDE_SETTINGS variable in install.cmd The duplicate hook warning referenced !CLAUDE_SETTINGS! but the variable was never set, causing the warning to silently never fire for CMD users. Co-Authored-By: Claude Opus 4.6 --- scripts/install.cmd | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/install.cmd b/scripts/install.cmd index 18e14f5c43..68e0f297a8 100644 --- a/scripts/install.cmd +++ b/scripts/install.cmd @@ -209,6 +209,11 @@ echo The /plannotator-review and /plannotator-annotate commands are ready to use REM Warn if plannotator is configured in both settings.json hooks AND the plugin (causes double execution) REM Only warn when the plugin is installed — manual-only users won't have overlap +if defined CLAUDE_CONFIG_DIR ( + set "CLAUDE_SETTINGS=%CLAUDE_CONFIG_DIR%\settings.json" +) else ( + set "CLAUDE_SETTINGS=%USERPROFILE%\.claude\settings.json" +) if exist "!PLUGIN_HOOKS!" if exist "!CLAUDE_SETTINGS!" ( findstr /r /c:"\"command\".*plannotator" "!CLAUDE_SETTINGS!" >nul 2>&1 if !ERRORLEVEL! equ 0 (