Skip to content

Commit 64d2f29

Browse files
backnotpropclaude
andauthored
fix: validate plugin hooks.json on install (backnotprop#230)
* 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 <noreply@anthropic.com> * 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 <noreply@anthropic.com> * 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 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1701424 commit 64d2f29

3 files changed

Lines changed: 137 additions & 0 deletions

File tree

scripts/install.cmd

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,34 @@ if !ERRORLEVEL! neq 0 (
127127
echo set PATH=%%PATH%%;!INSTALL_DIR!
128128
)
129129

130+
REM Validate plugin hooks.json if plugin is already installed
131+
if defined CLAUDE_CONFIG_DIR (
132+
set "PLUGIN_HOOKS=%CLAUDE_CONFIG_DIR%\plugins\marketplaces\plannotator\apps\hook\hooks\hooks.json"
133+
) else (
134+
set "PLUGIN_HOOKS=%USERPROFILE%\.claude\plugins\marketplaces\plannotator\apps\hook\hooks\hooks.json"
135+
)
136+
if exist "!PLUGIN_HOOKS!" (
137+
(
138+
echo {
139+
echo "hooks": {
140+
echo "PermissionRequest": [
141+
echo {
142+
echo "matcher": "ExitPlanMode",
143+
echo "hooks": [
144+
echo {
145+
echo "type": "command",
146+
echo "command": "plannotator",
147+
echo "timeout": 345600
148+
echo }
149+
echo ]
150+
echo }
151+
echo ]
152+
echo }
153+
echo }
154+
) > "!PLUGIN_HOOKS!"
155+
echo Updated plugin hooks at !PLUGIN_HOOKS!
156+
)
157+
130158
REM Install /review slash command
131159
if defined CLAUDE_CONFIG_DIR (
132160
set "CLAUDE_COMMANDS_DIR=%CLAUDE_CONFIG_DIR%\commands"
@@ -178,5 +206,29 @@ echo /plugin marketplace add backnotprop/plannotator
178206
echo /plugin install plannotator@plannotator
179207
echo.
180208
echo The /plannotator-review and /plannotator-annotate commands are ready to use!
209+
210+
REM Warn if plannotator is configured in both settings.json hooks AND the plugin (causes double execution)
211+
REM Only warn when the plugin is installed — manual-only users won't have overlap
212+
if defined CLAUDE_CONFIG_DIR (
213+
set "CLAUDE_SETTINGS=%CLAUDE_CONFIG_DIR%\settings.json"
214+
) else (
215+
set "CLAUDE_SETTINGS=%USERPROFILE%\.claude\settings.json"
216+
)
217+
if exist "!PLUGIN_HOOKS!" if exist "!CLAUDE_SETTINGS!" (
218+
findstr /r /c:"\"command\".*plannotator" "!CLAUDE_SETTINGS!" >nul 2>&1
219+
if !ERRORLEVEL! equ 0 (
220+
echo.
221+
echo WARNING: DUPLICATE HOOK DETECTED
222+
echo.
223+
echo plannotator was found in your settings.json hooks:
224+
echo !CLAUDE_SETTINGS!
225+
echo.
226+
echo This will cause plannotator to run TWICE on each plan review.
227+
echo Remove the plannotator hook from settings.json and rely on the
228+
echo plugin instead ^(installed automatically via marketplace^).
229+
echo.
230+
)
231+
)
232+
181233
echo.
182234
exit /b 0

scripts/install.ps1

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,30 @@ if ($userPath -notlike "*$installDir*") {
8282
Write-Host "Added to PATH. Restart your terminal for changes to take effect."
8383
}
8484

85+
# Validate plugin hooks.json if plugin is already installed
86+
$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" }
87+
if (Test-Path $pluginHooks) {
88+
@'
89+
{
90+
"hooks": {
91+
"PermissionRequest": [
92+
{
93+
"matcher": "ExitPlanMode",
94+
"hooks": [
95+
{
96+
"type": "command",
97+
"command": "plannotator",
98+
"timeout": 345600
99+
}
100+
]
101+
}
102+
]
103+
}
104+
}
105+
'@ | Set-Content -Path $pluginHooks
106+
Write-Host "Updated plugin hooks at $pluginHooks"
107+
}
108+
85109
# Clear OpenCode plugin cache
86110
Remove-Item -Recurse -Force "$env:USERPROFILE\.cache\opencode\node_modules\@plannotator" -ErrorAction SilentlyContinue
87111
Remove-Item -Recurse -Force "$env:USERPROFILE\.bun\install\cache\@plannotator" -ErrorAction SilentlyContinue
@@ -172,3 +196,23 @@ Write-Host " /plugin marketplace add backnotprop/plannotator"
172196
Write-Host " /plugin install plannotator@plannotator"
173197
Write-Host ""
174198
Write-Host "The /plannotator-review and /plannotator-annotate commands are ready to use after you restart Claude Code!"
199+
200+
# Warn if plannotator is configured in both settings.json hooks AND the plugin (causes double execution)
201+
# Only warn when the plugin is installed — manual-only users won't have overlap
202+
$claudeSettings = if ($env:CLAUDE_CONFIG_DIR) { "$env:CLAUDE_CONFIG_DIR\settings.json" } else { "$env:USERPROFILE\.claude\settings.json" }
203+
if ((Test-Path $pluginHooks) -and (Test-Path $claudeSettings)) {
204+
$settingsContent = Get-Content -Path $claudeSettings -Raw -ErrorAction SilentlyContinue
205+
if ($settingsContent -match '"command".*plannotator') {
206+
Write-Host ""
207+
Write-Host "⚠️ ⚠️ ⚠️ WARNING: DUPLICATE HOOK DETECTED ⚠️ ⚠️ ⚠️"
208+
Write-Host ""
209+
Write-Host " plannotator was found in your settings.json hooks:"
210+
Write-Host " $claudeSettings"
211+
Write-Host ""
212+
Write-Host " This will cause plannotator to run TWICE on each plan review."
213+
Write-Host " Remove the plannotator hook from settings.json and rely on the"
214+
Write-Host " plugin instead (installed automatically via marketplace)."
215+
Write-Host ""
216+
Write-Host "⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️"
217+
}
218+
}

scripts/install.sh

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,30 @@ if ! echo "$PATH" | tr ':' '\n' | grep -qx "$INSTALL_DIR"; then
8383
echo " source ${shell_config}"
8484
fi
8585

86+
# Validate plugin hooks.json if plugin is already installed
87+
PLUGIN_HOOKS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/plugins/marketplaces/plannotator/apps/hook/hooks/hooks.json"
88+
if [ -f "$PLUGIN_HOOKS" ]; then
89+
cat > "$PLUGIN_HOOKS" << 'HOOKS_EOF'
90+
{
91+
"hooks": {
92+
"PermissionRequest": [
93+
{
94+
"matcher": "ExitPlanMode",
95+
"hooks": [
96+
{
97+
"type": "command",
98+
"command": "plannotator",
99+
"timeout": 345600
100+
}
101+
]
102+
}
103+
]
104+
}
105+
}
106+
HOOKS_EOF
107+
echo "Updated plugin hooks at ${PLUGIN_HOOKS}"
108+
fi
109+
86110
# Clear any cached OpenCode plugin to force fresh download on next run
87111
rm -rf "$HOME/.cache/opencode/node_modules/@plannotator" "$HOME/.bun/install/cache/@plannotator" 2>/dev/null || true
88112

@@ -172,3 +196,20 @@ echo " /plugin marketplace add backnotprop/plannotator"
172196
echo " /plugin install plannotator@plannotator"
173197
echo ""
174198
echo "The /plannotator-review and /plannotator-annotate commands are ready to use after you restart Claude Code!"
199+
200+
# Warn if plannotator is configured in both settings.json hooks AND the plugin (causes double execution)
201+
# Only warn when the plugin is installed — manual-only users won't have overlap
202+
CLAUDE_SETTINGS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json"
203+
if [ -f "$PLUGIN_HOOKS" ] && [ -f "$CLAUDE_SETTINGS" ] && grep -q '"command".*plannotator' "$CLAUDE_SETTINGS" 2>/dev/null; then
204+
echo ""
205+
echo "⚠️ ⚠️ ⚠️ WARNING: DUPLICATE HOOK DETECTED ⚠️ ⚠️ ⚠️"
206+
echo ""
207+
echo " plannotator was found in your settings.json hooks:"
208+
echo " $CLAUDE_SETTINGS"
209+
echo ""
210+
echo " This will cause plannotator to run TWICE on each plan review."
211+
echo " Remove the plannotator hook from settings.json and rely on the"
212+
echo " plugin instead (installed automatically via marketplace)."
213+
echo ""
214+
echo "⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️"
215+
fi

0 commit comments

Comments
 (0)