Claude Code Hooks: Automatización y Personalización de Workflows de Desarrollo

Claude Code Hooks: Automatización y Personalización de Workflows de Desarrollo

Con la evolución constante de las herramientas de desarrollo impulsadas por IA, Claude Code ha introducido una funcionalidad revolucionaria: Hooks. Esta característica permite a los desarrolladores personalizar y automatizar comportamientos específicos en el ciclo de vida de Claude Code, transformando sugerencias en código ejecutable que funciona de manera determinística.

Los hooks representan un salto cualitativo en la personalización de herramientas de IA para desarrollo, permitiendo que cada equipo y desarrollador adapte Claude Code a sus necesidades específicas y estándares de proyecto.

¿Qué son los Claude Code Hooks?

Los Claude Code Hooks son comandos de shell definidos por el usuario que se ejecutan automáticamente en varios puntos específicos del ciclo de vida de Claude Code. A diferencia de las instrucciones de prompting, los hooks garantizan que ciertas acciones siempre ocurran, proporcionando control determinístico sobre el comportamiento de la herramienta.

El Problema que Resuelven

Tradicionalmente, personalizar el comportamiento de herramientas de IA requería:

  • Instrucciones repetitivas en cada conversación
  • Dependencia del LLM para recordar y ejecutar acciones específicas
  • Inconsistencias en la aplicación de estándares de código
  • Procesos manuales para formateo, validación y logging

Los hooks eliminan estas limitaciones al codificar reglas como aplicaciones que se ejecutan automáticamente.

Casos de Uso Transformadores

1. Formateo Automático de Código

# Hook que formatea automáticamente archivos TypeScript
hook_command="if [[ \$file_path =~ \.ts$ ]]; then prettier --write \$file_path; fi"

2. Notificaciones Personalizadas

# Notificación por Slack cuando Claude solicita permisos
hook_command="curl -X POST \$SLACK_WEBHOOK -d '{\"text\":\"Claude Code necesita tu atención\"}'"

3. Logging y Compliance

# Registro de todos los comandos ejecutados para auditoría
hook_command="echo \$(date): \$command >> ~/.claude/audit.log"

4. Validación de Convenciones

# Verificar que los commits siguen el estándar del equipo
hook_command="./scripts/validate-commit-message.sh \$commit_message"

5. Permisos Personalizados

# Bloquear modificaciones a archivos de producción
hook_command="if [[ \$file_path =~ ^production/ ]]; then exit 2; fi"

Configuración Paso a Paso

Configuración Básica: Hook de Logging

Vamos a crear nuestro primer hook que registra todos los comandos bash ejecutados por Claude Code.

Paso 1: Abrir Configuración de Hooks

# En Claude Code, ejecutar el comando slash
/hooks

Selecciona el evento PreToolUse para interceptar comandos antes de su ejecución.

Paso 2: Añadir Matcher

Matcher: Bash

Esto hace que el hook solo se ejecute para comandos de shell.

Paso 3: Configurar el Hook

# Comando que registra la ejecución
echo "$(date): Command executed by Claude Code" >> ~/.claude/command_log.txt

Paso 4: Guardar Configuración

Selecciona User settings para aplicar el hook a todos los proyectos.

Configuración Avanzada: Formateo Automático

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "if [[ \"$file_path\" =~ \\.(js|ts|jsx|tsx)$ ]]; then prettier --write \"$file_path\"; fi"
          },
          {
            "type": "command", 
            "command": "if [[ \"$file_path\" =~ \\.go$ ]]; then gofmt -w \"$file_path\"; fi"
          },
          {
            "type": "command",
            "command": "if [[ \"$file_path\" =~ \\.py$ ]]; then black \"$file_path\"; fi"
          }
        ]
      }
    ]
  }
}

Tipos de Eventos de Hooks

1. PreToolUse

Se ejecuta antes de que Claude procese una herramienta.

Casos de uso:

  • Validación de permisos
  • Verificación de pre-condiciones
  • Bloqueo de operaciones peligrosas
