Skip to content

[BUG] hookify layer has no runtime: /hookify rules are never read or enforced #2561

Description

@nguyenphivn

Summary

The hookify feature ships the authoring half but not the execution half. /hookify generates rule files at .claude/hookify.<name>.local.md, and /hookify-configure lets you flip their enabled: field — but nothing in ECC ever reads or evaluates those files. Every rule created via /hookify is inert. It silently does nothing while giving the user the impression that a guardrail is now in place.

Environment

  • ECC version: 2.0.0 (installed via the Claude Code plugin marketplace)
  • Mechanism: Claude Code plugin hooks.json

Evidence

In the installed ECC plugin, hooks/ contains only:

hooks/
  memory-persistence/
  README.md
  hooks.json

There is no pretooluse / posttooluse / stop / userpromptsubmit handler, and no core/ (rule engine / config loader) or matchers/ directory anywhere in the plugin. Grepping the whole plugin outside commands/, skills/, and docs/ finds nothing that reads .claude/hookify.*.local.md: the string hookify appears only in command/skill/doc markdown, never in hooks/ or scripts/. hooks/hooks.json registers no handler that loads these rule files.

By contrast, Anthropic's official hookify plugin — which uses the identical .local.md rule format — ships the complete runtime:

hooks/pretooluse.py
hooks/posttooluse.py
hooks/stop.py
hooks/userpromptsubmit.py
hooks/hooks.json        # registers the 4 handlers, one per event
core/rule_engine.py
core/config_loader.py
matchers/

Its hooks/hooks.json wires each event to python3 "${CLAUDE_PLUGIN_ROOT}/hooks/<event>.py", which load and evaluate the rules. ECC has none of this.

Because the official plugin works on the same Claude Code hook mechanism, this is not a Claude Code regression — the hook API is intact. The runtime is simply absent from ECC's packaging.

Secondary issue: action: warn would be silent even if a runtime existed

Even with a dispatcher, the default action: warn maps to a hook exit code of 0. Under Claude Code's hook contract, only a non-zero blocking exit (exit 2) feeds the hook's stderr back into the model's context; exit 0 is invisible to the model. So warn rules would never surface to Claude regardless. A working implementation needs to emit the message via exit 2 (or the additionalContext field) for it to reach the agent.

Steps to reproduce

  1. /hookify <some behavior to prevent> → it creates .claude/hookify.<name>.local.md.
  2. Perform the action the rule is meant to warn about / block.
  3. Observe: nothing happens. The rule never fires. /hookify-configure shows it as enabled, but toggling enabled: changes nothing because no code reads the field.

Expected vs. actual

  • Expected: rules created by /hookify are read and enforced (warn/block), consistent with the command's stated purpose — "Create hooks to prevent unwanted behaviors" — and with /hookify-configure"Enable or disable hookify rules".
  • Actual: the rule files are never read; they enforce nothing.

Suggested fixes (any one addresses the core problem)

  1. Ship the runtime — port the official plugin's hooks/*.py + core/ + matchers/ (or an ECC-native equivalent) and register the per-event handlers in hooks/hooks.json.
  2. If ECC intends users to rely on the official hookify plugin (or native hooks) for enforcement, document that dependency explicitly and make /hookify / /hookify-configure state that the generated files require that separate runtime to have any effect.
  3. Ensure action: warn actually reaches the model (exit 2 with a clear message, or additionalContext), so warnings are not silently dropped.

Why this matters

The failure mode is not "junk files" — it is a false sense of safety. A user writes a rule to stop a recurring mistake, believes they are now protected, and the mistake recurs unguarded. Since the rule files are typically git-ignored, they never reach commit-time checks either, so nothing else catches the gap. Please either wire up enforcement or make the runtime requirement explicit in the docs.


Filed after diagnosing why /hookify-generated rules had no effect in a real project. Happy to provide additional detail or test a fix.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High priorityarea:hooksHook behavior, compatibility, or configurationbugSomething isn't workingchurn-signalLikely contributor to failed adoption or uninstallstaleNo activity for 30+ days

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions