[BUG] hookify plugin fails with "No module named 'hookify'" on every hook invocation
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Every hook invocation (PreToolUse, PostToolUse, UserPromptSubmit, Stop) from the hookify plugin fails with an import error: "Hookify import error: No module named 'hookify'". It prints on every single tool call and session event, but doesn't block execution — meaning hookify's rules never actually get evaluated or enforced, silently.
What Should Happen?
Hookify's hook scripts should successfully import their internal modules and evaluate configured .local.md rules without printing an import error.
Error Messages/Logs
Hookify import error: No module named 'hookify'
Steps to Reproduce
- Install hookify: /plugin marketplace add anthropics/claude-code, then /plugin install hookify@claude-code-plugins
- Create any rule file in .claude/, e.g. .claude/hookify.test.local.md with a basic "warn on file" rule
- Trigger any Write, Edit, Bash, or prompt submission
- Every PreToolUse/PostToolUse/UserPromptSubmit/Stop hook prints "Hookify import error: No module named 'hookify'" instead of evaluating the rule
Root cause (found by inspecting the installed plugin): the hook scripts do from hookify.core.config_loader import load_rules, but the actual installed layout is .../claude-code-plugins/hookify/0.1.0/core/config_loader.py — there's no hookify package directory wrapping core/, it sits directly under the versioned 0.1.0 folder. Neither PLUGIN_ROOT nor its parent on sys.path makes hookify.core.config_loader resolve. Should be from core.config_loader import load_rules instead, using PLUGIN_ROOT which is already on sys.path.
The failure is wrapped in a bare exception handler that prints the message and exits 0, so rules are silently never evaluated rather than causing a hard failure.
Claude Model
None
Is this a regression?
No, this never worked
Last Working Version
_No response_
Claude Code Version
version 2.1.220.
Platform
Other
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
Plugin: hookify 0.1.0, installed via the claude-code-plugins marketplace (anthropics/claude-code repo, plugins/hookify). Installed path: ~/.claude/plugins/cache/claude-code-plugins/hookify/0.1.0/
Showing cached comments. Read the full discussion on GitHub ↗
3 Comments
Confirmed on macOS 26.6, Claude Code 2.1.220 — same failure, so it's layout-generic, not Windows-specific. Two data points to add:
1. This is a same-version regression of #47868's fix, not "never worked". My installed cache copy of hookify 0.1.0 (fetched weeks ago) had the working relative imports (
from core.config_loader import load_rules) and evaluated rules correctly — verified by invoking the hook entrypoint directly. Runningclaude plugin install hookify@claude-code-plugins --scope projectfor a second project today re-synced the shared cache in place (still version 0.1.0, files re-stamped) and replaced them with thefrom hookify.core.*style — which instantly and silently killed every hookify rule in all projects sharing that cache. Same plugin version, two different published behaviors: any marketplace refresh swaps working → broken with no version signal. (#62679 / #69665 were earlier reports of the same import bug, closed as dups of #47868.)2. No-code-edit workaround — one symlink makes
import hookifyresolve as a namespace package inside the versioned cache layout:All four hook scripts share the same import block, so this heals PreToolUse/PostToolUse/UserPromptSubmit/Stop at once. Verified end-to-end by piping probe JSON through
CLAUDE_PLUGIN_ROOT=~/.claude/plugins/cache/claude-code-plugins/hookify/0.1.0 python3 .../hooks/pretooluse.py: warn and block rules fire again on matching input,{}on non-matching. (Caveat: a future re-sync deletes the symlink along with the cache dir — it needs re-creating until the imports are fixed upstream.)Also worth noting the failure mode is doubly silent for
action: warnrules: the import error goes tosystemMessage, which per #20747 is rendered user-side only — from the model's perspective, configured rules simply cease to exist.Confirmed on Windows 11 (Claude Code 2.1.233, hookify 0.1.0 from the marketplace cache). Two independent failure layers on this platform, plus a root-cause isolation experiment for the import error.
1. Root cause of
No module named 'hookify': the versioned cache dir name breaks the import contract.hooks/pretooluse.pydoesfrom hookify.core.config_loader import load_rulesand inserts the parent ofCLAUDE_PLUGIN_ROOTintosys.path(the comment in the code says: so Python can find the "hookify" package). That contract requires the plugin directory itself to be namedhookify. But the marketplace installs into a versioned path:so
parent_diris.../hookify/, which contains only0.1.0/— nothing importable ashookify.Isolation experiment — copy the cache dir to a folder literally named
hookifyand run the same hook with the same stdin:Same bytes, only the directory name differs — the code itself is fine; the layout assumption is what's broken. This is consistent with @zhian14's observation that an older cache copy using relative imports (
from core.config_loader import ...) worked: relative imports (or insertingCLAUDE_PLUGIN_ROOTitself with matching package layout) would fix this regardless of how the cache names version directories.2. Windows-only and independent of #1:
python3in hooks.json resolves to the Microsoft Store alias.All four hook commands are
python3 ${CLAUDE_PLUGIN_ROOT}/hooks/....py. On stock Windows,python3in PATH is the App Execution Alias (.../WindowsApps/python3.exe->AppInstallerPythonRedirector.exe), which printsPythonand exits 49 without ever running the script. A real CPython install providespythonandpy, but nopython3name. Run exactly the way Claude Code invokes hooks:So on Windows the hooks die before even reaching the import bug. The plugin needs a
python/pyfallback (or interpreter resolution) to work on Windows at all.Both failures are soft (message + non-blocking exit), so configured rules are silently never enforced — matching the "silently" wording in the OP.
Confirmed / reproduced on Claude Code 2.1.234 (Linux):
claude plugin marketplace add anthropics/claude-code+claude plugin install hookify@claude-code-pluginsinstalls hookify 0.1.0 into the plugin cache under a versionedhookify/0.1.0/directory, and feeding a PreToolUse (Bashrm -rf …, with a matching.claude/hookify.*.local.mdrule) or Stop payload to the installed hook scripts prints{"systemMessage": "Hookify import error: No module named 'hookify'"}
every time, so no rule is ever evaluated. For comparison,
hookify@claude-plugins-officialinstalled the same way evaluates the same rule file correctly (the bash rule fires), so switching to that marketplace's copy is a workaround until this one is fixed.🤖 Generated with Claude Code
---
_Generated by Claude Code_