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>
This commit is contained in:
commit
162ca67098
34 changed files with 5904 additions and 0 deletions
184
hooks/command_validator.py
Executable file
184
hooks/command_validator.py
Executable file
|
|
@ -0,0 +1,184 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Command Validator Hook - PreToolUse[Bash] hook
|
||||
Validates bash commands using shadow learner insights
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import re
|
||||
import os
|
||||
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 models import ValidationResult
|
||||
|
||||
|
||||
class CommandValidator:
|
||||
"""Validates bash commands for safety and success probability"""
|
||||
|
||||
def __init__(self):
|
||||
self.shadow_learner = ShadowLearner()
|
||||
|
||||
# Dangerous command patterns
|
||||
self.dangerous_patterns = [
|
||||
r'rm\s+-rf\s+/', # Delete root
|
||||
r'mkfs\.', # Format filesystem
|
||||
r'dd\s+if=.*of=/dev/', # Overwrite devices
|
||||
r':(){ :|:& };:', # Fork bomb
|
||||
r'curl.*\|\s*bash', # Pipe to shell
|
||||
r'wget.*\|\s*sh', # Pipe to shell
|
||||
r';.*rm\s+-rf', # Command chaining with rm
|
||||
r'&&.*rm\s+-rf', # Command chaining with rm
|
||||
]
|
||||
|
||||
self.suspicious_patterns = [
|
||||
r'sudo\s+rm', # Sudo with rm
|
||||
r'chmod\s+777', # Overly permissive
|
||||
r'/etc/passwd', # System files
|
||||
r'/etc/shadow', # System files
|
||||
r'nc.*-l.*-p', # Netcat listener
|
||||
]
|
||||
|
||||
def validate_command_safety(self, command: str) -> ValidationResult:
|
||||
"""Comprehensive command safety validation"""
|
||||
|
||||
# Normalize command for analysis
|
||||
normalized = command.lower().strip()
|
||||
|
||||
# Check for dangerous patterns
|
||||
for pattern in self.dangerous_patterns:
|
||||
if re.search(pattern, normalized):
|
||||
return ValidationResult(
|
||||
allowed=False,
|
||||
reason=f"Dangerous command pattern detected",
|
||||
severity="critical"
|
||||
)
|
||||
|
||||
# Check for suspicious patterns
|
||||
for pattern in self.suspicious_patterns:
|
||||
if re.search(pattern, normalized):
|
||||
return ValidationResult(
|
||||
allowed=True, # Allow but warn
|
||||
reason=f"Suspicious command pattern detected",
|
||||
severity="warning"
|
||||
)
|
||||
|
||||
return ValidationResult(allowed=True, reason="Command appears safe")
|
||||
|
||||
def validate_with_shadow_learner(self, command: str) -> ValidationResult:
|
||||
"""Use shadow learner to predict command success"""
|
||||
|
||||
try:
|
||||
prediction = self.shadow_learner.predict_command_outcome(command)
|
||||
|
||||
if not prediction["likely_success"] and prediction["confidence"] > 0.8:
|
||||
suggestions = prediction.get("suggestions", [])
|
||||
suggestion_text = f" Try: {suggestions[0]}" if suggestions else ""
|
||||
|
||||
return ValidationResult(
|
||||
allowed=False,
|
||||
reason=f"Command likely to fail (confidence: {prediction['confidence']:.0%}){suggestion_text}",
|
||||
severity="medium",
|
||||
suggestions=suggestions
|
||||
)
|
||||
elif prediction["warnings"]:
|
||||
return ValidationResult(
|
||||
allowed=True,
|
||||
reason=prediction["warnings"][0],
|
||||
severity="warning",
|
||||
suggestions=prediction.get("suggestions", [])
|
||||
)
|
||||
|
||||
except Exception:
|
||||
# If shadow learner fails, don't block
|
||||
pass
|
||||
|
||||
return ValidationResult(allowed=True, reason="No issues detected")
|
||||
|
||||
def validate_command(self, command: str) -> ValidationResult:
|
||||
"""Main validation entry point"""
|
||||
|
||||
# Safety validation (blocking)
|
||||
safety_result = self.validate_command_safety(command)
|
||||
if not safety_result.allowed:
|
||||
return safety_result
|
||||
|
||||
# Shadow learner validation (predictive)
|
||||
prediction_result = self.validate_with_shadow_learner(command)
|
||||
|
||||
# Return most significant result
|
||||
if prediction_result.severity in ["high", "critical"]:
|
||||
return prediction_result
|
||||
elif safety_result.severity in ["warning", "medium"]:
|
||||
return safety_result
|
||||
else:
|
||||
return prediction_result
|
||||
|
||||
|
||||
def main():
|
||||
"""Main hook entry point"""
|
||||
try:
|
||||
# Read input from Claude Code
|
||||
input_data = json.loads(sys.stdin.read())
|
||||
|
||||
# Extract command from parameters
|
||||
tool = input_data.get("tool", "")
|
||||
parameters = input_data.get("parameters", {})
|
||||
command = parameters.get("command", "")
|
||||
|
||||
if tool != "Bash" or not command:
|
||||
# Not a bash command, allow it
|
||||
response = {"allow": True, "message": "Not a bash command"}
|
||||
print(json.dumps(response))
|
||||
sys.exit(0)
|
||||
|
||||
# Validate command
|
||||
validator = CommandValidator()
|
||||
result = validator.validate_command(command)
|
||||
|
||||
if not result.allowed:
|
||||
# Block the command
|
||||
response = {
|
||||
"allow": False,
|
||||
"message": f"⛔ Command blocked: {result.reason}"
|
||||
}
|
||||
print(json.dumps(response))
|
||||
sys.exit(1) # Exit code 1 = block operation
|
||||
|
||||
elif result.severity in ["warning", "medium"]:
|
||||
# Allow with warning
|
||||
warning_emoji = "⚠️" if result.severity == "warning" else "🚨"
|
||||
message = f"{warning_emoji} {result.reason}"
|
||||
|
||||
if result.suggestions:
|
||||
message += f"\n💡 Suggestion: {result.suggestions[0]}"
|
||||
|
||||
response = {
|
||||
"allow": True,
|
||||
"message": message
|
||||
}
|
||||
print(json.dumps(response))
|
||||
sys.exit(0)
|
||||
|
||||
else:
|
||||
# Allow without warning
|
||||
response = {"allow": True, "message": "Command validated"}
|
||||
print(json.dumps(response))
|
||||
sys.exit(0)
|
||||
|
||||
except Exception as e:
|
||||
# Never block on validation errors - always allow operation
|
||||
response = {
|
||||
"allow": True,
|
||||
"message": f"Validation error: {str(e)}"
|
||||
}
|
||||
print(json.dumps(response))
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue