| |
| """PreToolUse hook executor for hookify plugin. |
| |
| This script is called by Claude Code before any tool executes. |
| It reads .claude/hookify.*.local.md files and evaluates rules. |
| """ |
|
|
| import os |
| import sys |
| import json |
|
|
| |
| |
| 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) |
|
|
| try: |
| from hookify.core.config_loader import load_rules |
| from hookify.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) |
| sys.exit(0) |
|
|
|
|
| def main(): |
| """Main entry point for PreToolUse hook.""" |
| try: |
| |
| input_data = json.load(sys.stdin) |
|
|
| |
| |
| tool_name = input_data.get('tool_name', '') |
|
|
| event = None |
| if tool_name == 'Bash': |
| event = 'bash' |
| elif tool_name in ['Edit', 'Write', 'MultiEdit']: |
| event = 'file' |
|
|
| |
| rules = load_rules(event=event) |
|
|
| |
| engine = RuleEngine() |
| result = engine.evaluate_rules(rules, input_data) |
|
|
| |
| print(json.dumps(result), file=sys.stdout) |
|
|
| except Exception as e: |
| |
| error_output = { |
| "systemMessage": f"Hookify error: {str(e)}" |
| } |
| print(json.dumps(error_output), file=sys.stdout) |
|
|
| finally: |
| |
| sys.exit(0) |
|
|
|
|
| if __name__ == '__main__': |
| main() |
|
|