# Ejemplo: Bloquear ediciones a archivos críticos
if [[ "$file_path" =~ (package\.json|\.env) ]]; then
    echo "Error: Archivo crítico protegido" >&2
    exit 2  # Bloquea la operación
fi

2. PostToolUse

Se ejecuta después de que una herramienta se complete exitosamente.

Casos de uso:

  • Formateo automático
  • Validación post-procesamiento
  • Notificaciones de cambios
# Ejemplo: Ejecutar tests después de cambios de código
if [[ "$file_path" =~ \.test\.(js|ts)$ ]]; then
    npm test "$file_path"
fi

3. Notification

Se ejecuta cuando Claude Code envía notificaciones.

Casos de uso:

  • Notificaciones personalizadas
  • Integración con sistemas externos
  • Alertas por múltiples canales
# Ejemplo: Notificación por Discord
curl -H "Content-Type: application/json" \
     -d '{"content":"Claude Code requiere atención"}' \
     "$DISCORD_WEBHOOK"

4. Stop

Se ejecuta cuando Claude Code termina de responder.

Casos de uso:

  • Ejecutar scripts de post-procesamiento
  • Generar reportes de sesión
  • Limpiar archivos temporales
# Ejemplo: Generar reporte de cambios
git diff --stat > session_changes.txt

Estructura de Datos de Input

Los hooks reciben información contextual vía JSON en stdin:

PreToolUse Input

{
  "event": "PreToolUse",
  "session_id": "session_123",
  "tool_name": "Edit",
  "tool_input": {
    "file_path": "src/component.tsx",
    "content": "// Nuevo contenido...",
    "start_line": 1,
    "end_line": 10
  }
}

PostToolUse Input

{
  "event": "PostToolUse", 
  "session_id": "session_123",
  "tool_name": "Bash",
  "tool_input": {
    "command": "npm test"
  },
  "tool_response": {
    "exit_code": 0,
    "stdout": "Tests passed",
    "stderr": ""
  }
}

Ejemplos Avanzados de Hooks

Sistema de Validación de Código

#!/bin/bash
# validate_code.sh - Hook de validación comprehensiva

# Leer input JSON
input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
tool_name=$(echo "$input" | jq -r '.tool_name')

# Solo procesar operaciones de archivo
if [[ "$tool_name" != "Edit" && "$tool_name" != "Write" ]]; then
    exit 0
fi

# Validaciones específicas por tipo de archivo
case "$file_path" in
    *.js|*.ts|*.jsx|*.tsx)
        # Validar sintaxis JavaScript/TypeScript
        if ! npx tsc --noEmit "$file_path" 2>/dev/null; then
            echo "Error: Código TypeScript inválido" >&2
            exit 2
        fi
        
        # Ejecutar ESLint
        if ! npx eslint "$file_path" --fix; then
            echo "Warning: Problemas de linting detectados" >&2
        fi
        ;;
        
    *.py)
        # Validar sintaxis Python
        if ! python -m py_compile "$file_path"; then
            echo "Error: Sintaxis Python inválida" >&2
            exit 2
        fi
        
        # Formatear con black
        black "$file_path"
        ;;
        
    *.go)
        # Validar sintaxis Go
        if ! go fmt -e "$file_path"; then
            echo "Error: Sintaxis Go inválida" >&2
            exit 2
        fi
        
        # Ejecutar go vet
        go vet "$file_path"
        ;;
esac

echo "Validación completada para $file_path"

Sistema de Notificaciones Inteligentes

#!/bin/bash
# smart_notifications.sh - Notificaciones contextuales

input=$(cat)
event=$(echo "$input" | jq -r '.event')
tool_name=$(echo "$input" | jq -r '.tool_name // empty')

case "$event" in
    "Notification")
        # Notificación por terminal
        osascript -e 'display notification "Claude Code requiere atención" with title "AI Assistant"'
        
        # Notificación por Slack en horario laboral
        hour=$(date +%H)
        if [[ $hour -ge 9 && $hour -le 17 ]]; then
            curl -X POST "$SLACK_WEBHOOK" \
                 -H 'Content-type: application/json' \
                 -d '{"text":"Claude Code necesita input"}'
        fi
        ;;
        
    "Stop")
        # Generar resumen de sesión
        session_id=$(echo "$input" | jq -r '.session_id')
        echo "Sesión $session_id completada - $(date)" >> ~/.claude/session_log.txt
        ;;
