Claude Code Hooks: automatiza tu workflow de desarrollo

Aprende a configurar Claude Code Hooks para ejecutar comandos automáticamente en respuesta a acciones del agente. Linting, tests, notificaciones y más.

Claude Code Hooks: automatiza tu workflow de desarrollo

Claude Code Hooks: automatiza tu workflow de desarrollo

Los hooks de Claude Code son comandos de shell que se ejecutan automáticamente en respuesta a eventos del agente. Cuando Claude Code termina de editar un archivo, un hook puede lanzar el formatter. Cuando completa una sesión, otro hook puede correr los tests afectados. Y todo sin que tú lo pidas.

Esta guía cubre todo lo que necesitas saber para implementar hooks en tu proyecto: tipos disponibles, configuración, casos de uso reales y patrones avanzados.


Qué son los Claude Code Hooks

Los hooks son comandos que se ejecutan en puntos específicos del ciclo de vida de Claude Code. Funcionan de forma similar a los git hooks: defines qué comando ejecutar y en qué momento, y el sistema los invoca automáticamente.

Son útiles para:

  • Formatear código automáticamente después de cada edición
  • Validar que los cambios pasan linting antes de seguir
  • Correr tests de los archivos modificados al terminar
  • Enviar notificaciones cuando Claude Code completa una tarea larga
  • Actualizar un archivo de log de cambios

Configuración básica: settings.json

Los hooks se configuran en .claude/settings.json dentro del repositorio:

{
  "hooks": {
    "EventName": [
      {
        "matcher": "PatrónOpcional",
        "hooks": [
          {
            "type": "command",
            "command": "tu-comando-aquí"
          }
        ]
      }
    ]
  }
}

El matcher es opcional: si lo incluyes, el hook solo se dispara cuando la herramienta que lo generó coincide con el patrón. Si lo omites, el hook se dispara en cualquier acción del tipo de evento.


Tipos de eventos disponibles

PreToolUse

Se ejecuta antes de que Claude Code use una herramienta. Puedes usarlo para validaciones o para bloquear ciertas acciones.

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{
          "type": "command",
          "command": "echo 'Claude va a ejecutar un comando'"
        }]
      }
    ]
  }
}

PostToolUse

Se ejecuta después de que Claude Code usa una herramienta. El más común — ideal para formateo y linting.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [{
          "type": "command",
          "command": "npx prettier --write $CLAUDE_TOOL_INPUT_FILE_PATH"
        }]
      }
    ]
  }
}

La variable de entorno $CLAUDE_TOOL_INPUT_FILE_PATH contiene la ruta del archivo que acaba de modificarse.

Stop

Se ejecuta cuando Claude Code termina una sesión o tarea. Perfecto para correr tests o enviar notificaciones.

{
  "hooks": {
    "Stop": [
      {
        "hooks": [{
          "type": "command",
          "command": "npm run test:changed"
        }]
      }
    ]
  }
}

Notification

Se dispara cuando Claude Code genera una notificación interna (por ejemplo, cuando necesita confirmación). Útil para integrar con sistemas de alertas externos.


Variables de entorno disponibles en hooks

VariableContenido
$CLAUDE_TOOL_NAMENombre de la herramienta que disparó el evento (Edit, Bash, etc.)
$CLAUDE_TOOL_INPUT_FILE_PATHRuta del archivo afectado (en eventos de edición)
$CLAUDE_TOOL_OUTPUTOutput de la herramienta (en PostToolUse)
$CLAUDE_SESSION_IDID de la sesión actual

Casos de uso reales

1. Auto-format con Prettier después de cada edición

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [{
          "type": "command",
          "command": "npx prettier --write --ignore-unknown \"$CLAUDE_TOOL_INPUT_FILE_PATH\""
        }]
      }
    ]
  }
}

2. Linting con Ruff (Python) en cada edición

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [{
          "type": "command",
          "command": "ruff check --fix \"$CLAUDE_TOOL_INPUT_FILE_PATH\" 2>/dev/null || true"
        }]
      }
    ]
  }
}

El || true evita que un fallo de linting interrumpa el flujo de Claude Code.

3. Tests automáticos al terminar una sesión

{
  "hooks": {
    "Stop": [
      {
        "hooks": [{
          "type": "command",
          "command": "pytest tests/ -x -q 2>&1 | tail -20"
        }]
      }
    ]
  }
}

4. Notificación de escritorio al completar tarea larga

{
  "hooks": {
    "Stop": [
      {
        "hooks": [{
          "type": "command",
          "command": "osascript -e 'display notification \"Claude Code terminó\" with title \"DevAI\"' 2>/dev/null || notify-send 'Claude Code terminó'"
        }]
      }
    ]
  }
}

Funciona en macOS (osascript) y Linux (notify-send).

5. Actualizar changelog automáticamente

{
  "hooks": {
    "Stop": [
      {
        "hooks": [{
          "type": "command",
          "command": "git diff --stat HEAD | head -20 >> CLAUDE_CHANGES.log"
        }]
      }
    ]
  }
}

Hooks combinados: un settings.json completo

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write --ignore-unknown \"$CLAUDE_TOOL_INPUT_FILE_PATH\" 2>/dev/null || true"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "npm run test:changed 2>&1 | tail -30"
          },
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude Code terminó\" with title \"DevAI\"' 2>/dev/null || true"
          }
        ]
      }
    ]
  }
}

Hooks vs permisos: la diferencia clave

Es importante no confundir hooks con permisos:

  • Permisos (permissions.allow): controlan qué puede hacer Claude Code sin pedir confirmación.
  • Hooks: comandos adicionales que defines y que se ejecutan como respuesta a las acciones del agente.

Los hooks corren con tus privilegios de usuario, no con los del agente. Si un hook falla, Claude Code recibe el error y puede reaccionar, pero el hook no puede bloquear una acción que ya tiene permisos para realizar.


Debugging de hooks

Si un hook no funciona como esperas:

  1. Prueba el comando manualmente en el terminal con las variables de entorno simuladas:
    CLAUDE_TOOL_INPUT_FILE_PATH="src/main.py" bash -c 'ruff check "$CLAUDE_TOOL_INPUT_FILE_PATH"'
  2. Añade logging: redirige el output del hook a un archivo:
    "command": "tu-comando >> /tmp/claude-hooks.log 2>&1"
  3. Usa /doctor en Claude Code para verificar que el settings.json es válido.

Guía completa de Claude Code

Cómo hacer que Claude Code acepte todo automáticamente

DevAI — newsletter semanal para desarrolladores sobre Claude Code, Cursor y herramientas de IA. Suscríbete gratis.