claude-hooks/hooks/session_logger.py
Ryan Malloy 162ca67098 Initial commit: Claude Code Hooks with Diátaxis documentation
 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>
2025-07-19 18:25:34 -06:00

124 lines
3.6 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Session Logger Hook - PostToolUse[*] hook
Logs all tool usage and feeds data to shadow learner
"""
import sys
import json
import os
from datetime import datetime
from pathlib import Path
# Add lib directory to path
sys.path.insert(0, str(Path(__file__).parent.parent / "lib"))
from shadow_learner import ShadowLearner
from session_state import SessionStateManager
from context_monitor import ContextMonitor
from models import ToolExecution
def main():
"""Main hook entry point"""
try:
# Read input from Claude Code
input_data = json.loads(sys.stdin.read())
# Extract tool execution data
tool = input_data.get("tool", "")
parameters = input_data.get("parameters", {})
success = input_data.get("success", True)
error = input_data.get("error", "")
execution_time = input_data.get("execution_time", 0.0)
# Create tool execution record
execution = ToolExecution(
timestamp=datetime.now(),
tool=tool,
parameters=parameters,
success=success,
error_message=error if error else None,
execution_time=execution_time,
context={}
)
# Initialize components
shadow_learner = ShadowLearner()
session_manager = SessionStateManager()
context_monitor = ContextMonitor()
# Feed execution to shadow learner
shadow_learner.learn_from_execution(execution)
# Update session state
session_manager.update_from_tool_use(input_data)
# Update context monitor
context_monitor.update_from_tool_use(input_data)
# Save learned patterns periodically
# (Only save every 10 executions to avoid too much disk I/O)
if context_monitor.tool_executions % 10 == 0:
shadow_learner.save_database()
# Log execution to file for debugging (optional)
log_execution(execution)
# Always allow - this is a post-execution hook
response = {
"allow": True,
"message": f"Logged {tool} execution"
}
print(json.dumps(response))
sys.exit(0)
except Exception as e:
# Post-execution hooks should never block
response = {
"allow": True,
"message": f"Logging error: {str(e)}"
}
print(json.dumps(response))
sys.exit(0)
def log_execution(execution: ToolExecution):
"""Log execution to file for debugging and analysis"""
try:
log_dir = Path(".claude_hooks/logs")
log_dir.mkdir(parents=True, exist_ok=True)
# Create daily log file
log_file = log_dir / f"executions_{datetime.now().strftime('%Y%m%d')}.jsonl"
# Append execution record
with open(log_file, 'a') as f:
f.write(json.dumps(execution.to_dict()) + "\n")
# Clean up old log files (keep last 7 days)
cleanup_old_logs(log_dir)
except Exception:
# Don't let logging errors break the hook
pass
def cleanup_old_logs(log_dir: Path):
"""Clean up log files older than 7 days"""
try:
import time
cutoff_time = time.time() - (7 * 24 * 3600) # 7 days ago
for log_file in log_dir.glob("executions_*.jsonl"):
if log_file.stat().st_mtime < cutoff_time:
log_file.unlink()
except Exception:
pass
if __name__ == "__main__":
main()