esac

Control de Permisos Granular

#!/bin/bash
# permission_control.sh - Control de acceso basado en contexto

input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
tool_name=$(echo "$input" | jq -r '.tool_name')
command=$(echo "$input" | jq -r '.tool_input.command // empty')

# Proteger archivos de configuración críticos
protected_files=(
    "package.json"
    ".env"
    "docker-compose.yml"
    "Dockerfile"
    ".github/workflows/*"
)

for pattern in "${protected_files[@]}"; do
    if [[ "$file_path" == $pattern ]]; then
        # Solicitar confirmación explícita
        echo "ADVERTENCIA: Intentando modificar archivo crítico: $file_path" >&2
        echo "¿Estás seguro? Este cambio podría afectar la configuración del proyecto." >&2
        exit 2
    fi
done

# Bloquear comandos potencialmente peligrosos
dangerous_commands=(
    "rm -rf"
    "sudo"
    "chmod 777"
    "dd"
)

for cmd in "${dangerous_commands[@]}"; do
    if [[ "$command" == *"$cmd"* ]]; then
        echo "Error: Comando peligroso bloqueado: $cmd" >&2
        echo "Uso: Evita comandos que puedan causar daño al sistema" >&2
        exit 2
    fi
done

echo "Permisos validados correctamente"

Integración con MCP Tools

Claude Code hooks funcionan perfectamente con herramientas del Model Context Protocol (MCP):

Nomenclatura de Herramientas MCP

mcp__<servidor>__<herramienta>

Ejemplos:
- mcp__memory__create_entities
- mcp__filesystem__read_file  
- mcp__github__search_repositories

Configuración para Herramientas MCP

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp__github__.*",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'GitHub operation logged' >> ~/.claude/github_ops.log"
          }
        ]
      },
      {
        "matcher": "mcp__filesystem__write_file",
        "hooks": [
          {
            "type": "command",
            "command": "./scripts/backup_before_write.sh \"$file_path\""
          }
        ]
      }
    ]
  }
}

Respuestas Avanzadas con JSON

Para control sofisticado, los hooks pueden retornar JSON estructurado:

Control de Flujo PreToolUse

#!/bin/bash
# advanced_pretool_hook.sh

input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')

# Lógica de validación compleja...
if [[ "$file_path" =~ ^production/ ]]; then
    # Bloquear operación y proporcionar feedback específico
    jq -n '{
        "decision": "block",
        "reason": "Las modificaciones a archivos de producción requieren revisión manual. Por favor, crea un pull request.",
        "continue": false,
        "stopReason": "Operación bloqueada por política de seguridad"
    }'
    exit 0
fi

# Aprobar automáticamente archivos de desarrollo
if [[ "$file_path" =~ ^dev/ ]]; then
    jq -n '{
        "decision": "approve", 
        "reason": "Archivo de desarrollo - aprobación automática"
    }'
    exit 0
fi

# Continuar con flujo normal
echo '{}'

Feedback Inteligente PostToolUse

#!/bin/bash
# intelligent_feedback.sh

input=$(cat)
tool_response=$(echo "$input" | jq -r '.tool_response')
exit_code=$(echo "$tool_response" | jq -r '.exit_code // 0')

if [[ $exit_code -ne 0 ]]; then
    stderr_output=$(echo "$tool_response" | jq -r '.stderr')
    
    # Proporcionar feedback específico basado en el error
    if [[ "$stderr_output" == *"permission denied"* ]]; then
        jq -n '{
            "decision": "block",
            "reason": "Error de permisos detectado. Intenta usar sudo o verifica los permisos del archivo.",
            "continue": false
        }'
    elif [[ "$stderr_output" == *"command not found"* ]]; then
        jq -n '{
            "decision": "block", 
            "reason": "Comando no encontrado. Verifica que la herramienta esté instalada o usa una alternativa.",
            "continue": false
        }'
    fi
