Plugin hooks.json entries using exec form (command + args array) are silently ignored
Open 💬 2 comments Opened Jul 13, 2026 by StakeholderSensei
Environment
- Claude Code 2.1.59, Windows 11 Pro (10.0.26200), Node v22.20.0
- Plugin installed from a local marketplace (
claude plugin marketplace add <path>+claude plugin install)
Observed
A plugin's hooks/hooks.json entry registered in exec form never executes — no hook fires, no error or warning is surfaced (nothing in --debug, plugin shows enabled):
{ "type": "command", "command": "node", "args": ["${CLAUDE_PLUGIN_ROOT}/scripts/entry.mjs", "SessionStart"], "timeout": 5 }
Rewriting the same entry in string form makes it fire on every event as expected:
{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/entry.mjs\" SessionStart", "timeout": 5 }
Repro
- Create a minimal plugin whose hook script appends a line to a file.
- Register any hook (e.g. SessionStart) in exec form as above; install; run
claude -p "reply OK"→ file untouched. - Switch the same entry to string form; reinstall; rerun → file written.
Expected
Either exec form executes (the plugins reference recommends command+args for ${CLAUDE_PLUGIN_ROOT} paths that may contain spaces), or invalid/unsupported hook entries produce a validation warning instead of being dropped silently.
Found while building a hooks-based plugin (https://github.com/StakeholderSensei/polygraph); happy to provide the full probe transcripts.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