Configurar Husky + lint-staged con Claude Code: guía práctica de pre-commit
Configura Husky y lint-staged con Claude Code para ejecutar ESLint y Prettier antes de cada commit.
Claude Code puede modificar muchos archivos en una sola sesión. Eso es útil para refactors, tests y cambios de configuración, pero también aumenta el ruido en la revisión. El revisor debería mirar comportamiento, diseño y riesgos, no perseguir imports sin usar, formato inconsistente o tablas Markdown que cambiaron solo por espacios.
Husky + lint-staged resuelve una parte concreta de ese problema. Un Git hook es un pequeño script que Git ejecuta en un punto del flujo, por ejemplo antes de crear un commit. Husky permite versionar esos hooks dentro del repositorio. lint-staged ejecuta comandos solo sobre archivos ya preparados con git add, por eso evita recorrer todo el proyecto en cada commit. Los hooks de Claude Code son otra cosa: se ejecutan dentro del ciclo de vida de Claude Code y sirven como apoyo, pero no sustituyen a un Git hook que protege cualquier commit.
La idea no es convertir pre-commit en un CI local pesado. La regla práctica es simple: checks rápidos en pre-commit, validaciones medianas en pre-push y verificación completa en CI.
Flujo recomendado
Cuando Claude Code edita varios archivos, conviene que el flujo sea predecible. Primero se eligen los archivos con git add; después Husky llama a lint-staged; por último ESLint y Prettier corrigen lo que esté a punto de entrar al commit.
flowchart LR
A["Claude Code edita archivos"] --> B["El desarrollador hace git add"]
B --> C["Husky pre-commit"]
C --> D["lint-staged"]
D --> E["ESLint / Prettier"]
E --> F["commit"]
C --> G["typecheck, tests y build van a pre-push o CI"]
Para evitar información antigua, revisé las referencias oficiales: Husky Get started, lint-staged README, manual de Git hooks y Claude Code hooks reference. El punto importante es que Husky recomienda npx husky init, y lint-staged necesita un hook pre-commit más una configuración de patrones de archivos.
Configuración mínima que funciona
Si ESLint o Prettier todavía no están claros en el proyecto, empieza por la guía de ESLint con Claude Code y la guía de Prettier. Husky solo dispara comandos; la calidad real depende de esos comandos.
Un buen prompt para Claude Code debe indicar alcance y límites:
Agrega Husky y lint-staged a este repositorio Node.js/TypeScript.
El pre-commit solo debe procesar archivos JS, TS, JSON, Markdown y CSS que estén staged.
Ejecuta ESLint con auto-fix y Prettier en pre-commit.
No pongas typecheck, tests ni build en pre-commit; muévelos a pre-push o CI.
Al final, lista los comandos manuales de verificación.
La instalación manual es corta:
npm install --save-dev husky lint-staged eslint prettier
npx husky init
npx husky init crea .husky/pre-commit y actualiza el script prepare en package.json. Cambia el contenido del hook por esto:
#!/usr/bin/env sh
npx lint-staged
Después agrega una configuración pequeña. Si tu package.json ya tiene scripts, combina las claves sin borrar las existentes.
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint --fix .",
"format": "prettier --write .",
"format:check": "prettier --check .",
"prepare": "husky"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix --max-warnings=0",
"prettier --write"
],
"*.{json,md,mdx,yml,yaml,css,scss}": [
"prettier --write"
]
}
}
Verifica con un archivo deliberadamente mal formateado:
git add src/example.ts
npx lint-staged --debug
git commit -m "chore: verify pre-commit checks"
El modo --debug muestra qué configuración se cargó, qué archivos coincidieron y qué comandos se ejecutaron. Cuando algo falle, pega esa salida en Claude Code; es mucho más útil que pedirle que adivine.
Configuración mantenible
En repositorios medianos prefiero mover la configuración a lint-staged.config.mjs. Mantiene limpio el package.json y permite funciones auxiliares. Este ejemplo entrecomilla nombres de archivo para evitar fallos con rutas que tienen espacios.
// lint-staged.config.mjs
const shellQuote = (file) => `"${file.replaceAll('"', '\\"')}"`;
const joinFiles = (files) => files.map(shellQuote).join(" ");
export default {
"*.{js,jsx,ts,tsx}": (files) => [
`eslint --fix --max-warnings=0 ${joinFiles(files)}`,
`prettier --write ${joinFiles(files)}`,
],
"*.{json,md,mdx,yml,yaml,css,scss}": (files) =>
`prettier --write ${joinFiles(files)}`,
};
Si usas este archivo, elimina la clave lint-staged de package.json. Dos fuentes de verdad generan confusión para el equipo y también para Claude Code.
Tres casos de uso
Primer caso: una aplicación TypeScript. Claude Code suele tocar componentes, tests y utilidades en el mismo cambio. ESLint con auto-fix y Prettier eliminan ruido antes de la revisión. El typecheck completo conviene dejarlo en pre-push o CI, porque necesita contexto del proyecto y puede tardar demasiado.
Segundo caso: un sitio Astro o Next.js con mucho contenido. MDX, JSON, CSS y TypeScript se mezclan con frecuencia. lint-staged ayuda a que el diff de un artículo muestre cambios reales de contenido, no solo saltos de línea.
Tercer caso: un monorepo. Ejecutar todos los tests de todos los paquetes en pre-commit suele ser un error. Es mejor formatear y lintar archivos staged, y dejar que CI o el task runner decidan qué pruebas de paquete corren según la ruta modificada.
commit-msg y pre-push
La validación del mensaje de commit debe ir separada. Para Conventional Commits, usa commitlint.
npm install --save-dev @commitlint/cli @commitlint/config-conventional
// commitlint.config.mjs
export default {
extends: ["@commitlint/config-conventional"],
rules: {
"subject-max-length": [2, "always", 72],
},
};
#!/usr/bin/env sh
npx --no -- commitlint --edit "$1"
Guarda ese shell en .husky/commit-msg. Para checks más pesados, usa .husky/pre-push:
#!/usr/bin/env sh
npm run validate
Y alinea el script con CI:
{
"scripts": {
"typecheck": "tsc --noEmit",
"test:ci": "vitest run --coverage",
"build": "vite build",
"validate": "npm run typecheck && npm run lint && npm run format:check && npm run test:ci && npm run build"
}
}
Errores frecuentes
El error más común es poner demasiado en pre-commit. Si cada commit tarda dos minutos, el equipo aprenderá a saltarse el hook. Si tarda pocos segundos, se vuelve parte natural del flujo.
Otro problema real es el partial staging. lint-staged trabaja con archivos staged, pero el mismo archivo puede tener cambios no staged. Para depurar, mira juntos git status --short, git diff --staged y npx lint-staged --debug.
En equipos con Windows, macOS y Linux, las terminaciones de línea importan. Los hooks de Husky son scripts shell, así que conviene guardarlos con LF.
* text=auto eol=lf
*.cmd text eol=crlf
*.bat text eol=crlf
Tampoco aceptes soluciones como || true. Ocultan el fallo y convierten el control de calidad en decoración. Es mejor mover tareas lentas a pre-push, reducir el mensaje de error o documentar el comando de arreglo.
Resultado probado
Probé esta estructura en un proyecto TypeScript/Vite pequeño con formato roto, un import sin usar y un problema de espacios en MDX. pre-commit siguió siendo rápido porque solo procesó archivos staged. npx lint-staged --debug mostró claramente los archivos y comandos. Los errores de tipos quedaron para npm run validate en pre-push, lo que mantuvo fluido el ritmo de commits sin debilitar la revisión final.
Resumen
Husky + lint-staged es una barrera práctica para proyectos donde Claude Code genera cambios amplios. Mantén pre-commit ligero, mueve las comprobaciones caras a pre-push o CI, y deja esa regla escrita en los prompts de Claude Code. Así el hook se vuelve un hábito de equipo, no un obstáculo local.
El siguiente paso es reforzar las reglas en la guía de ESLint y unificar formato con la guía de Prettier.
PDF gratis: cheatsheet de Claude Code
Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.
Cuidamos tus datos y no enviamos spam.
Sobre el autor
Masa
Ingeniero enfocado en workflows prácticos con Claude Code.
Artículos relacionados
Escalera de permisos de Claude Code para ampliar acceso sin perder control
Pasa de read-only a ediciones limitadas, comandos de prueba y checks de deploy con menos riesgo.
Claude Code Small PR Proof Pack: cambios pequeños que sí se pueden revisar
Un paquete de prueba para PRs de Claude Code: diff, checks, URL pública, CTA y rollback.
Gate de revisión antes del commit con Claude Code
Cómo revisar con Claude Code antes del commit: diff, build, URL pública, Gumroad, consultoría, tests y archivos ajenos.