✨ Features: - 🧠 Shadow learner that builds intelligence from command patterns - 🛡️ Smart command validation with safety checks - 💾 Automatic context monitoring and backup system - 🔄 Session continuity across Claude restarts 📚 Documentation: - Complete Diátaxis-organized documentation - Learning-oriented tutorial for getting started - Task-oriented how-to guides for specific problems - Information-oriented reference for quick lookup - Understanding-oriented explanations of architecture 🚀 Installation: - One-command installation script - Bootstrap prompt for installation via Claude - Cross-platform compatibility - Comprehensive testing suite 🎯 Ready for real-world use and community feedback! 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
202 lines
6.4 KiB
Python
202 lines
6.4 KiB
Python
#!/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() |