- Claude-Code-Hooks
- Hands-On
- Implementation-Guide
- Development-Automation
- Practical-Code-Examples
- Troubleshooting
- hands-on-implementation categories:
- AI-Development-Automation
- Tools-Development-Efficiency author: Claude Code status: deep-dive experience_level: practical
Claude Code Hooks Hands-On Implementation: Learning Development Automation Through Practice [Latest July 2025 Practical Edition]¶
Introduction¶
This article serves as the practical edition of Claude Code Hooks Revolution: A New Dimension in Development Workflow Automation [Latest July 2025], enabling you to completely master the introduction and implementation of Claude Code Hooks through actual code examples and hands-on experience.
From theory to implementation, we provide concrete code examples and setup procedures you can use immediately in your projects.
Key Points¶
Actual Code Implementation
Configuration files and script examples ready to copy and use
Error Handling
Comprehensive coverage of actual errors and their solutions
Project-Specific Configurations
Optimized configuration examples by framework and language
Gradual Introduction
Risk-minimized introduction strategy and rollback methods
🚀 Hands-On 1: Basic Hooks Configuration¶
Environment Preparation¶
First, create the Claude Code Hooks configuration directory.
# Create Claude Code configuration directory
mkdir -p ~/.claude
# Initialize configuration file
touch ~/.claude/settings.json
Recommended Configuration Method
Official Recommendation: Using the /hooks interactive UI command in Claude Code is recommended over direct editing of configuration files.
# Execute the following command after starting Claude Code
/hooks
This method minimizes syntax error risks and allows safe configuration management via GUI. However, this article explains the configuration file structure in detail for learning purposes.
Your First Hook: Simple File Change Notification¶
{
"hooks": {
"PostToolUse": [
{
"name": "File Change Notification",
"condition": {
"tool_name": "edit_file"
},
"hooks": [
{
"type": "command",
"command": "echo '📝 File modified: $CLAUDE_FILE_PATHS'"
}
]
}
]
}
}
Configuration Verification and Testing¶
# Create a test file with Claude Code
claude-code "Create a simple test.txt file with hello world"
# Example output:
# 📝 File modified: /path/to/test.txt
Debugging Tips
If hooks don't work, running in claude-code --debug mode will show detailed logs.
🐍 Hands-On 2: Complete Python Development Environment Automation¶
Project Structure¶
my-python-project/
├── src/
│ ├── main.py
│ └── utils.py
├── tests/
│ └── test_main.py
├── requirements.txt
├── setup.cfg
└── pyproject.toml
Gradual Hook Configuration¶
Step 1: Basic Formatting¶
{
"hooks": {
"PostToolUse": [
{
"name": "Python Basic Format",
"condition": {
"tool_name": "edit_file",
"files_changed": ["*.py"]
},
"hooks": [
{
"type": "command",
"command": "echo \"🐍 Formatting Python file: $CLAUDE_FILE_PATHS\" && black $CLAUDE_FILE_PATHS && if [ $? -eq 0 ]; then echo \"✅ Black formatting completed\"; else echo \"❌ Black formatting failed\"; exit 1; fi"
}
]
}
]
}
}
Step 2: Import Organization and Linting¶
{
"hooks": {
"PostToolUse": [
{
"name": "Python Full Quality Check",
"condition": {
"tool_name": "edit_file",
"files_changed": ["*.py"]
},
"hooks": [
{
"type": "command",
"command": "echo \"🔍 Python quality check for: $CLAUDE_FILE_PATHS\" && echo \" ↳ Sorting imports...\" && isort $CLAUDE_FILE_PATHS --check-only --diff; if [ $? -ne 0 ]; then echo \" ↳ Applying import sort...\" && isort $CLAUDE_FILE_PATHS; fi && echo \" ↳ Running flake8...\" && flake8 $CLAUDE_FILE_PATHS --max-line-length=88 --extend-ignore=E203,W503 && echo \" ↳ Type checking with mypy...\" && mypy $CLAUDE_FILE_PATHS --ignore-missing-imports && echo \"✅ Python quality check completed\""
}
]
}
]
}
}
Step 3: Automatic Test Execution¶
[[hooks]]
name = "Python Test Runner"
event = "PostToolUse"
run_in_background = true
[hooks.matcher]
tool_name = "edit_file"
file_paths = ["src/**/*.py", "tests/**/*.py"]
command = """
echo "🧪 Running Python tests..."
# Identify related test files
test_files=$(find tests/ -name "*test*.py" 2>/dev/null)
if [ -n "$test_files" ]; then
# Run only tests related to changed files
pytest -xvs $test_files --tb=short
# Generate coverage report
if command -v coverage >/dev/null 2>&1; then
echo "📊 Generating coverage report..."
coverage run -m pytest $test_files
coverage report --show-missing
fi
else
echo "ℹ️ No test files found, skipping test execution"
fi
"""
Practical Usage Example¶
# Create src/main.py
def calculate_fibonacci(n: int) -> int:
"""Calculate the nth Fibonacci number"""
if n <= 1:
return n
return calculate_fibonacci(n-1) + calculate_fibonacci(n-2)
def main():
result = calculate_fibonacci(10)
print(f"Fibonacci(10) = {result}")
if __name__ == "__main__":
main()
When you create this file with Claude Code, the following will execute automatically:
- Black formatting applied
- isort import organization
- flake8 static analysis
- mypy type checking
- pytest execution (background)
⚛️ Hands-On 3: React/TypeScript Development Environment¶
Configuration for Next.js Projects¶
[[hooks]]
name = "React TypeScript Quality"
event = "PostToolUse"
[hooks.matcher]
tool_name = "edit_file"
file_paths = ["*.ts", "*.tsx", "*.js", "*.jsx"]
command = """
echo "⚛️ React/TypeScript quality check: $CLAUDE_FILE_PATHS"
# Prettier formatting
echo " ↳ Formatting with Prettier..."
prettier --write $CLAUDE_FILE_PATHS
# ESLint check
echo " ↳ Linting with ESLint..."
eslint --fix $CLAUDE_FILE_PATHS
# TypeScript type checking
echo " ↳ Type checking..."
tsc --noEmit --skipLibCheck
echo "✅ React/TypeScript check completed"
"""
Component-Specific Hook¶
[[hooks]]
name = "React Component Validation"
event = "PostToolUse"
[hooks.matcher]
tool_name = "edit_file"
file_paths = ["src/components/**/*.tsx", "src/pages/**/*.tsx"]
command = """
echo "🧩 Validating React component: $CLAUDE_FILE_PATHS"
# React-specific rule checks
echo " ↳ React hooks validation..."
eslint $CLAUDE_FILE_PATHS --rule 'react-hooks/rules-of-hooks: error'
# Run component tests
component_name=$(basename $CLAUDE_FILE_PATHS .tsx)
test_file="src/components/__tests__/${component_name}.test.tsx"
if [ -f "$test_file" ]; then
echo " ↳ Running component tests..."
npm test -- --testPathPattern="$test_file" --watchAll=false
fi
# Storybook build test (if stories file exists)
stories_file="src/components/${component_name}.stories.tsx"
if [ -f "$stories_file" ]; then
echo " ↳ Validating Storybook stories..."
npm run build-storybook --quiet
fi
echo "✅ React component validation completed"
"""
🔒 Hands-On 4: Security Enhancement Configuration¶
Git Secrets Integration¶
[[hooks]]
name = "Security Secret Scan"
event = "PreToolUse"
[hooks.matcher]
tool_name = "edit_file"
command = """
echo "🔒 Security scan for: $CLAUDE_FILE_PATHS"
# Scan with git-secrets
if command -v git-secrets >/dev/null 2>&1; then
echo " ↳ Scanning for secrets..."
git secrets --scan $CLAUDE_FILE_PATHS
if [ $? -ne 0 ]; then
echo "🚨 Secret detected! Operation blocked."
exit 1
fi
fi
# Additional pattern checks
echo " ↳ Additional pattern checks..."
for file in $CLAUDE_FILE_PATHS; do
# API key pattern check
if grep -qE "api[_-]?key\s*=\s*['\"][^'\"]{10,}['\"]" "$file"; then
echo "🚨 Potential API key found in $file"
exit 1
fi
# AWS credentials check
if grep -qE "AKIA[0-9A-Z]{16}" "$file"; then
echo "🚨 AWS Access Key found in $file"
exit 1
fi
done
echo "✅ Security scan passed"
"""
Production Environment Protection¶
[[hooks]]
name = "Production Environment Protection"
event = "PreToolUse"
[hooks.matcher]
tool_name = "edit_file"
file_paths = ["prod/**", "production/**", "*.prod.*", "deploy/**", "terraform/**"]
command = """
echo "🛡️ Production file modification detected!"
echo "Files: $CLAUDE_FILE_PATHS"
# Interactive confirmation
echo "⚠️ You are about to modify production-related files."
echo "Are you sure you want to continue? (Type 'yes' to confirm)"
read -r confirmation
if [ "$confirmation" != "yes" ]; then
echo "❌ Operation cancelled for safety"
exit 1
fi
# Additional safety checks
current_branch=$(git branch --show-current)
if [ "$current_branch" = "main" ] || [ "$current_branch" = "master" ]; then
echo "🚨 WARNING: You are on the main branch!"
echo "Consider creating a feature branch for production changes."
echo "Continue anyway? (Type 'CONFIRM' to proceed)"
read -r final_confirmation
if [ "$final_confirmation" != "CONFIRM" ]; then
echo "❌ Operation cancelled"
exit 1
fi
fi
echo "✅ Production modification approved"
"""
📊 Hands-On 5: Advanced Workflow Integration¶
GitHub Actions Integration¶
[[hooks]]
name = "GitHub Actions Integration"
event = "PostToolUse"
[hooks.matcher]
tool_name = "edit_file"
file_paths = [".github/workflows/**/*.yml", ".github/workflows/**/*.yaml"]
command = """
echo "🔄 GitHub Actions workflow validation: $CLAUDE_FILE_PATHS"
# YAML syntax check
echo " ↳ YAML syntax validation..."
for file in $CLAUDE_FILE_PATHS; do
if command -v yamllint >/dev/null 2>&1; then
yamllint "$file"
else
python -c "import yaml; yaml.safe_load(open('$file'))"
fi
done
# GitHub Actions-specific syntax check
echo " ↳ GitHub Actions syntax check..."
if command -v act >/dev/null 2>&1; then
act --list
fi
echo "✅ GitHub Actions validation completed"
"""
Docker Integration¶
[[hooks]]
name = "Docker Build Validation"
event = "PostToolUse"
[hooks.matcher]
tool_name = "edit_file"
file_paths = ["Dockerfile", "docker-compose.yml", "docker-compose.yaml"]
command = """
echo "🐳 Docker configuration validation: $CLAUDE_FILE_PATHS"
for file in $CLAUDE_FILE_PATHS; do
case "$file" in
*Dockerfile*)
echo " ↳ Validating Dockerfile..."
docker build --no-cache -t temp-validation -f "$file" .
docker rmi temp-validation
;;
*docker-compose*)
echo " ↳ Validating docker-compose..."
docker-compose -f "$file" config
;;
esac
done
echo "✅ Docker validation completed"
"""
🔧 Troubleshooting¶
Common Issues and Solutions¶
1. Hook Not Executing¶
# Run in debug mode
claude-code --debug "Edit a test file"
# Check configuration file syntax
# For JSON files, check with jq
# jq empty ~/.claude/settings.json
2. Environment Variables Not Recognized¶
# Explicitly pass environment variables
[[hooks]]
name = "Environment Variable Fix"
event = "PostToolUse"
[hooks.matcher]
tool_name = "edit_file"
command = """
export PATH="$PATH:/usr/local/bin"
export PYTHONPATH="$PYTHONPATH:$(pwd)/src"
your-command $CLAUDE_FILE_PATHS
"""
3. Performance Issues¶
# Run long-running tasks in background
[[hooks]]
name = "Performance Optimized"
event = "PostToolUse"
run_in_background = true # Add this
timeout = 30 # Set timeout
[hooks.matcher]
tool_name = "edit_file"
command = "long-running-task $CLAUDE_FILE_PATHS"
Debug Hook¶
[[hooks]]
name = "Debug Information"
event = "PostToolUse"
[hooks.matcher]
tool_name = "edit_file"
command = """
echo "🔍 Debug Information:"
echo " Working Directory: $(pwd)"
echo " User: $(whoami)"
echo " Files: $CLAUDE_FILE_PATHS"
echo " Environment: $(env | grep CLAUDE)"
echo " Git Branch: $(git branch --show-current 2>/dev/null || echo 'not a git repo')"
"""
🎯 Project-Specific Optimization Configurations¶
Django Project¶
[[hooks]]
name = "Django Development"
event = "PostToolUse"
[hooks.matcher]
tool_name = "edit_file"
file_paths = ["*.py"]
command = """
# Django-specific processing
if [ -f "manage.py" ]; then
echo "🐍 Django project detected"
# Check for migration creation
if echo $CLAUDE_FILE_PATHS | grep -q "models.py"; then
echo " ↳ Model changes detected, checking migrations..."
python manage.py makemigrations --dry-run --verbosity=0
if [ $? -ne 0 ]; then
echo " ↳ Creating migrations..."
python manage.py makemigrations
fi
fi
# Run Django application tests
echo " ↳ Running Django tests..."
python manage.py test --parallel --keepdb
fi
"""
Node.js/Express Project¶
[[hooks]]
name = "Node.js Express Development"
event = "PostToolUse"
[hooks.matcher]
tool_name = "edit_file"
file_paths = ["*.js", "*.ts"]
command = """
if [ -f "package.json" ]; then
echo "📦 Node.js project detected"
# Dependency check
if echo $CLAUDE_FILE_PATHS | grep -q "package.json"; then
echo " ↳ Package.json modified, checking dependencies..."
npm audit
npm outdated
fi
# ESLint & Prettier
echo " ↳ Code quality checks..."
npm run lint --if-present
npm run format --if-present
# Run tests
echo " ↳ Running tests..."
npm test --if-present
fi
"""
📈 Performance Optimization¶
Conditional Execution¶
[[hooks]]
name = "Conditional Execution"
event = "PostToolUse"
[hooks.matcher]
tool_name = "edit_file"
file_paths = ["*.py"]
command = """
# File size check
file_size=$(wc -c < $CLAUDE_FILE_PATHS)
if [ $file_size -gt 10000 ]; then
echo "⚠️ Large file detected (${file_size} bytes), skipping expensive checks"
exit 0
fi
# Normal processing
black $CLAUDE_FILE_PATHS
flake8 $CLAUDE_FILE_PATHS
"""
Parallel Execution¶
[[hooks]]
name = "Parallel Processing"
event = "PostToolUse"
[hooks.matcher]
tool_name = "edit_file"
file_paths = ["*.py"]
command = """
echo "🔄 Starting parallel quality checks..."
# Improve performance with parallel execution
(
echo " ↳ Black formatting..." && black $CLAUDE_FILE_PATHS
) &
(
echo " ↳ Import sorting..." && isort $CLAUDE_FILE_PATHS
) &
(
echo " ↳ Linting..." && flake8 $CLAUDE_FILE_PATHS
) &
# Wait for all background jobs to complete
wait
echo "✅ Parallel processing completed"
"""
🔄 Gradual Introduction Strategy¶
Phase 1: Monitoring Only¶
[[hooks]]
name = "Monitor Only - Phase 1"
event = "PostToolUse"
[hooks.matcher]
tool_name = "edit_file"
file_paths = ["*.py"]
command = """
echo "👀 MONITOR MODE: File modified - $CLAUDE_FILE_PATHS"
echo " ↳ Would run: black, flake8, pytest"
echo " ↳ This is monitor-only mode - no actions taken"
"""
Phase 2: Auto-Fix¶
[[hooks]]
name = "Auto Fix - Phase 2"
event = "PostToolUse"
[hooks.matcher]
tool_name = "edit_file"
file_paths = ["*.py"]
command = """
echo "🔧 AUTO-FIX MODE: $CLAUDE_FILE_PATHS"
black $CLAUDE_FILE_PATHS
isort $CLAUDE_FILE_PATHS
echo "✅ Automatic fixes applied"
"""
Phase 3: Full Automation¶
[[hooks]]
name = "Full Automation - Phase 3"
event = "PostToolUse"
[hooks.matcher]
tool_name = "edit_file"
file_paths = ["*.py"]
command = """
echo "🚀 FULL AUTOMATION: $CLAUDE_FILE_PATHS"
black $CLAUDE_FILE_PATHS
isort $CLAUDE_FILE_PATHS
flake8 $CLAUDE_FILE_PATHS
pytest --tb=short -x
echo "✅ Full automation pipeline completed"
"""
💡 Practical Tips¶
1. Split Configuration File Management¶
# Manage configurations by splitting them
mkdir -p ~/.claude/hooks
# Configuration management in JSON format (apologies, but file splitting is not currently supported in JSON format)
# The latest official specification requires all settings to be written in ~/.claude/settings.json
2. Project-Specific Configuration¶
# Conditional branching by project directory
[[hooks]]
name = "Project Specific"
event = "PostToolUse"
[hooks.matcher]
tool_name = "edit_file"
command = """
project_root=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
project_name=$(basename "$project_root")
case "$project_name" in
"my-backend-api")
echo "🔙 Backend API project detected"
# API specific hooks
;;
"my-frontend-app")
echo "🎨 Frontend app project detected"
# Frontend specific hooks
;;
*)
echo "📁 Generic project"
# Default hooks
;;
esac
"""
3. Emergency Disabling¶
# Temporarily disable Hooks
export CLAUDE_HOOKS_DISABLED=1
claude-code "Emergency edit without hooks"
# Or rename configuration file
mv ~/.claude/settings.json ~/.claude/settings.json.disabled
Summary¶
Through implementing Claude Code Hooks, you have acquired the following practical skills:
- Gradual Introduction: Safe introduction methods that minimize risk
- Language-Specific Optimization: Dedicated configurations for Python, JavaScript/TypeScript, Docker, etc.
- Security Enhancement: Implementation of production environment protection and secret detection
- Troubleshooting: Actual problems and their solutions
- Performance Optimization: Acceleration through parallel and conditional execution
Next Steps
After mastering the basics with this hands-on implementation, try tackling advanced features and GitHub Copilot Agent Mode integration introduced in Claude Code Hooks Revolution: A New Dimension in Development Workflow Automation [Latest July 2025].
Important Notes
Before production deployment, ensure sufficient testing in a development environment. Also, don't forget to unify settings across your team and maintain documentation.