#!/usr/bin/env python3 """Claude Hooks Installation Script for NPM Distribution""" import os import sys import json import shutil import subprocess from pathlib import Path # Colors for terminal output class Colors: RED = '\033[0;31m' GREEN = '\033[0;32m' YELLOW = '\033[1;33m' BLUE = '\033[0;34m' NC = '\033[0m' # No Color def print_colored(message, color): print(f"{color}{message}{Colors.NC}") def print_status(message, status="INFO"): colors = { "SUCCESS": Colors.GREEN, "ERROR": Colors.RED, "WARNING": Colors.YELLOW, "INFO": Colors.BLUE } print_colored(f"[{status}] {message}", colors.get(status, Colors.NC)) def main(): print_colored("Claude Code Hooks Initialization", Colors.BLUE) print("=" * 40) # Get package root (npm package location) package_root = Path(__file__).parent.parent claude_config_dir = Path.home() / ".config" / "claude" hooks_config_file = claude_config_dir / "hooks.json" # Check for existing installation print("Checking for existing Claude Hooks installation...") if hooks_config_file.exists(): print_status("Claude Hooks already configured!", "WARNING") response = input("Overwrite existing configuration? (y/N): ").lower() if response != 'y': print("Installation cancelled.") return 1 # Check Python version print("Checking Python version...") if sys.version_info < (3, 8): print_status(f"Python 3.8+ required, found {sys.version_info.major}.{sys.version_info.minor}", "ERROR") return 1 print_status(f"Python {sys.version_info.major}.{sys.version_info.minor} found", "SUCCESS") # Create Claude config directory print("Creating Claude config directory...") claude_config_dir.mkdir(parents=True, exist_ok=True) print_status("Claude config directory ready", "SUCCESS") # Generate hooks configuration print("Generating hooks configuration...") hooks_template = package_root / "config" / "hooks.json.template" if hooks_template.exists(): with open(hooks_template, 'r') as f: config_content = f.read() # Replace template variables config_content = config_content.replace("{{INSTALL_PATH}}", str(package_root)) with open(hooks_config_file, 'w') as f: f.write(config_content) print_status("Hooks configuration generated", "SUCCESS") else: # Fallback: create basic configuration hooks_config = { "hooks": { "UserPromptSubmit": f"python3 {package_root}/hooks/context_monitor.py", "PreToolUse": { "Bash": f"python3 {package_root}/hooks/command_validator.py" }, "PostToolUse": { "*": f"python3 {package_root}/hooks/session_logger.py" }, "Stop": f"python3 {package_root}/hooks/session_finalizer.py" } } with open(hooks_config_file, 'w') as f: json.dump(hooks_config, f, indent=2) print_status("Basic hooks configuration created", "SUCCESS") # Test hook scripts print("Testing hook scripts...") test_hook = package_root / "hooks" / "context_monitor.py" if test_hook.exists(): try: result = subprocess.run([ sys.executable, str(test_hook) ], input='{"prompt": "test"}', text=True, capture_output=True, timeout=10) if result.returncode == 0: print_status("Hook scripts working", "SUCCESS") else: print_status("Hook scripts may have issues", "WARNING") except subprocess.TimeoutExpired: print_status("Hook script test timeout", "WARNING") except Exception as e: print_status(f"Hook test error: {e}", "WARNING") else: print_status("Hook scripts not found", "WARNING") print() print_colored("Initialization Complete!", Colors.GREEN) print() print_colored("Next Steps:", Colors.BLUE) print("1. Restart Claude Code to activate the hooks") print("2. Test with: claude-hooks test") print("3. Try commands that commonly fail (pip vs pip3) to see learning in action") print() print(f"📁 Installation directory: {package_root}") print(f"⚙️ Configuration file: {hooks_config_file}") print() print_colored("The hooks will start learning from your usage patterns automatically.", Colors.YELLOW) return 0 if __name__ == "__main__": sys.exit(main())