ESLint Flat Config com Claude Code em projetos reais
Configure ESLint Flat Config com Claude Code para TypeScript, React, Astro, CI e prompts de correção.
Não deixe o Claude Code adivinhar toda a configuração
ESLint é uma ferramenta de análise estática para JavaScript e TypeScript. Análise estática significa verificar o código antes de executar a aplicação, para encontrar Promises esquecidas, erros de React Hooks, problemas de acessibilidade, imports desorganizados e padrões que aumentam risco em revisão.
Desde o ESLint v9, Flat Config virou o formato padrão. Em junho de 2026, a documentação oficial ainda organiza a configuração em torno de arquivos como eslint.config.js e eslint.config.mjs. Mesmo assim, pedir apenas “configure ESLint” ao Claude Code é vago demais. Ele pode misturar hábitos antigos de .eslintrc, ignorar lint com tipos ou ativar regras que deixam CI lento sem melhorar a segurança do produto.
O fluxo mais confiável é dar um contrato claro: stack do projeto, pastas geradas, comandos que precisam passar e regras que só podem ser relaxadas em testes. Este artigo resume o padrão que Masa usa em um painel React, um site Astro de conteúdo e uma pequena biblioteca TypeScript.
Use a documentação oficial como base: ESLint Configuration Files, typescript-eslint typed linting, eslint-plugin-astro User Guide e Claude Code CLI reference.
Instale dependências e scripts primeiro
Antes de pedir alterações ao Claude Code, instale os pacotes certos. O conjunto base cobre ESLint, TypeScript, React, Hooks, acessibilidade e ordenação de imports. Adicione os pacotes Astro apenas quando o projeto tiver arquivos .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
# Apenas para projetos Astro
npm i -D eslint-plugin-astro astro-eslint-parser
No package.json, separe correção local de verificação em CI. lint:fix serve para limpeza local. lint e typecheck são os comandos que o CI deve executar. --max-warnings=0 transforma warnings em falha; em projetos antigos, ative depois da primeira rodada de limpeza.
{
"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 não deve parar depois de escrever o arquivo. Ele precisa executar a mesma cadeia de verificação que a equipe vai usar.
package.json scripts
-> eslint.config.mjs
-> npm run lint:fix
-> npm run lint
-> npm run typecheck
-> CI gate
-> revisão do diff restante com Claude Code
Flat Config para TypeScript e React
Para uma aplicação React + TypeScript, este eslint.config.mjs é um bom ponto de partida. projectService: true ativa lint com informação de tipos. Isso é poderoso, mas tem custo, então saídas de build e pastas geradas precisam ser ignoradas logo no começo.
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"
}
}
);
O objetivo não é impor gosto de estilo, mas reduzir problemas reais. no-floating-promises encontra await esquecido. no-misused-promises reduz handlers async perigosos em JSX. consistent-type-imports deixa imports usados apenas como tipo mais claros. Testes podem ter exceções, mas a regra principal não deve enfraquecer o código de produção.
Astro precisa de tratamento próprio
Arquivos Astro misturam template, TypeScript frontmatter, chamadas de componentes e scripts de cliente. Se uma configuração pensada para React for aplicada diretamente a .astro, o ESLint pode falhar no parse antes de encontrar problemas úteis.
Em um site Astro de conteúdo, comece pelas configs Flat recomendadas do plugin e adicione um override para .astro. A regra astro/no-set-html-directive ajuda em blogs e documentações porque injeção de HTML é fácil de perder em revisão 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"
}
}
);
Não use ESLint como formatador universal. Deixe formatação para Prettier e mantenha ESLint focado em código inseguro, acessibilidade, erros com tipos e regras do projeto. O próximo passo natural é o guia de Prettier com Claude Code.
Três casos de uso práticos
O primeiro caso é um painel SaaS. Convites, cobrança e permissões dependem de código assíncrono. Nesse contexto, @typescript-eslint/no-floating-promises deve ser error, porque um await esquecido pode virar incidente de produção.
O segundo caso é um blog técnico Astro. As verificações de maior valor são parse de .astro, acessibilidade, estilos não usados e HTML inseguro. Como há muitas páginas geradas, ignorar dist/, .astro/ e saídas de build é obrigatório.
O terceiro caso é uma biblioteca TypeScript. APIs públicas precisam ser mais rígidas do que testes. Mantenha regras fortes para type imports, variáveis não usadas e exports, e relaxe any apenas em fixtures.
| Projeto | Regras para fortalecer | Onde relaxar |
|---|---|---|
| Painel React | Promises, Hooks, a11y | Mocks do Storybook |
| Blog Astro | .astro, HTML inseguro, CSS não usado | Conteúdo gerado |
| Biblioteca TypeScript | Type imports, variáveis, exports | Fixtures de teste |
Se quiser validar antes do commit, conecte com Husky + lint-staged. Em repositórios grandes, pre-commit deve ser rápido; lint pesado com tipos fica melhor no CI.
Coloque uma barreira no CI
Passar localmente não basta. CI deve executar os mesmos comandos e falhar com as mesmas regras. Para GitHub Actions, este workflow mínimo atende a maioria dos projetos.
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
Se um projeto existente tiver centenas de erros, não rode eslint --fix em tudo e envie um diff enorme. Agrupe por regra primeiro, depois peça ao Claude Code para corrigir pequenos lotes.
npm run lint
npm run lint:fix
npm run lint
npm run typecheck
npm run lint:debug
lint:debug mostra a configuração resolvida para um arquivo. Use quando uma regra React atingir .astro por engano ou quando uma exceção de testes vazar para código de produção.
Prompts para Claude Code
Modelo 1: nova instalação.
Adicione ESLint Flat Config a este repositório.
A stack é TypeScript + React. Leia primeiro package.json, tsconfig e qualquer configuração lint existente.
Crie eslint.config.mjs e continue até npm run lint e npm run typecheck passarem.
Evite autofixes que possam mudar comportamento; se forem necessários, explique o motivo antes.
Modelo 2: corrigir erros.
Vou colar a saída de npm run lint.
Agrupe os erros por regra, corrija primeiro as categorias de menor risco e mantenha o diff pequeno.
Use eslint-disable apenas como último recurso. Se usar, adicione uma razão de uma linha.
Depois execute npm run lint e npm run typecheck.
Modelo 3: suporte Astro.
Revise a configuração ESLint deste site Astro.
Separe as regras para .astro, .ts e .tsx. Use a configuração Flat recomendada de eslint-plugin-astro.
Defina astro/no-set-html-directive como error e confirme que regras React não se aplicam por engano ao arquivo .astro inteiro.
Modelo 4: falha no CI.
O job de lint no GitHub Actions está falhando.
Compare as versões locais e do CI de Node, npm, ESLint e plugins.
Crie um comando de reprodução e separe a solução em mudança de config, atualização de dependência ou mudança de código.
Aplique o menor diff seguro.
Claude Code precisa de arquivos para ler, comandos para executar e limites claros. “Corrija lint” é fraco. “Não enfraqueça regras de produção e prove com estes comandos” é muito melhor.
Armadilhas comuns
A primeira armadilha é copiar uma cadeia antiga de extends do .eslintrc para Flat Config. O formato é diferente. Se uma config compartilhada antiga for necessária, avalie compatibilidade, mas prefira exemplos Flat da documentação do plugin.
A segunda armadilha é aplicar lint com tipos a todos os arquivos. projectService: true é poderoso, mas bundles, saídas geradas e builds deixam CI lento. Defina ignores antes de ajustar regras.
A terceira armadilha é aceitar um diff gigante de autofix. Ordenação de imports, type imports, variáveis não usadas e formatação podem esconder mudanças reais. Masa costuma dividir a primeira adoção por Promises, imports e regras do framework.
A quarta armadilha é manter warnings para sempre. Warning que nunca bloqueia vira ruído. Use error para regra de equipe, warn para fase temporária de aprendizado e remova regras de baixo sinal.
A quinta armadilha é não explicar intenção ao Claude Code. Diga se acessibilidade é crítica, se fixtures podem usar any ou se APIs públicas precisam ser rígidas. Essas restrições geram uma configuração melhor do que recomendações genéricas.
Resumo
ESLint Flat Config deixa o alcance das regras mais visível porque a configuração do projeto fica em um só lugar. Claude Code é útil não apenas para gerar esse arquivo, mas para ler a codebase, executar verificações e ajustar sem enfraquecer padrões importantes.
Comece pela base correta para React/TypeScript ou Astro. Adicione npm run lint e npm run typecheck ao CI. Depois use prompts explícitos e revise manualmente qualquer eslint-disable ou diff grande de --fix.
Para completar o fluxo, combine com Prettier e Husky + lint-staged. Se precisar de prompts reutilizáveis e checklists de adoção, a página de produtos ClaudeCodeLab reúne guias e consultoria.
Resultado testado na prática
Masa testou esta configuração em um pequeno painel React e em um starter de blog Astro. A primeira execução encontrou ruído de ordem de imports e várias Promises sem tratamento. Um único diff de eslint --fix foi difícil de revisar, então separar Promises, imports e regras de segurança Astro funcionou melhor. O fluxo mais repetível foi fixar npm run lint e npm run typecheck no CI, colar os logs de falha no Claude Code e pedir correções pequenas com comandos de prova.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.
Artigos relacionados
Escada de segurança de permissões no Claude Code
Amplie de read-only para edições limitadas, comandos de prova e deploy checks sem perder controle.
Claude Code Small PR Proof Pack: pequenas mudanças fáceis de revisar
Um pacote de prova para PRs do Claude Code: diff, checks, URL pública, CTA e rollback.
Gate de revisão antes do commit com Claude Code
Revisão antes do commit com Claude Code: diff, build, URL pública, Gumroad, consultoria, testes e arquivos fora do escopo.