fix(hookify): make package import independent of the install directory name - #81672
Open
ozdemirsarman wants to merge 1 commit into
Open
fix(hookify): make package import independent of the install directory name#81672ozdemirsarman wants to merge 1 commit into
ozdemirsarman wants to merge 1 commit into
Conversation
…y name
The hook entry points made the `hookify` package importable by putting
`os.path.dirname(CLAUDE_PLUGIN_ROOT)` on `sys.path` and relying on the plugin
directory being named exactly `hookify`.
A marketplace install does not satisfy that: the plugin is unpacked into a
versioned directory (`.../hookify@0.1.0`), so `hookify` is not a name Python
can resolve there. Every hook event then hits the ImportError branch and the
plugin emits `Hookify import error: No module named 'hookify'` instead of
evaluating any rule - the plugin appears installed but is inert.
Instead of guessing the package name from the directory layout, register the
package explicitly with its `__path__` pinned to the plugin root
(hooks/_bootstrap.py). This also removes the dependency on CLAUDE_PLUGIN_ROOT
being set or correct: the root is derived from `__file__` when the variable is
missing or does not point at a hookify checkout.
Verified against a versioned marketplace layout, with a real rule file in
.claude/hookify.dangerous-rm.local.md:
before: {"systemMessage": "Hookify import error: No module named 'hookify'"}
after: {"systemMessage": "**[block-dangerous-rm]** ..."}
Also verified for all four entry points (PreToolUse, PostToolUse, Stop,
UserPromptSubmit), with CLAUDE_PLUGIN_ROOT unset, with CLAUDE_PLUGIN_ROOT
pointing at a nonexistent path, and for the plain `hookify/` directory layout
that already worked.
Fixes anthropics#69665
Fixes anthropics#81448
This was referenced Jul 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #69665
Fixes #81448
The problem
The hook entry points make the
hookifypackage importable by puttingos.path.dirname(CLAUDE_PLUGIN_ROOT)onsys.pathand relying on the plugindirectory being named exactly
hookify.A marketplace install does not satisfy that — the plugin is unpacked into a
versioned directory (
.../hookify@0.1.0), sohookifyis not a name Python canresolve there. Every hook event hits the
ImportErrorbranch and the plugin emitsHookify import error: No module named 'hookify'instead of evaluating any rule.The plugin looks installed but is inert, on every single hook event.
Repro
With a real rule at
.claude/hookify.dangerous-rm.local.mdand input{"tool_name":"Bash","tool_input":{"command":"rm -rf /"}}:The fix
Rather than inferring the package name from the directory layout, register the
package explicitly with its
__path__pinned to the plugin root(
hooks/_bootstrap.py). That makes the import independent of the directory name.It also removes the dependency on
CLAUDE_PLUGIN_ROOTbeing set and correct: theroot falls back to a path derived from
__file__when the variable is missing ordoes not point at a hookify checkout.
Testing
hookify@0.1.0directory.CLAUDE_PLUGIN_ROOTunset — works.CLAUDE_PLUGIN_ROOTpointing at a nonexistent path — works.hookify/directory layout — unchanged, still works.