Configurar Husky + lint-staged com Claude Code: guia prático de pre-commit
Use Claude Code, Husky e lint-staged para rodar ESLint e Prettier antes de cada commit sem perder velocidade.
Claude Code consegue alterar muitos arquivos em uma única sessão. Isso ajuda em refactors, testes e ajustes de configuração, mas também aumenta o ruído da revisão. A pessoa revisora deveria focar em comportamento, arquitetura e riscos, não em imports sem uso, formatação inconsistente ou quebras de linha em Markdown.
Husky + lint-staged resolve uma parte objetiva desse problema. Um Git hook é um pequeno script executado pelo Git em um ponto do fluxo, como antes de criar um commit. Husky permite versionar esses hooks dentro do repositório. lint-staged executa comandos apenas nos arquivos que já estão preparados com git add, evitando varrer o projeto inteiro a cada commit. Hooks do Claude Code são outra camada: eles rodam dentro do ciclo de vida do Claude Code. São úteis como apoio, mas não substituem um Git hook que protege qualquer commit.
A meta não é criar um CI local pesado. O desenho que funciona melhor é: checks rápidos em pre-commit, validações médias em pre-push e verificação completa em CI.
Fluxo recomendado
Quando Claude Code muda vários arquivos, a automação precisa ser previsível. Primeiro o desenvolvedor escolhe o que vai entrar com git add; depois Husky chama lint-staged; então ESLint e Prettier atuam apenas nesses arquivos.
flowchart LR
A["Claude Code edita arquivos"] --> B["Desenvolvedor faz git add"]
B --> C["Husky pre-commit"]
C --> D["lint-staged"]
D --> E["ESLint / Prettier"]
E --> F["commit"]
C --> G["typecheck, testes e build ficam em pre-push ou CI"]
As referências oficiais usadas aqui são Husky Get started, lint-staged README, manual de Git hooks e Claude Code hooks reference. O detalhe prático é que Husky recomenda npx husky init, e lint-staged precisa de um hook pre-commit mais uma configuração de padrões de arquivos.
Configuração mínima
Se ESLint ou Prettier ainda não estão estáveis no projeto, comece pelo guia de ESLint com Claude Code e pelo guia de Prettier. Husky apenas dispara comandos; ele não conserta regras mal definidas.
Um prompt útil para Claude Code deve deixar claro o escopo:
Adicione Husky e lint-staged a este repositório Node.js/TypeScript.
O pre-commit deve processar apenas arquivos JS, TS, JSON, Markdown e CSS staged.
Rode ESLint com auto-fix e Prettier no pre-commit.
Não coloque typecheck, testes nem build no pre-commit; mova isso para pre-push ou CI.
No fim, liste os comandos de verificação manual.
Instalando manualmente:
npm install --save-dev husky lint-staged eslint prettier
npx husky init
npx husky init cria .husky/pre-commit e atualiza o script prepare no package.json. Troque o conteúdo do hook por:
#!/usr/bin/env sh
npx lint-staged
Depois adicione a configuração. Se já existirem scripts no package.json, faça merge das chaves em vez de substituir tudo.
{
"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"
]
}
}
Para testar, crie um arquivo com formatação ruim e prepare-o:
git add src/example.ts
npx lint-staged --debug
git commit -m "chore: verify pre-commit checks"
--debug mostra qual configuração foi carregada, quais arquivos casaram com cada glob e quais comandos rodaram. Se algo falhar, envie essa saída para Claude Code junto com a pergunta.
Configuração sustentável
Em repositórios maiores, prefiro mover a configuração para lint-staged.config.mjs. O package.json fica mais legível e podemos usar pequenas funções auxiliares. Este exemplo coloca aspas nos caminhos para reduzir problemas com nomes de arquivo que têm espaço.
// 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)}`,
};
Ao usar esse arquivo, remova a chave lint-staged de package.json. Duas fontes de verdade criam divergência e confundem tanto humanos quanto Claude Code.
Três casos de uso
Primeiro caso: uma aplicação TypeScript. Claude Code costuma alterar componentes, testes e utilitários juntos. ESLint com auto-fix e Prettier removem ruído antes da revisão. Typecheck completo precisa do contexto do projeto, então é melhor em pre-push ou CI.
Segundo caso: um site Astro ou Next.js com bastante conteúdo. MDX, JSON, CSS e TypeScript mudam ao mesmo tempo. lint-staged mantém o diff focado no conteúdo real, sem misturar revisão editorial com espaços e quebras de linha.
Terceiro caso: monorepo. Rodar todos os testes de todos os pacotes em pre-commit costuma ficar lento. Formate e aplique lint nos arquivos staged, depois deixe CI ou o task runner escolher os testes relevantes pelos caminhos alterados.
commit-msg e pre-push
Regras de mensagem de commit devem ficar em um hook separado. Para Conventional Commits, use 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"
Coloque esse shell em .husky/commit-msg. Para checks mais pesados, use .husky/pre-push:
#!/usr/bin/env sh
npm run validate
O script validate pode espelhar 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"
}
}
Armadilhas comuns
A maior armadilha é deixar pre-commit pesado demais. Se cada commit demora dois minutos, a equipe aprende a pular o hook. Se dura poucos segundos, ele vira hábito.
Outra armadilha é o partial staging. lint-staged olha para arquivos staged, mas o mesmo arquivo pode ter mudanças não staged. Para depurar, veja git status --short, git diff --staged e npx lint-staged --debug juntos.
Em equipes com Windows, macOS e Linux, finais de linha importam. Hooks do Husky são scripts shell, então LF é a opção mais segura.
* text=auto eol=lf
*.cmd text eol=crlf
*.bat text eol=crlf
Também evite || true. Isso esconde falhas e transforma a barreira de qualidade em enfeite. Peça ao Claude Code para reduzir o erro, mover tarefas lentas para pre-push ou documentar o comando de correção.
Resultado testado
Testei essa estrutura em um projeto TypeScript/Vite pequeno com formatação quebrada, import sem uso e problema de espaço em MDX. pre-commit ficou rápido porque processou apenas arquivos staged. npx lint-staged --debug deixou claro quais arquivos e comandos estavam envolvidos. Erros de tipo ficaram para npm run validate no pre-push, preservando o ritmo de commits sem perder a proteção final.
Resumo
Husky + lint-staged é uma proteção prática para fluxos com Claude Code. Mantenha pre-commit leve, mova verificações caras para pre-push ou CI e descreva essa separação nos prompts. Assim o hook vira um padrão de qualidade compartilhado, não um obstáculo local.
O próximo passo é reforçar as regras no guia de ESLint e padronizar formatação com o guia de Prettier.
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
Como pedir ao Claude Code para mexer em um único arquivo
Do desastre em que um 'deixa melhor' alterou 40 linhas nasceu um template de prompt que limita o escopo, valida e permite reverter.
Recuperar de negações de permissão no Claude Code sem enfraquecer guardrails
Transforme um comando negado em plano seguro com motivo, alternativa, provas e critérios de nova tentativa.
Claude Code Harness Smoke Test: prova de 15 minutos antes de confiar em um agente
Um smoke test para escopo, áreas bloqueadas, comandos de prova, URL pública e CTAs de receita no Claude Code.