ESLint Flat Config con Claude Code para proyectos reales
Configura ESLint Flat Config con Claude Code para TypeScript, React, Astro, CI y prompts de corrección.
No dejes que Claude Code adivine toda la configuración
ESLint es una herramienta de análisis estático para JavaScript y TypeScript. Análisis estático significa revisar el código antes de ejecutarlo, para detectar promesas sin esperar, errores de React Hooks, problemas de accesibilidad, importaciones desordenadas y patrones que suelen acabar en bugs.
Desde ESLint v9, Flat Config es el formato estándar. En junio de 2026 la documentación oficial sigue explicando la configuración alrededor de eslint.config.js y eslint.config.mjs. El problema es que pedir a Claude Code “configura ESLint” es demasiado abierto. Puede mezclar hábitos de .eslintrc, omitir reglas con información de tipos o activar reglas que ralentizan CI sin aportar seguridad real.
La forma práctica es darle un contrato claro: stack del proyecto, carpetas generadas, comandos que deben pasar y reglas que se pueden relajar solo en tests. Esta guía resume el flujo que Masa usa en un panel React, un sitio Astro de contenidos y una librería TypeScript pequeña.
Las referencias oficiales son ESLint Configuration Files, typescript-eslint typed linting, eslint-plugin-astro User Guide y Claude Code CLI reference.
Instala dependencias y scripts primero
Antes de pedir cambios a Claude Code, instala los paquetes que corresponden al proyecto. El conjunto base cubre ESLint, TypeScript, React, Hooks, accesibilidad y orden de imports. Añade los paquetes de Astro solo si hay archivos .astro.
npm i -D eslint @eslint/js typescript typescript-eslint globals
npm i -D eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y
npm i -D eslint-plugin-simple-import-sort
# Solo para proyectos Astro
npm i -D eslint-plugin-astro astro-eslint-parser
En package.json, separa la corrección local de la verificación de CI. lint:fix sirve para limpiar código en local. lint y typecheck son los comandos que debe ejecutar CI. --max-warnings=0 hace que las advertencias fallen; en proyectos antiguos conviene activarlo después de la primera limpieza.
{
"scripts": {
"lint": "eslint . --max-warnings=0",
"lint:fix": "eslint . --fix",
"lint:debug": "eslint --print-config src/App.tsx > .eslint-debug.json",
"typecheck": "tsc --noEmit",
"ci:verify": "npm run lint && npm run typecheck"
}
}
Claude Code no debe detenerse al escribir el archivo de configuración. Tiene que ejecutar los mismos comandos que usará el equipo.
package.json scripts
-> eslint.config.mjs
-> npm run lint:fix
-> npm run lint
-> npm run typecheck
-> CI gate
-> revisión del diff restante con Claude Code
Flat Config para TypeScript y React
Para una app React + TypeScript, este eslint.config.mjs es un buen punto de partida. projectService: true activa linting con información de tipos. Es potente, pero tiene coste, así que los artefactos generados y carpetas de build deben ignorarse desde el principio.
import js from "@eslint/js";
import globals from "globals";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";
import jsxA11y from "eslint-plugin-jsx-a11y";
import simpleImportSort from "eslint-plugin-simple-import-sort";
import tseslint from "typescript-eslint";
export default tseslint.config(
{
ignores: [
"node_modules/",
"dist/",
"build/",
"coverage/",
".next/",
".astro/",
"public/",
"*.min.js"
]
},
js.configs.recommended,
...tseslint.configs.strictTypeChecked,
...tseslint.configs.stylisticTypeChecked,
{
files: ["**/*.{js,mjs,cjs,ts,tsx}"],
languageOptions: {
ecmaVersion: "latest",
sourceType: "module",
globals: {
...globals.browser,
...globals.node,
...globals.es2024
},
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname
}
}
},
{
files: ["**/*.{jsx,tsx}"],
...react.configs.flat.recommended,
settings: {
react: { version: "detect" }
},
rules: {
...react.configs.flat.recommended.rules,
"react/react-in-jsx-scope": "off",
"react/prop-types": "off"
}
},
{
files: ["**/*.{jsx,tsx}"],
plugins: {
"react-hooks": reactHooks,
"jsx-a11y": jsxA11y
},
rules: {
...reactHooks.configs.recommended.rules,
...jsxA11y.configs.recommended.rules
}
},
{
plugins: {
"simple-import-sort": simpleImportSort
},
rules: {
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"@typescript-eslint/consistent-type-imports": [
"error",
{ prefer: "type-imports", fixStyle: "separate-type-imports" }
],
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-misused-promises": [
"error",
{ checksVoidReturn: { attributes: false } }
],
"@typescript-eslint/no-unused-vars": [
"error",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" }
],
"no-console": ["warn", { allow: ["warn", "error"] }]
}
},
{
files: ["**/*.{js,mjs,cjs}"],
extends: [tseslint.configs.disableTypeChecked]
},
{
files: ["**/*.{test,spec}.{ts,tsx}", "**/__tests__/**/*.{ts,tsx}"],
rules: {
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-member-access": "off"
}
}
);
La intención no es imponer gustos de estilo, sino reducir fallos reales. no-floating-promises detecta llamadas async olvidadas. no-misused-promises evita handlers JSX peligrosos. consistent-type-imports mantiene claras las importaciones que solo son tipos. Los tests pueden tener excepciones, pero la configuración principal no debe debilitarse por comodidad.
Astro necesita tratar .astro aparte
Un archivo Astro mezcla plantilla, TypeScript frontmatter, componentes y scripts de cliente. Si aplicas una configuración pensada solo para React a .astro, ESLint puede fallar en el parseo antes de encontrar problemas útiles.
Para un sitio Astro de contenido, usa primero las configuraciones recomendadas del plugin y añade reglas propias para .astro. astro/no-set-html-directive es especialmente útil en blogs y documentación, porque la inyección HTML puede pasar desapercibida durante la revisión editorial.
import js from "@eslint/js";
import astro from "eslint-plugin-astro";
import globals from "globals";
import tseslint from "typescript-eslint";
export default tseslint.config(
{
ignores: ["dist/", ".astro/", "node_modules/", "public/"]
},
js.configs.recommended,
...astro.configs["flat/recommended"],
...astro.configs["jsx-a11y-recommended"],
...tseslint.configs.recommendedTypeChecked,
{
files: ["**/*.{ts,tsx}"],
languageOptions: {
globals: {
...globals.browser,
...globals.node
},
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname
}
}
},
{
files: ["**/*.astro"],
languageOptions: {
parserOptions: {
parser: tseslint.parser,
extraFileExtensions: [".astro"],
projectService: true,
tsconfigRootDir: import.meta.dirname
}
},
rules: {
"astro/no-set-html-directive": "error",
"astro/no-unused-define-vars-in-style": "error"
}
}
);
No conviertas ESLint en el formateador de todo. Deja el formato a Prettier y usa ESLint para código inseguro, accesibilidad, errores de tipos y convenciones del proyecto. Puedes seguir con la guía de Prettier con Claude Code.
Tres casos de uso reales
El primer caso es un panel SaaS. Invitaciones, facturación y permisos dependen de código async. Ahí @typescript-eslint/no-floating-promises debe ser error, porque un await olvidado puede convertirse en una incidencia de producción.
El segundo caso es un blog técnico con Astro. Las comprobaciones de mayor valor son parseo de .astro, accesibilidad, estilos no usados y HTML inseguro. Como hay muchas páginas generadas, ignorar dist/, .astro/ y salidas de build es obligatorio.
El tercer caso es una librería TypeScript. La API pública debe ser más estricta que los tests. Mantén reglas fuertes para imports de tipo, variables sin usar y exports, y relaja any solo en fixtures.
| Proyecto | Reglas a endurecer | Lugares a relajar |
|---|---|---|
| Panel React | Promesas, Hooks, a11y | Mocks de Storybook |
| Blog Astro | .astro, HTML inseguro, CSS no usado | Contenido generado |
| Librería TypeScript | Imports de tipo, variables, exports | Fixtures de test |
Si también quieres validar antes de commit, conecta esto con Husky + lint-staged. En repos grandes, mantén pre-commit rápido y deja el lint con tipos para CI.
Añade una puerta de CI
Que funcione en local no basta. CI debe ejecutar los mismos comandos y fallar con las mismas reglas. Para GitHub Actions, este flujo mínimo cubre la mayoría de proyectos.
name: code-quality
on:
pull_request:
push:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run lint
- run: npm run typecheck
Si el repositorio existente tiene cientos de errores, no ejecutes eslint --fix en todo y publiques un diff gigante. Primero agrupa por regla y pide a Claude Code que arregle lotes pequeños.
npm run lint
npm run lint:fix
npm run lint
npm run typecheck
npm run lint:debug
lint:debug muestra la configuración resuelta para un archivo. Sirve para comprobar si una regla React toca por error .astro, o si una excepción de tests se filtró al código de producción.
Prompts para Claude Code
Plantilla 1: instalación nueva.
Añade ESLint Flat Config a este repositorio.
El stack es TypeScript + React. Lee primero package.json, tsconfig y cualquier configuración lint existente.
Crea eslint.config.mjs y continúa hasta que npm run lint y npm run typecheck pasen.
Evita autofixes que puedan cambiar comportamiento; si son necesarios, explica por qué antes.
Plantilla 2: corregir errores.
Voy a pegar la salida de npm run lint.
Agrupa los errores por regla, corrige primero las categorías de menor riesgo y mantén el diff pequeño.
Usa eslint-disable solo como último recurso. Si lo usas, añade una razón de una línea.
Después ejecuta npm run lint y npm run typecheck.
Plantilla 3: soporte Astro.
Revisa la configuración ESLint de este sitio Astro.
Separa las reglas para .astro, .ts y .tsx. Usa la configuración Flat recomendada de eslint-plugin-astro.
Pon astro/no-set-html-directive en error y confirma que las reglas React no se aplican por accidente a todo el archivo .astro.
Plantilla 4: fallo en CI.
El job de lint en GitHub Actions está fallando.
Compara las versiones locales y de CI de Node, npm, ESLint y plugins.
Crea un comando de reproducción y separa la solución en cambio de config, actualización de dependencia o cambio de código.
Aplica el diff seguro más pequeño.
Claude Code necesita archivos que leer, comandos que ejecutar y límites claros. “Arregla lint” es débil. “No debilites reglas de producción y demuéstralo con estos comandos” es mucho más útil.
Errores habituales
El primer error es copiar una cadena extends antigua de .eslintrc dentro de Flat Config. La forma es distinta. Si una configuración compartida aún no tiene soporte, revisa compatibilidad, pero prioriza ejemplos Flat oficiales.
El segundo error es aplicar lint con tipos a todos los archivos. projectService: true es potente, pero leer bundles, salidas generadas y builds vuelve CI lento. Define ignores antes de ajustar reglas.
El tercer error es aceptar un diff enorme de autofix. Orden de imports, type imports, variables sin usar y formato pueden esconder cambios reales. Masa suele separar el primer rollout por promesas, imports y reglas del framework.
El cuarto error es dejar warnings para siempre. Una advertencia que nunca bloquea se convierte en ruido. Usa error para política, warn para educación temporal y elimina reglas con poca señal.
El quinto error es no explicar intención a Claude Code. Dile si accesibilidad es crítica, si los fixtures pueden usar any, o si la API pública debe ser estricta. Esas restricciones producen mejores decisiones que una recomendación genérica.
Resumen
ESLint Flat Config hace más visible el alcance de las reglas porque la configuración vive en un solo lugar. Claude Code aporta valor cuando lee el código actual, ejecuta verificaciones y ajusta la configuración sin rebajar los estándares importantes.
Empieza con una base correcta para React/TypeScript o Astro. Añade npm run lint y npm run typecheck a CI. Luego usa prompts explícitos y revisa manualmente cualquier eslint-disable o diff grande de --fix.
Para completar el flujo, combina esta guía con Prettier y Husky + lint-staged. Si necesitas prompts reutilizables y listas de adopción, la página de productos de ClaudeCodeLab reúne guías y consultoría.
Resultado probado en la práctica
Masa probó esta configuración en un panel React pequeño y en una plantilla de blog Astro. La primera ejecución mostró mucho ruido de importaciones y varias promesas sin manejar. Un solo diff de eslint --fix fue difícil de revisar, así que funcionó mejor separar promesas, imports y reglas de seguridad Astro. El flujo más repetible fue fijar npm run lint y npm run typecheck en CI, pegar los logs fallidos en Claude Code y pedir correcciones pequeñas con comandos de prueba.
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.