Skip to content
  • 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 Complete Guide

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:

  1. Black formatting applied
  2. isort import organization
  3. flake8 static analysis
  4. mypy type checking
  5. 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.