else
    # Operación exitosa
    echo '{"decision": "approve"}'
fi

Mejores Prácticas de Seguridad

⚠️ Consideraciones Críticas

Los hooks ejecutan comandos con permisos completos del usuario sin confirmación. Esto requiere precauciones estrictas:

1. Validación y Sanitización de Inputs

#!/bin/bash
# secure_hook_template.sh

# Función para sanitizar inputs
sanitize_input() {
    local input="$1"
    # Remover caracteres peligrosos
    echo "$input" | sed 's/[;&|`$(){}[\]\\]//g'
}

# Función para validar paths
validate_path() {
    local path="$1"
    
    # Bloquear path traversal
    if [[ "$path" == *".."* ]]; then
        echo "Error: Path traversal detectado" >&2
        exit 1
    fi
    
    # Asegurar que el path esté dentro del proyecto
    if [[ ! "$path" =~ ^[./] ]]; then
        echo "Error: Path fuera del proyecto" >&2
        exit 1
    fi
}

# Leer y validar input
input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')

if [[ -n "$file_path" ]]; then
    validate_path "$file_path"
    file_path=$(sanitize_input "$file_path")
fi

2. Uso Seguro de Variables

# ❌ INCORRECTO - Vulnerable a injection
command="ls $user_input"

# ✅ CORRECTO - Variables citadas apropiadamente  
command="ls \"$user_input\""

# ✅ MÁS SEGURO - Validación previa
if [[ "$user_input" =~ ^[a-zA-Z0-9._/-]+$ ]]; then
    command="ls \"$user_input\""
else
    echo "Input inválido" >&2
    exit 1
fi

3. Lista de Archivos Sensibles Protegidos

#!/bin/bash
# protect_sensitive_files.sh

SENSITIVE_PATTERNS=(
    "*.env*"
    "*.key"
    "*.pem"
    "*.p12"
    "*.jks"
    ".ssh/*"
    ".aws/*"
    ".docker/config.json"
    "secrets/*"
    "password*"
    "*.secret"
)

file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')

for pattern in "${SENSITIVE_PATTERNS[@]}"; do
    if [[ "$file_path" == $pattern ]]; then
        echo "Error: Archivo sensible protegido: $file_path" >&2
        echo "Por favor, maneja archivos de credenciales manualmente." >&2
        exit 2
    fi
done

Configuración Segura por Defecto

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "./scripts/security_check.sh"
          }
        ]
      }
    ]
  }
}

Workflow de Desarrollo Completo

Configuración de Equipo Empresarial

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "comment": "Validar permisos de archivo",
            "command": "./hooks/validate_permissions.sh"
          },
          {
            "type": "command", 
            "comment": "Verificar estándares de código",
            "command": "./hooks/code_standards.sh"
          }
        ]
      },
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "comment": "Auditar comandos ejecutados", 
            "command": "echo \"$(date): $command\" >> ~/.claude/audit.log"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "comment": "Formateo automático",
            "command": "./hooks/auto_format.sh"
          },
          {
            "type": "command",
            "comment": "Ejecutar linting",
            "command": "./hooks/run_linting.sh"
          },
          {
            "type": "command",
            "comment": "Tests unitarios si aplicable",
            "command": "./hooks/run_tests.sh"
          }
        ]
      }
    ],
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "comment": "Notificación por Slack",
            "command": "./hooks/slack_notification.sh"
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "comment": "Generar reporte de sesión",
            "command": "./hooks/session_report.sh"
          }
        ]
      }
    ]
  }
}

Debugging y Troubleshooting

Verificación de Configuración

# Verificar configuración actual
/hooks

# Comprobar archivos de configuración
cat ~/.claude/settings.json | jq '.hooks'
cat .claude/settings.json | jq '.hooks'

# Validar JSON
json_verify < ~/.claude/settings.json

Modo Debug

# Ejecutar Claude Code con debug habilitado
claude-code --debug

# Los hooks mostrarán información detallada:
# - Comando ejecutándose
# - Status de éxito/fallo  
# - Output y mensajes de error

Testing Manual de Hooks

