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
138
scripts/install.sh
Executable file
138
scripts/install.sh
Executable file
|
|
@ -0,0 +1,138 @@
|
|||
#!/bin/bash
|
||||
# Claude Hooks Installation Script
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
CLAUDE_HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
CLAUDE_CONFIG_DIR="$HOME/.config/claude"
|
||||
HOOKS_CONFIG_FILE="$CLAUDE_CONFIG_DIR/hooks.json"
|
||||
|
||||
echo -e "${BLUE}Claude Code Hooks Installation${NC}"
|
||||
echo "=================================="
|
||||
|
||||
# Check Python version
|
||||
echo -n "Checking Python version... "
|
||||
if ! python3 --version >/dev/null 2>&1; then
|
||||
echo -e "${RED}FAILED${NC}"
|
||||
echo "Python 3 is required but not found. Please install Python 3.8 or later."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PYTHON_VERSION=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
|
||||
echo -e "${GREEN}Python $PYTHON_VERSION found${NC}"
|
||||
|
||||
# Check if Python version is 3.8+
|
||||
if python3 -c "import sys; exit(0 if sys.version_info >= (3, 8) else 1)"; then
|
||||
echo -e "${GREEN}✓ Python version is compatible${NC}"
|
||||
else
|
||||
echo -e "${RED}✗ Python 3.8+ required, found $PYTHON_VERSION${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install Python dependencies
|
||||
echo -n "Installing Python dependencies... "
|
||||
if pip3 install -r "$CLAUDE_HOOKS_DIR/requirements.txt" >/dev/null 2>&1; then
|
||||
echo -e "${GREEN}SUCCESS${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}WARNING${NC}"
|
||||
echo "Some dependencies may not have installed. Continuing..."
|
||||
fi
|
||||
|
||||
# Create Claude config directory
|
||||
echo -n "Creating Claude config directory... "
|
||||
mkdir -p "$CLAUDE_CONFIG_DIR"
|
||||
echo -e "${GREEN}SUCCESS${NC}"
|
||||
|
||||
# Generate hooks configuration
|
||||
echo -n "Generating hooks configuration... "
|
||||
sed "s|{{INSTALL_PATH}}|$CLAUDE_HOOKS_DIR|g" "$CLAUDE_HOOKS_DIR/config/hooks.json.template" > "$HOOKS_CONFIG_FILE"
|
||||
echo -e "${GREEN}SUCCESS${NC}"
|
||||
|
||||
# Make scripts executable
|
||||
echo -n "Setting script permissions... "
|
||||
chmod +x "$CLAUDE_HOOKS_DIR/hooks/"*.py
|
||||
chmod +x "$CLAUDE_HOOKS_DIR/scripts/"*.sh
|
||||
echo -e "${GREEN}SUCCESS${NC}"
|
||||
|
||||
# Create runtime directories
|
||||
echo -n "Creating runtime directories... "
|
||||
mkdir -p "$CLAUDE_HOOKS_DIR/.claude_hooks/"{backups,logs,patterns}
|
||||
echo -e "${GREEN}SUCCESS${NC}"
|
||||
|
||||
# Test hook scripts
|
||||
echo -n "Testing hook scripts... "
|
||||
if python3 "$CLAUDE_HOOKS_DIR/hooks/context_monitor.py" <<< '{"prompt": "test"}' >/dev/null 2>&1; then
|
||||
echo -e "${GREEN}SUCCESS${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}WARNING${NC}"
|
||||
echo "Hook scripts may have issues. Check logs for details."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}Installation Complete!${NC}"
|
||||
echo ""
|
||||
echo "📁 Installation directory: $CLAUDE_HOOKS_DIR"
|
||||
echo "⚙️ Configuration file: $HOOKS_CONFIG_FILE"
|
||||
echo ""
|
||||
echo -e "${BLUE}Next Steps:${NC}"
|
||||
echo "1. Add the hooks configuration to your Claude Code settings"
|
||||
echo "2. Restart Claude Code to load the hooks"
|
||||
echo "3. Test with: ./scripts/test.sh"
|
||||
echo ""
|
||||
echo -e "${BLUE}Configuration to add to Claude Code:${NC}"
|
||||
echo "Copy the contents of: $HOOKS_CONFIG_FILE"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Note:${NC} The hooks will start learning from your usage patterns automatically."
|
||||
|
||||
# Offer to add to Claude settings automatically if possible
|
||||
if [ -f "$HOME/.config/claude/settings.json" ]; then
|
||||
echo ""
|
||||
read -p "Would you like to automatically add hooks to your Claude settings? (y/n): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo -n "Updating Claude settings... "
|
||||
|
||||
# Backup existing settings
|
||||
cp "$HOME/.config/claude/settings.json" "$HOME/.config/claude/settings.json.backup"
|
||||
|
||||
# Add hooks configuration
|
||||
python3 << EOF
|
||||
import json
|
||||
|
||||
# Read existing settings
|
||||
try:
|
||||
with open('$HOME/.config/claude/settings.json', 'r') as f:
|
||||
settings = json.load(f)
|
||||
except:
|
||||
settings = {}
|
||||
|
||||
# Read hooks config
|
||||
with open('$HOOKS_CONFIG_FILE', 'r') as f:
|
||||
hooks_config = json.load(f)
|
||||
|
||||
# Merge hooks into settings
|
||||
settings.update(hooks_config)
|
||||
|
||||
# Write back
|
||||
with open('$HOME/.config/claude/settings.json', 'w') as f:
|
||||
json.dump(settings, f, indent=2)
|
||||
|
||||
print("Settings updated successfully")
|
||||
EOF
|
||||
|
||||
echo -e "${GREEN}SUCCESS${NC}"
|
||||
echo "🎉 Hooks have been automatically configured!"
|
||||
echo " Restart Claude Code to activate them."
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}Installation completed successfully!${NC}"
|
||||
169
scripts/test.sh
Executable file
169
scripts/test.sh
Executable file
|
|
@ -0,0 +1,169 @@
|
|||
#!/bin/bash
|
||||
# Claude Hooks Test Script
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
CLAUDE_HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
|
||||
echo -e "${BLUE}Claude Code Hooks Test Suite${NC}"
|
||||
echo "============================="
|
||||
|
||||
# Test 1: Context Monitor
|
||||
echo -n "Testing context monitor... "
|
||||
if python3 "$CLAUDE_HOOKS_DIR/hooks/context_monitor.py" <<< '{"prompt": "test prompt"}' >/dev/null 2>&1; then
|
||||
echo -e "${GREEN}PASS${NC}"
|
||||
else
|
||||
echo -e "${RED}FAIL${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 2: Command Validator - Safe command
|
||||
echo -n "Testing command validator (safe command)... "
|
||||
if python3 "$CLAUDE_HOOKS_DIR/hooks/command_validator.py" <<< '{"tool": "Bash", "parameters": {"command": "ls -la"}}' >/dev/null 2>&1; then
|
||||
echo -e "${GREEN}PASS${NC}"
|
||||
else
|
||||
echo -e "${RED}FAIL${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 3: Command Validator - Dangerous command
|
||||
echo -n "Testing command validator (dangerous command)... "
|
||||
OUTPUT=$(python3 "$CLAUDE_HOOKS_DIR/hooks/command_validator.py" <<< '{"tool": "Bash", "parameters": {"command": "rm -rf /"}}' 2>&1)
|
||||
EXIT_CODE=$?
|
||||
if echo "$OUTPUT" | grep -q '"allow": false' && [ $EXIT_CODE -eq 1 ]; then
|
||||
echo -e "${GREEN}PASS${NC}"
|
||||
else
|
||||
echo -e "${RED}FAIL${NC}"
|
||||
echo "Expected dangerous command to be blocked with exit code 1"
|
||||
echo "Got exit code: $EXIT_CODE"
|
||||
echo "Output: $OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 4: Session Logger
|
||||
echo -n "Testing session logger... "
|
||||
if python3 "$CLAUDE_HOOKS_DIR/hooks/session_logger.py" <<< '{"tool": "Read", "parameters": {"file_path": "test.txt"}, "success": true}' >/dev/null 2>&1; then
|
||||
echo -e "${GREEN}PASS${NC}"
|
||||
else
|
||||
echo -e "${RED}FAIL${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 5: Session Finalizer
|
||||
echo -n "Testing session finalizer... "
|
||||
if python3 "$CLAUDE_HOOKS_DIR/hooks/session_finalizer.py" <<< '{}' >/dev/null 2>&1; then
|
||||
echo -e "${GREEN}PASS${NC}"
|
||||
else
|
||||
echo -e "${RED}FAIL${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 6: Shadow Learner
|
||||
echo -n "Testing shadow learner... "
|
||||
python3 << 'EOF'
|
||||
import sys
|
||||
sys.path.insert(0, 'lib')
|
||||
from shadow_learner import ShadowLearner
|
||||
from models import ToolExecution
|
||||
from datetime import datetime
|
||||
|
||||
learner = ShadowLearner()
|
||||
execution = ToolExecution(
|
||||
timestamp=datetime.now(),
|
||||
tool="Bash",
|
||||
parameters={"command": "test command"},
|
||||
success=True
|
||||
)
|
||||
learner.learn_from_execution(execution)
|
||||
prediction = learner.predict_command_outcome("test command")
|
||||
print("Shadow learner test completed")
|
||||
EOF
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "${GREEN}PASS${NC}"
|
||||
else
|
||||
echo -e "${RED}FAIL${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 7: Context Monitor functionality
|
||||
echo -n "Testing context monitor functionality... "
|
||||
python3 << 'EOF'
|
||||
import sys
|
||||
sys.path.insert(0, 'lib')
|
||||
from context_monitor import ContextMonitor
|
||||
|
||||
monitor = ContextMonitor()
|
||||
monitor.update_from_prompt({"prompt": "test prompt"})
|
||||
usage = monitor.get_context_usage_ratio()
|
||||
assert 0 <= usage <= 1, f"Invalid usage ratio: {usage}"
|
||||
print("Context monitor functionality test completed")
|
||||
EOF
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "${GREEN}PASS${NC}"
|
||||
else
|
||||
echo -e "${RED}FAIL${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 8: File permissions
|
||||
echo -n "Testing file permissions... "
|
||||
if [ -x "$CLAUDE_HOOKS_DIR/hooks/context_monitor.py" ] && \
|
||||
[ -x "$CLAUDE_HOOKS_DIR/hooks/command_validator.py" ] && \
|
||||
[ -x "$CLAUDE_HOOKS_DIR/hooks/session_logger.py" ] && \
|
||||
[ -x "$CLAUDE_HOOKS_DIR/hooks/session_finalizer.py" ]; then
|
||||
echo -e "${GREEN}PASS${NC}"
|
||||
else
|
||||
echo -e "${RED}FAIL${NC}"
|
||||
echo "Hook scripts are not executable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 9: Configuration files
|
||||
echo -n "Testing configuration files... "
|
||||
if [ -f "$CLAUDE_HOOKS_DIR/config/hooks.json.template" ] && \
|
||||
[ -f "$CLAUDE_HOOKS_DIR/config/settings.json" ]; then
|
||||
echo -e "${GREEN}PASS${NC}"
|
||||
else
|
||||
echo -e "${RED}FAIL${NC}"
|
||||
echo "Configuration files missing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 10: Runtime directories
|
||||
echo -n "Testing runtime directories... "
|
||||
if [ -d "$CLAUDE_HOOKS_DIR/.claude_hooks" ] && \
|
||||
[ -d "$CLAUDE_HOOKS_DIR/.claude_hooks/backups" ] && \
|
||||
[ -d "$CLAUDE_HOOKS_DIR/.claude_hooks/logs" ] && \
|
||||
[ -d "$CLAUDE_HOOKS_DIR/.claude_hooks/patterns" ]; then
|
||||
echo -e "${GREEN}PASS${NC}"
|
||||
else
|
||||
echo -e "${RED}FAIL${NC}"
|
||||
echo "Runtime directories missing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}All tests passed! 🎉${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}Hook Status:${NC}"
|
||||
echo "✓ Context monitoring ready"
|
||||
echo "✓ Command validation ready"
|
||||
echo "✓ Session logging ready"
|
||||
echo "✓ Session finalization ready"
|
||||
echo "✓ Shadow learner ready"
|
||||
echo ""
|
||||
echo -e "${BLUE}Next Steps:${NC}"
|
||||
echo "1. Configure Claude Code to use the hooks"
|
||||
echo "2. Start using Claude - the hooks will activate automatically"
|
||||
echo "3. Check .claude_hooks/ directory for logs and patterns"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Note:${NC} The shadow learner will start empty and learn from your usage patterns."
|
||||
112
scripts/uninstall.sh
Executable file
112
scripts/uninstall.sh
Executable file
|
|
@ -0,0 +1,112 @@
|
|||
#!/bin/bash
|
||||
# Claude Hooks Uninstallation Script
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
CLAUDE_CONFIG_DIR="$HOME/.config/claude"
|
||||
HOOKS_CONFIG_FILE="$CLAUDE_CONFIG_DIR/hooks.json"
|
||||
|
||||
echo -e "${BLUE}Claude Code Hooks Uninstallation${NC}"
|
||||
echo "===================================="
|
||||
|
||||
# Warn user about data loss
|
||||
echo -e "${YELLOW}WARNING:${NC} This will remove:"
|
||||
echo "- Hook configuration from Claude Code"
|
||||
echo "- All learned patterns and session data"
|
||||
echo "- Backup files (if in project directory)"
|
||||
echo ""
|
||||
read -p "Are you sure you want to continue? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Uninstallation cancelled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Remove hooks from Claude settings
|
||||
if [ -f "$HOME/.config/claude/settings.json" ]; then
|
||||
echo -n "Removing hooks from Claude settings... "
|
||||
|
||||
# Backup settings
|
||||
cp "$HOME/.config/claude/settings.json" "$HOME/.config/claude/settings.json.backup"
|
||||
|
||||
# Remove hooks configuration
|
||||
python3 << 'EOF'
|
||||
import json
|
||||
import sys
|
||||
|
||||
try:
|
||||
with open('/home/usr/.config/claude/settings.json', 'r') as f:
|
||||
settings = json.load(f)
|
||||
|
||||
# Remove hooks section
|
||||
if 'hooks' in settings:
|
||||
del settings['hooks']
|
||||
|
||||
with open('/home/usr/.config/claude/settings.json', 'w') as f:
|
||||
json.dump(settings, f, indent=2)
|
||||
|
||||
print("SUCCESS")
|
||||
else:
|
||||
print("NO HOOKS FOUND")
|
||||
|
||||
except Exception as e:
|
||||
print(f"ERROR: {e}")
|
||||
sys.exit(1)
|
||||
EOF
|
||||
|
||||
echo -e "${GREEN}Hooks removed from Claude settings${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}No Claude settings file found${NC}"
|
||||
fi
|
||||
|
||||
# Remove hooks configuration file
|
||||
if [ -f "$HOOKS_CONFIG_FILE" ]; then
|
||||
echo -n "Removing hooks configuration file... "
|
||||
rm -f "$HOOKS_CONFIG_FILE"
|
||||
echo -e "${GREEN}SUCCESS${NC}"
|
||||
fi
|
||||
|
||||
# Ask about removing data
|
||||
echo ""
|
||||
read -p "Remove learned patterns and session data? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo -n "Removing hook data... "
|
||||
rm -rf ".claude_hooks"
|
||||
rm -f "LAST_SESSION.md" "ACTIVE_TODOS.md" "RECOVERY_GUIDE.md"
|
||||
echo -e "${GREEN}SUCCESS${NC}"
|
||||
fi
|
||||
|
||||
# Ask about removing project files
|
||||
echo ""
|
||||
read -p "Remove project files (hooks, scripts, etc.)? This cannot be undone! (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
CLAUDE_HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
echo -n "Removing project files... "
|
||||
cd ..
|
||||
rm -rf "$CLAUDE_HOOKS_DIR"
|
||||
echo -e "${GREEN}SUCCESS${NC}"
|
||||
echo ""
|
||||
echo -e "${GREEN}Complete uninstallation finished!${NC}"
|
||||
echo "All files have been removed."
|
||||
else
|
||||
echo ""
|
||||
echo -e "${GREEN}Partial uninstallation finished!${NC}"
|
||||
echo "Hooks disabled, but project files remain."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}Post-uninstallation:${NC}"
|
||||
echo "1. Restart Claude Code to ensure hooks are disabled"
|
||||
echo "2. Check that no hook-related errors appear"
|
||||
echo "3. Your backup files (if any) remain in git history"
|
||||
echo ""
|
||||
echo -e "${GREEN}Claude Code Hooks successfully removed.${NC}"
|
||||
Loading…
Add table
Add a link
Reference in a new issue