From fe60f05d28d45257d073161a8bc1a1c039faca15 Mon Sep 17 00:00:00 2001 From: Fuat Date: Tue, 28 Apr 2026 22:27:51 +0300 Subject: [PATCH] fix(hookify): drop hookify.* import prefix so hooks resolve in versioned cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each hook script's sys.path setup added the parent of CLAUDE_PLUGIN_ROOT in the hope that Python would find a hookify package there. That works in dev mode (parent dir of plugins/hookify is plugins/, which literally contains hookify/ as a subdirectory) but fails in production where the cache layout puts the plugin at .../hookify/0.1.0/ — the parent dir contains only the version directory. All four hooks then fail import, emit a systemMessage, and exit 0; the plugin silently no-ops for every cache install. Drop the hookify. prefix from the imports across the four hook scripts and the core rule_engine module, and rely on the existing sys.path.insert(0, PLUGIN_ROOT) so that core, matchers, and utils resolve as top-level packages. The dead parent_dir block (which was the misleading mechanism) is removed and the comment updated. Closes #47868. Closes #33409. --- plugins/hookify/core/rule_engine.py | 4 ++-- plugins/hookify/hooks/posttooluse.py | 15 ++++++--------- plugins/hookify/hooks/pretooluse.py | 19 ++++++------------- plugins/hookify/hooks/stop.py | 15 ++++++--------- plugins/hookify/hooks/userpromptsubmit.py | 15 ++++++--------- 5 files changed, 26 insertions(+), 42 deletions(-) diff --git a/plugins/hookify/core/rule_engine.py b/plugins/hookify/core/rule_engine.py index 8244c00591..51561c39e9 100644 --- a/plugins/hookify/core/rule_engine.py +++ b/plugins/hookify/core/rule_engine.py @@ -7,7 +7,7 @@ from typing import List, Dict, Any, Optional # Import from local module -from hookify.core.config_loader import Rule, Condition +from core.config_loader import Rule, Condition # Cache compiled regexes (max 128 patterns) @@ -275,7 +275,7 @@ def _regex_match(self, pattern: str, text: str) -> bool: # For testing if __name__ == '__main__': - from hookify.core.config_loader import Condition, Rule + from core.config_loader import Condition, Rule # Test rule evaluation rule = Rule( diff --git a/plugins/hookify/hooks/posttooluse.py b/plugins/hookify/hooks/posttooluse.py index a9e12cc797..cb7a7e4c60 100755 --- a/plugins/hookify/hooks/posttooluse.py +++ b/plugins/hookify/hooks/posttooluse.py @@ -9,18 +9,15 @@ import sys import json -# CRITICAL: Add plugin root to Python path for imports +# Add the plugin root to sys.path so internal modules (core, matchers, utils) +# resolve as top-level packages. PLUGIN_ROOT = os.environ.get('CLAUDE_PLUGIN_ROOT') -if PLUGIN_ROOT: - parent_dir = os.path.dirname(PLUGIN_ROOT) - if parent_dir not in sys.path: - sys.path.insert(0, parent_dir) - if PLUGIN_ROOT not in sys.path: - sys.path.insert(0, PLUGIN_ROOT) +if PLUGIN_ROOT and PLUGIN_ROOT not in sys.path: + sys.path.insert(0, PLUGIN_ROOT) try: - from hookify.core.config_loader import load_rules - from hookify.core.rule_engine import RuleEngine + from core.config_loader import load_rules + from core.rule_engine import RuleEngine except ImportError as e: error_msg = {"systemMessage": f"Hookify import error: {e}"} print(json.dumps(error_msg), file=sys.stdout) diff --git a/plugins/hookify/hooks/pretooluse.py b/plugins/hookify/hooks/pretooluse.py index f265c277e3..083e555722 100755 --- a/plugins/hookify/hooks/pretooluse.py +++ b/plugins/hookify/hooks/pretooluse.py @@ -9,22 +9,15 @@ import sys import json -# CRITICAL: Add plugin root to Python path for imports -# We need to add the parent of the plugin directory so Python can find "hookify" package +# Add the plugin root to sys.path so internal modules (core, matchers, utils) +# resolve as top-level packages. PLUGIN_ROOT = os.environ.get('CLAUDE_PLUGIN_ROOT') -if PLUGIN_ROOT: - # Add the parent directory of the plugin - parent_dir = os.path.dirname(PLUGIN_ROOT) - if parent_dir not in sys.path: - sys.path.insert(0, parent_dir) - - # Also add PLUGIN_ROOT itself in case we have other scripts - if PLUGIN_ROOT not in sys.path: - sys.path.insert(0, PLUGIN_ROOT) +if PLUGIN_ROOT and PLUGIN_ROOT not in sys.path: + sys.path.insert(0, PLUGIN_ROOT) try: - from hookify.core.config_loader import load_rules - from hookify.core.rule_engine import RuleEngine + from core.config_loader import load_rules + from core.rule_engine import RuleEngine except ImportError as e: # If imports fail, allow operation and log error error_msg = {"systemMessage": f"Hookify import error: {e}"} diff --git a/plugins/hookify/hooks/stop.py b/plugins/hookify/hooks/stop.py index fc299bc696..57072d7989 100755 --- a/plugins/hookify/hooks/stop.py +++ b/plugins/hookify/hooks/stop.py @@ -9,18 +9,15 @@ import sys import json -# CRITICAL: Add plugin root to Python path for imports +# Add the plugin root to sys.path so internal modules (core, matchers, utils) +# resolve as top-level packages. PLUGIN_ROOT = os.environ.get('CLAUDE_PLUGIN_ROOT') -if PLUGIN_ROOT: - parent_dir = os.path.dirname(PLUGIN_ROOT) - if parent_dir not in sys.path: - sys.path.insert(0, parent_dir) - if PLUGIN_ROOT not in sys.path: - sys.path.insert(0, PLUGIN_ROOT) +if PLUGIN_ROOT and PLUGIN_ROOT not in sys.path: + sys.path.insert(0, PLUGIN_ROOT) try: - from hookify.core.config_loader import load_rules - from hookify.core.rule_engine import RuleEngine + from core.config_loader import load_rules + from core.rule_engine import RuleEngine except ImportError as e: error_msg = {"systemMessage": f"Hookify import error: {e}"} print(json.dumps(error_msg), file=sys.stdout) diff --git a/plugins/hookify/hooks/userpromptsubmit.py b/plugins/hookify/hooks/userpromptsubmit.py index 28ee51fdf3..b2550bb552 100755 --- a/plugins/hookify/hooks/userpromptsubmit.py +++ b/plugins/hookify/hooks/userpromptsubmit.py @@ -9,18 +9,15 @@ import sys import json -# CRITICAL: Add plugin root to Python path for imports +# Add the plugin root to sys.path so internal modules (core, matchers, utils) +# resolve as top-level packages. PLUGIN_ROOT = os.environ.get('CLAUDE_PLUGIN_ROOT') -if PLUGIN_ROOT: - parent_dir = os.path.dirname(PLUGIN_ROOT) - if parent_dir not in sys.path: - sys.path.insert(0, parent_dir) - if PLUGIN_ROOT not in sys.path: - sys.path.insert(0, PLUGIN_ROOT) +if PLUGIN_ROOT and PLUGIN_ROOT not in sys.path: + sys.path.insert(0, PLUGIN_ROOT) try: - from hookify.core.config_loader import load_rules - from hookify.core.rule_engine import RuleEngine + from core.config_loader import load_rules + from core.rule_engine import RuleEngine except ImportError as e: error_msg = {"systemMessage": f"Hookify import error: {e}"} print(json.dumps(error_msg), file=sys.stdout)