# Test independiente de hook
echo '{"event":"PreToolUse","tool_name":"Edit","tool_input":{"file_path":"test.js"}}' | ./my_hook.sh

# Verificar exit codes
echo $?  # 0=success, 2=block, other=error

Logs y Monitoreo

# Configurar logging comprehensivo
mkdir -p ~/.claude/logs

# Hook de logging universal
echo '{"event":"'$event'","tool":"'$tool_name'","timestamp":"'$(date -Iseconds)'"}' >> ~/.claude/logs/hook_activity.log

Casos de Uso Empresariales

1. Compliance y Auditoría

#!/bin/bash
# compliance_hook.sh - Registro para auditoría SOX/SOC2

{
    echo "{"
    echo "  \"timestamp\": \"$(date -Iseconds)\","
    echo "  \"user\": \"$USER\","
    echo "  \"session\": \"$session_id\","
    echo "  \"action\": \"$tool_name\","
    echo "  \"file\": \"$file_path\","
    echo "  \"command\": \"$command\""
    echo "}"
} >> /var/log/claude_audit.jsonl

2. CI/CD Integration

#!/bin/bash
# cicd_trigger.sh - Integración con pipelines

if [[ "$file_path" =~ \.(js|ts|py|go)$ ]]; then
    # Trigger build pipeline
    curl -X POST "$CI_WEBHOOK" \
         -H "Content-Type: application/json" \
         -d "{\"ref\":\"$BRANCH\",\"message\":\"Code updated by Claude\"}"
fi

3. Seguridad Corporativa

#!/bin/bash
# corporate_security.sh - Políticas de seguridad empresarial

# Verificar contra base de datos de vulnerabilidades
if command -v safety &> /dev/null && [[ "$file_path" == "requirements.txt" ]]; then
    safety check --file "$file_path" --json > safety_report.json
    
    if [[ $(jq '.vulnerabilities | length' safety_report.json) -gt 0 ]]; then
        echo "Error: Vulnerabilidades detectadas en dependencias" >&2
        jq '.vulnerabilities[] | .vulnerability' safety_report.json >&2
        exit 2
    fi
fi

El Futuro de Claude Code Hooks

Los hooks representan solo el comienzo de un ecosistema más amplio de personalización:

Funcionalidades en Desarrollo

  • Hooks visuales con interfaces gráficas
  • Marketplace de hooks compartidos por la comunidad
  • Integración nativa con más herramientas de desarrollo
  • Hooks remotos ejecutados en la nube
  • AI-powered hooks que aprenden de patrones de uso

Ecosistema Emergente

  • Templates de hooks para diferentes stacks tecnológicos
  • Librerías de validación específicas por lenguaje
  • Integraciones enterprise con herramientas corporativas
  • Hooks colaborativos para equipos distribuidos

Conclusión: Transformando el Desarrollo con IA

Los Claude Code Hooks representan un paradigma fundamental en cómo las herramientas de IA se integran en workflows de desarrollo reales. Al permitir automatización determinística y personalización granular, transforman Claude Code de una herramienta de asistencia a una plataforma de desarrollo extensible.

Beneficios clave:

  • Consistencia garantizada en estándares de código
  • Automatización de tareas repetitivas
  • Integración profunda con herramientas existentes
  • Control granular sobre comportamientos de IA
  • Escalabilidad empresarial con políticas centralizadas

Para comenzar:

  1. Identifica procesos manuales repetitivos en tu workflow
  2. Implementa hooks simples (logging, formateo)
  3. Gradualmente añade validaciones y controles más sofisticados
  4. Comparte configuraciones exitosas con tu equipo

Los hooks no solo mejoran la productividad individual, sino que permiten a los equipos codificar su conocimiento colectivo en automatizaciones que benefician a toda la organización.

El futuro del desarrollo de software está en herramientas que no solo asisten, sino que se adaptan y evolucionan con las necesidades específicas de cada proyecto y equipo. Claude Code Hooks marca el camino hacia esa realidad.


Enlaces útiles:

Tags: #ClaudeCode #Hooks #AI #Automation #DevOps #Workflow #Development #Productivity

Comentarios

Relacionados