Description
On every Claude Code session start, ECC's plugin hooks produce a warning like:
hooks.json: unknown keys "$schema", "description" in hooks.PreToolUse[0], "id" in hooks.PreToolUse[0], "description" in hooks.PreToolUse[1], "id" in hooks.PreToolUse[1] and 42 more ignored
The cause is hooks/hooks.json: it has a top-level $schema key, and every matcher entry under each event (PreToolUse, PostToolUse, Stop, etc.) carries description and id fields. Claude Code's actual hook-loading schema only recognizes matcher and hooks on a matcher entry (with type/command/async/timeout inside each hook item) — it does not accept $schema, description, or id there, so all 47 of those fields are silently dropped with a warning on every startup.
Note that scripts/ci/validate-hooks.js + schemas/hooks.schema.json don't catch this because that schema's matcherEntry definition doesn't set additionalProperties: false, so id (which isn't even declared in the schema's properties) passes CI validation even though Claude Code's real loader rejects it.
Also worth confirming: the id/description values in hooks/hooks.json don't appear to be read back by any ECC runtime code — scripts/hooks/posttooluse-dispatcher.js, for example, hardcodes its own separate list of hook ids rather than reading them from hooks.json. So these fields look like leftover/decorative metadata rather than something functionally required.
Steps to reproduce
- Install the ECC plugin via the Claude Code plugin marketplace.
- Start a new Claude Code session.
- Observe the "unknown keys ... ignored" warning referencing
hooks.PreToolUse[0], [1], etc.
Expected behavior
No schema warnings on startup; hooks/hooks.json should only contain keys Claude Code's hook loader recognizes (matcher, hooks, and per-hook type/command/async/timeout).
Actual behavior
Warning is printed every session, listing 47 ignored fields ($schema + description/id on each of the 21 matcher entries).
Suggested fix
Strip $schema from the top level and description/id from each matcher entry in hooks/hooks.json (and consider updating schemas/hooks.schema.json to set additionalProperties: false on matcherEntry so CI catches this class of drift in the future, if that schema is meant to mirror Claude Code's real loader).
I've validated locally that removing these 47 fields keeps the file valid JSON and eliminates the warning — happy to attach a diff/PR if useful.
Environment
- Claude Code 2.1.x
- ECC plugin version 2.2.1 (installed via marketplace)
- Windows 11
Description
On every Claude Code session start, ECC's plugin hooks produce a warning like:
The cause is
hooks/hooks.json: it has a top-level$schemakey, and every matcher entry under each event (PreToolUse,PostToolUse,Stop, etc.) carriesdescriptionandidfields. Claude Code's actual hook-loading schema only recognizesmatcherandhookson a matcher entry (withtype/command/async/timeoutinside each hook item) — it does not accept$schema,description, oridthere, so all 47 of those fields are silently dropped with a warning on every startup.Note that
scripts/ci/validate-hooks.js+schemas/hooks.schema.jsondon't catch this because that schema'smatcherEntrydefinition doesn't setadditionalProperties: false, soid(which isn't even declared in the schema'sproperties) passes CI validation even though Claude Code's real loader rejects it.Also worth confirming: the
id/descriptionvalues inhooks/hooks.jsondon't appear to be read back by any ECC runtime code —scripts/hooks/posttooluse-dispatcher.js, for example, hardcodes its own separate list of hook ids rather than reading them fromhooks.json. So these fields look like leftover/decorative metadata rather than something functionally required.Steps to reproduce
hooks.PreToolUse[0],[1], etc.Expected behavior
No schema warnings on startup;
hooks/hooks.jsonshould only contain keys Claude Code's hook loader recognizes (matcher,hooks, and per-hooktype/command/async/timeout).Actual behavior
Warning is printed every session, listing 47 ignored fields ($schema + description/id on each of the 21 matcher entries).
Suggested fix
Strip
$schemafrom the top level anddescription/idfrom each matcher entry inhooks/hooks.json(and consider updatingschemas/hooks.schema.jsonto setadditionalProperties: falseonmatcherEntryso CI catches this class of drift in the future, if that schema is meant to mirror Claude Code's real loader).I've validated locally that removing these 47 fields keeps the file valid JSON and eliminates the warning — happy to attach a diff/PR if useful.
Environment