Hook de Claude Code para formatear con Pint y analizar con PHPStan
Hola, bienvenido. En esta lección pasamos al otro lado de la herramienta, a PostToolUse, después de crear en la anterior guard.sh, que bloquea en PreToolUse lo que no debe pasar nunca en el proyecto. Vamos a crear 2 hooks de calidad: pint.sh, que formatea con Pint cada archivo PHP que Claude acaba de escribir o editar, y phpstan.sh, que lo analiza con PHPStan y le cuenta a Claude los errores que encuentre. Por el camino veremos cómo le llega esa información a Claude con additionalContext y qué límites tiene, por qué Rector se queda fuera de los hooks y, para probarlo todo, le pediremos a Claude una acción que marca una tarea como completada, mal formateada a propósito.
Nuestro CLAUDE.md ya dice que una tarea está terminada cuando pasa composer qa, pero el circuito completo llega al final, cuando Claude ya ha escrito todos los archivos, y un hook llega justo después de cada edición, mientras el cambio está todavía fresco en la conversación. Si Claude escribe una acción con una propiedad que no existe y sigue adelante, puede escribir encima un controlador y un test que usan esa misma propiedad, y el error aparece 3 archivos después. Con el hook, PHPStan se lo dice en cuanto guarda el primer archivo, y Claude lo corrige antes de construir nada encima.
Calidad justo después de cada edición
Los 2 hooks responden al mismo momento, cuando la herramienta Edit o Write termina con éxito sobre un archivo PHP, pero hacen cosas distintas con él:
pint.shcambia el archivo. Pasa Pint solo sobre ese archivo, con las reglas de nuestropint.json, y si el formato cambia, se lo dice a Claude. Es una tarea mecánica y sin decisiones: el estilo del proyecto ya está decidido, y no tiene sentido que Claude gaste tokens en espacios y saltos de línea, ni que tú los revises.phpstan.shno cambia nada. Analiza el archivo con Larastan en el nivel 5 de nuestrophpstan.neon, y si hay errores, se los pasa a Claude para que los corrija él. Aquí sí hay decisiones, porque un error de tipos puede tener varias soluciones, así que el hook informa y Claude decide.
Ninguno de los 2 sustituye a composer qa. Los hooks miran un archivo cada vez y dan una señal rápida, y el circuito completo, con Rector en seco y los tests, sigue siendo lo que dice si una tarea está lista. Y hay una tercera herramienta del circuito que no va a tener hook, Rector, por un motivo que veremos más abajo.
Para seguir esta lección necesitas el commit de guard.sh de la lección anterior, los contenedores de Sail levantados, porque los 2 hooks ejecutan las herramientas dentro del contenedor, y jq instalado. Recuerda también lo que vimos al configurar los hooks: se ejecutan fuera del sandbox, así que pueden llamar a ./vendor/bin/sail aunque Sail no pueda ejecutarse dentro de él.
- 02El hook de Pint
- 03El hook de PHPStan
- 04Registrarlos en settings.json
- 05additionalContext y sus límites
- 06Por qué Rector se queda fuera de los hooks
- 07La prueba: una acción mal formateada