Skip to content

fix(plugin-dev): validate-hook-schema.sh handles plugin hooks.json format#77556

Open
sorapallivenkatesh wants to merge 1 commit into
anthropics:mainfrom
sorapallivenkatesh:fix/validate-hook-schema-plugin-format
Open

fix(plugin-dev): validate-hook-schema.sh handles plugin hooks.json format#77556
sorapallivenkatesh wants to merge 1 commit into
anthropics:mainfrom
sorapallivenkatesh:fix/validate-hook-schema-plugin-format

Conversation

@sorapallivenkatesh

Copy link
Copy Markdown

Problem

The hook-schema validator shipped in the plugin-dev plugin's Hook Development skill (plugins/plugin-dev/skills/hook-development/scripts/validate-hook-schema.sh) has two bugs that make it fail on valid configurations — including the exact format the skill itself documents.

1. Crashes on plugin hooks.json files.
The validator only understood the flat settings format, where hook events live at the top level. But plugin hooks.json uses a wrapper — events nested under a "hooks" key alongside an optional "description" — which is the format documented in SKILL.md and used by every bundled plugin (hookify, security-guidance, ralph-wiggum, …). Given a real plugin hooks.json, the validator treated description and hooks as event names and then crashed:

⚠️  Unknown event type: description
⚠️  Unknown event type: hooks
jq: error (at hooks.json:49): Cannot index string with number

2. Treats matcher as required.
It reported ❌ Missing 'matcher' field for any hook entry without a matcher. But matcher is optional: it only applies to PreToolUse/PostToolUse (to target specific tools), and even there an absent matcher means "match all". Events like Stop, SessionStart, and UserPromptSubmit never carry one, so valid configs failed validation.

Fix

  • Detect the config format and unwrap the plugin {"hooks": {...}} wrapper (ignoring description); fall back to the flat settings format.
  • Stop treating matcher as required.

No behavior change for genuinely invalid configs — missing hooks arrays, bad hook type, missing command/prompt, and non-numeric timeouts are still reported.

Verification

Input Before After
plugins/hookify/hooks/hooks.json (wrapper) crash ✅ passes
plugins/security-guidance/hooks/hooks.json (wrapper, matchers, timeouts) crash ✅ passes
flat settings config with a matcher-less Stop hook ❌ false "Missing matcher" ✅ passes
deliberately broken config (missing hooks array, bad type, missing command, bad timeout) errors ✅ still errors (exit 1)

…rmat

The hook schema validator only understood the flat settings.json format
(events at the top level). Given a plugin `hooks.json`, which wraps events
under a `"hooks"` key alongside an optional `"description"`, it treated
`description` and `hooks` as event names and then crashed with
`jq: Cannot index string with number`. This is the exact format the
Hook Development skill documents and every bundled plugin uses.

It also flagged a missing `matcher` field as an error for every hook, but
`matcher` is optional — it only applies to PreToolUse/PostToolUse, and even
there an absent matcher means "match all". Events like Stop, SessionStart,
and UserPromptSubmit never carry one, so valid configs failed validation.

- Detect and unwrap the plugin `{"hooks": {...}}` wrapper; fall back to the
  flat settings format.
- Stop treating `matcher` as required.

Verified against the bundled hookify and security-guidance hooks.json
(now pass), a flat matcher-less Stop config (now passes), and a
deliberately broken config (errors still reported).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant