From 3b681a3858cd3a94945ed57743a0541d409fc070 Mon Sep 17 00:00:00 2001 From: Chris Peterson Date: Wed, 23 Sep 2026 19:12:33 -0700 Subject: [PATCH] Quote the plugin root in every hook command The three hook commands expanded ${CLAUDE_PLUGIN_ROOT} bare, so a plugin installed under a path with a space split into several words and the watchdog never ran. Claude Code 2.1.281's `claude plugin validate` now warns on each one, and shipyard's projection gate fails on any warning plugin.yml doesn't accept, so the gate goes red once its validator pin reaches 2.1.281. SPEC.md, SCHEMA.md and the rules skill quote the same commands, so they match what the hooks run. --- SCHEMA.md | 4 ++-- SPEC.md | 2 +- hooks/hooks.json | 6 +++--- hooks/hooks.yml | 6 +++--- skills/rules/SKILL.md | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/SCHEMA.md b/SCHEMA.md index 092320e..b27a503 100644 --- a/SCHEMA.md +++ b/SCHEMA.md @@ -209,7 +209,7 @@ Two `PreToolUse` hooks point the engine at the `watches/` directory — one for "hooks": [ { "type": "command", - "command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/watchdog.py ${CLAUDE_PLUGIN_ROOT}/watches" + "command": "python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/watchdog.py\" \"${CLAUDE_PLUGIN_ROOT}/watches\"" } ] }, @@ -218,7 +218,7 @@ Two `PreToolUse` hooks point the engine at the `watches/` directory — one for "hooks": [ { "type": "command", - "command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/watchdog.py ${CLAUDE_PLUGIN_ROOT}/watches" + "command": "python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/watchdog.py\" \"${CLAUDE_PLUGIN_ROOT}/watches\"" } ] } diff --git a/SPEC.md b/SPEC.md index ebf5103..043f77b 100644 --- a/SPEC.md +++ b/SPEC.md @@ -232,7 +232,7 @@ These describe how the current implementation satisfies the spec. They are pure-Python YAML parser (no PyYAML dependency). The parser supports inline list syntax (`['.ps1', '.psm1']`) for the top-level `extensions` field. - The hook command line is - `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/watchdog.py ${CLAUDE_PLUGIN_ROOT}/watches`, + `python3 "${CLAUDE_PLUGIN_ROOT}/scripts/watchdog.py" "${CLAUDE_PLUGIN_ROOT}/watches"`, invoked from two `PreToolUse` matchers: `Bash|Monitor` and `Write|Edit`. - The ambient-guidance emission ([HK-04]) is a second SessionStart hook, `hooks/emit-rules.sh`, which prints a `# Ambient rules from the ClaudeWatch diff --git a/hooks/hooks.json b/hooks/hooks.json index 835e319..211552d 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -6,7 +6,7 @@ "hooks": [ { "type": "command", - "command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/watchdog.py ${CLAUDE_PLUGIN_ROOT}/watches" + "command": "python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/watchdog.py\" \"${CLAUDE_PLUGIN_ROOT}/watches\"" } ] }, @@ -15,7 +15,7 @@ "hooks": [ { "type": "command", - "command": "python3 ${CLAUDE_PLUGIN_ROOT}/scripts/watchdog.py ${CLAUDE_PLUGIN_ROOT}/watches" + "command": "python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/watchdog.py\" \"${CLAUDE_PLUGIN_ROOT}/watches\"" } ] } @@ -25,7 +25,7 @@ "hooks": [ { "type": "command", - "command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/emit-rules.sh" + "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/emit-rules.sh\"" } ] } diff --git a/hooks/hooks.yml b/hooks/hooks.yml index 85d805f..ab60708 100644 --- a/hooks/hooks.yml +++ b/hooks/hooks.yml @@ -2,12 +2,12 @@ hooks: - event: PreToolUse matcher: Bash|Monitor - command: 'python3 ${CLAUDE_PLUGIN_ROOT}/scripts/watchdog.py ${CLAUDE_PLUGIN_ROOT}/watches' + command: 'python3 "${CLAUDE_PLUGIN_ROOT}/scripts/watchdog.py" "${CLAUDE_PLUGIN_ROOT}/watches"' description: Screens the shell command against the watch rules before it runs. Monitor is included because it runs its command in the same shell as Bash. - event: PreToolUse matcher: Write|Edit - command: 'python3 ${CLAUDE_PLUGIN_ROOT}/scripts/watchdog.py ${CLAUDE_PLUGIN_ROOT}/watches' + command: 'python3 "${CLAUDE_PLUGIN_ROOT}/scripts/watchdog.py" "${CLAUDE_PLUGIN_ROOT}/watches"' description: Screens the code Claude writes to disk against the watch rules before it lands. - event: SessionStart - command: 'bash ${CLAUDE_PLUGIN_ROOT}/hooks/emit-rules.sh' + command: 'bash "${CLAUDE_PLUGIN_ROOT}/hooks/emit-rules.sh"' description: Emit ClaudeWatch's ambient guidance into context. diff --git a/skills/rules/SKILL.md b/skills/rules/SKILL.md index 3cc4c3e..c6d931d 100644 --- a/skills/rules/SKILL.md +++ b/skills/rules/SKILL.md @@ -160,7 +160,7 @@ rules: ### 9. Verify -Run `bash ${CLAUDE_PLUGIN_ROOT}/tests/test-watchdog.sh`. If tests fail, explain which +Run `bash "${CLAUDE_PLUGIN_ROOT}/tests/test-watchdog.sh"`. If tests fail, explain which rule caused the failure and offer to fix or revert. If any rules were added, note that the test file has no coverage for them yet