#!/usr/bin/env python3 """ Claude Hooks CLI - Command line interface for managing hooks """ import argparse import json import sys from datetime import datetime from pathlib import Path from .backup_manager import BackupManager from .session_state import SessionStateManager from .shadow_learner import ShadowLearner from .context_monitor import ContextMonitor def list_backups(): """List available backups""" backup_manager = BackupManager() backups = backup_manager.list_backups() if not backups: print("No backups found.") return print("Available Backups:") print("==================") for backup in backups: timestamp = backup.get("timestamp", "unknown") backup_id = backup.get("backup_id", "unknown") reason = backup.get("session_state", {}).get("backup_history", []) if reason: reason = reason[-1].get("reason", "unknown") else: reason = "unknown" print(f"šŸ—‚ļø {backup_id}") print(f" šŸ“… {timestamp}") print(f" šŸ“ {reason}") print() def show_session_status(): """Show current session status""" session_manager = SessionStateManager() context_monitor = ContextMonitor() summary = session_manager.get_session_summary() context_summary = context_monitor.get_session_summary() print("Session Status:") print("===============") print(f"Session ID: {summary.get('session_id', 'unknown')}") print(f"Duration: {summary.get('session_stats', {}).get('duration_minutes', 0)} minutes") print(f"Context Usage: {context_summary.get('context_usage_ratio', 0):.1%}") print(f"Tool Calls: {summary.get('session_stats', {}).get('total_tool_calls', 0)}") print(f"Files Modified: {len(summary.get('modified_files', []))}") print(f"Commands Executed: {summary.get('session_stats', {}).get('total_commands', 0)}") print(f"Backups Created: {len(summary.get('backup_history', []))}") print() if summary.get('modified_files'): print("Modified Files:") for file_path in summary['modified_files']: print(f" - {file_path}") print() if context_summary.get('should_backup'): print("āš ļø Backup recommended (high context usage)") else: print("āœ… No backup needed currently") def show_patterns(): """Show learned patterns""" shadow_learner = ShadowLearner() print("Learned Patterns:") print("=================") # Command patterns command_patterns = shadow_learner.db.command_patterns if command_patterns: print("\nšŸ–„ļø Command Patterns:") for pattern_id, pattern in list(command_patterns.items())[:10]: # Show top 10 cmd = pattern.trigger.get("command", "unknown") confidence = pattern.confidence evidence = pattern.evidence_count success_rate = pattern.success_rate print(f" {cmd}") print(f" Confidence: {confidence:.1%}") print(f" Evidence: {evidence} samples") print(f" Success Rate: {success_rate:.1%}") # Context patterns context_patterns = shadow_learner.db.context_patterns if context_patterns: print("\nšŸ” Context Patterns:") for pattern_id, pattern in list(context_patterns.items())[:5]: # Show top 5 error_type = pattern.trigger.get("error_type", "unknown") confidence = pattern.confidence evidence = pattern.evidence_count print(f" {error_type}") print(f" Confidence: {confidence:.1%}") print(f" Evidence: {evidence} samples") if not command_patterns and not context_patterns: print("No patterns learned yet. Use Claude Code to start building the knowledge base!") def clear_patterns(): """Clear learned patterns""" response = input("Are you sure you want to clear all learned patterns? (y/N): ") if response.lower() == 'y': shadow_learner = ShadowLearner() shadow_learner.db = shadow_learner._load_database() # Reset to empty shadow_learner.save_database() print("āœ… Patterns cleared successfully") else: print("Operation cancelled") def export_data(): """Export all hook data""" export_dir = Path("claude_hooks_export") export_dir.mkdir(exist_ok=True) # Export session state session_manager = SessionStateManager() summary = session_manager.get_session_summary() with open(export_dir / "session_data.json", 'w') as f: json.dump(summary, f, indent=2) # Export patterns shadow_learner = ShadowLearner() with open(export_dir / "patterns.json", 'w') as f: json.dump(shadow_learner.db.to_dict(), f, indent=2) # Export logs logs_dir = Path(".claude_hooks/logs") if logs_dir.exists(): import shutil shutil.copytree(logs_dir, export_dir / "logs", dirs_exist_ok=True) print(f"āœ… Data exported to {export_dir}") def main(): """Main CLI entry point""" parser = argparse.ArgumentParser(description="Claude Code Hooks CLI") subparsers = parser.add_subparsers(dest="command", help="Available commands") # List backups subparsers.add_parser("list-backups", help="List available backups") # Show session status subparsers.add_parser("status", help="Show current session status") # Show patterns subparsers.add_parser("patterns", help="Show learned patterns") # Clear patterns subparsers.add_parser("clear-patterns", help="Clear all learned patterns") # Export data subparsers.add_parser("export", help="Export all hook data") args = parser.parse_args() if not args.command: parser.print_help() return try: if args.command == "list-backups": list_backups() elif args.command == "status": show_session_status() elif args.command == "patterns": show_patterns() elif args.command == "clear-patterns": clear_patterns() elif args.command == "export": export_data() else: print(f"Unknown command: {args.command}") parser.print_help() except Exception as e: print(f"Error: {e}", file=sys.stderr) sys.exit(1) if __name__ == "__main__": main()