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

  1. Create a minimal plugin whose hook script appends a line to a file.
  2. Register any hook (e.g. SessionStart) in exec form as above; install; run claude -p "reply OK" → file untouched.
  3. 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.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