surshar / claude-code
Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.
Built by Anthropic · github.com/anthropics
| 1 | #!/usr/bin/env python3 |
| 2 | """PostToolUse hook executor for hookify plugin. |
| 3 | |
| 4 | This script is called by Claude Code after a tool executes. |
| 5 | It reads .claude/hookify.*.local.md files and evaluates rules. |
| 6 | """ |
| 7 | |
| 8 | import os |
| 9 | import sys |
| 10 | import json |
| 11 | |
| 12 | # CRITICAL: Add plugin root to Python path for imports |
| 13 | PLUGIN_ROOT = os.environ.get('CLAUDE_PLUGIN_ROOT') |
| 14 | if PLUGIN_ROOT: |
| 15 | parent_dir = os.path.dirname(PLUGIN_ROOT) |
| 16 | if parent_dir not in sys.path: |
| 17 | sys.path.insert(0, parent_dir) |
| 18 | if PLUGIN_ROOT not in sys.path: |
| 19 | sys.path.insert(0, PLUGIN_ROOT) |
| 20 | |
| 21 | try: |
| 22 | from hookify.core.config_loader import load_rules |
| 23 | from hookify.core.rule_engine import RuleEngine |
| 24 | except ImportError as e: |
| 25 | error_msg = {"systemMessage": f"Hookify import error: {e}"} |
| 26 | print(json.dumps(error_msg), file=sys.stdout) |
| 27 | sys.exit(0) |
| 28 | |
| 29 | |
| 30 | def main(): |
| 31 | """Main entry point for PostToolUse hook.""" |
| 32 | try: |
| 33 | # Read input from stdin |
| 34 | input_data = json.load(sys.stdin) |
| 35 | |
| 36 | # Determine event type based on tool |
| 37 | tool_name = input_data.get('tool_name', '') |
| 38 | event = None |
| 39 | if tool_name == 'Bash': |
| 40 | event = 'bash' |
| 41 | elif tool_name in ['Edit', 'Write', 'MultiEdit']: |
| 42 | event = 'file' |
| 43 | |
| 44 | # Load rules |
| 45 | rules = load_rules(event=event) |
| 46 | |
| 47 | # Evaluate rules |
| 48 | engine = RuleEngine() |
| 49 | result = engine.evaluate_rules(rules, input_data) |
| 50 | |
| 51 | # Always output JSON (even if empty) |
| 52 | print(json.dumps(result), file=sys.stdout) |
| 53 | |
| 54 | except Exception as e: |
| 55 | error_output = { |
| 56 | "systemMessage": f"Hookify error: {str(e)}" |
| 57 | } |
| 58 | print(json.dumps(error_output), file=sys.stdout) |
| 59 | |
| 60 | finally: |
| 61 | # ALWAYS exit 0 |
| 62 | sys.exit(0) |
| 63 | |
| 64 | |
| 65 | if __name__ == '__main__': |
| 66 | main() |