voltar

Migrando de Husky para Lefthook

Recentemente precisei revisitar a forma como estávamos gerenciando os Git hooks em um dos projetos do time. Nada estava exatamente “quebrado”. O Husky estava funcionando, os hooks rodavam, o lint acontecia antes do commit e os testes antes do push. Mas tinham dois pontos incomodando: o tempo de execução e ajustes específicos para funcionar em windows, linux e mac.

Pre-commits começando a demorar mais do que deveriam, scripts rodando de forma sequencial e pequenas esperas que, no dia a dia, acabam se acumulando. Não era um problema crítico, mas era aquele tipo de fricção que todo desenvolvedor percebe: você faz um commit pequeno e fica alguns segundos olhando para o terminal esperando os hooks terminarem.

Foi aí que comecei a investigar alternativas para melhorar esse fluxo. Durante essa busca, encontrei o Lefthook, uma ferramenta para gerenciamento de Git hooks escrita em Go, com foco em performance e execução paralela.

Resolvi então fazer um experimento prático: migrar a configuração do projeto de Husky para Lefthook, medir os impactos e entender se a mudança realmente valeria a pena.

Este post mostra exatamente esse processo: o que motivou a mudança, como foi feita a migração e quais foram os resultados na prática.

1. Melhor Performance

  • Lefthook é mais rápido: Lefthook é escrito em Go, uma linguagem compilada e eficiente, o que o torna significativamente mais rápido que o Husky, que é baseado em JavaScript. Isso é especialmente notável em projetos grandes com múltiplos hooks, onde o tempo de execução dos hooks pode impactar a produtividade.

  • Execução paralela de hooks: Lefthook suporta a execução paralela dos hooks, permitindo que várias tarefas rodem simultaneamente, reduzindo o tempo total de pre-commit ou pre-push. Husky executa hooks sequencialmente, o que pode aumentar o tempo de espera quando há muitos scripts para rodar.

2. Configuração Mais Simples e Flexível

  • Configuração via YAML: Lefthook utiliza um arquivo de configuração YAML (lefthook.yml), que é mais legível e flexível para definir hooks complexos e múltiplos comandos. Husky usa configuração no package.json ou scripts que podem ficar confusos em projetos maiores.

  • Independência do Node.js: Lefthook é agnóstico em relação à linguagem, funcionando bem em projetos que não são baseados em JavaScript/Node.js, enquanto Husky está fortemente integrado ao ecossistema Node.js. Isso torna Lefthook uma escolha melhor para projetos multi-linguagem ou que usam outras stacks.

  • Manutenção do package.json mais limpa: Lefthook não adiciona dependências ou scripts extras no package.json, mantendo o arquivo mais organizado, o que facilita o gerenciamento em equipes e ambientes de CI/CD.

3. Facilidade na Migração e Uso

  • A migração do Husky para Lefthook é simples e rápida, podendo ser feita com poucos comandos, como desinstalar Husky e instalar Lefthook, além de mover a configuração para o arquivo YAML, sem grande impacto no fluxo atual.

  • Lefthook possui uma CLI amigável para gerenciar e testar hooks manualmente, o que ajuda na configuração e depuração.

4. Suporte Multiplataforma e Comunidade

  • Lefthook oferece suporte nativo a Windows, Linux e macOS, garantindo compatibilidade em diferentes ambientes de desenvolvimento.

  • Embora Husky tenha uma comunidade maior atualmente, Lefthook vem ganhando espaço e possui documentação clara e atualizações regulares, com suporte ativo no GitHub

Comparativo Técnico: Husky vs Lefthook

AspectoHuskyLefthook
LinguagemJavaScript (Node.js)Go (agnóstico)
PerformanceSequencial, mais lentoParalelo, mais rápido
ConfiguraçãoJSON no package.jsonYAML (mais legível e flexível)
Suporte a múltiplas linguagensLimitado ao Node.jsCompleto, multi-stack
Suporte multiplataformaSimSim
Impacto no package.jsonAdiciona dependênciasMantém package.json limpo
Integração com CI/CDRequer configuração manualAutomatizado e padronizável
Facilidade de migraçãoN/ASimples e rápida
Suporte a monoreposLimitadoNativo
ComunidadeGrande e consolidadaMenor, mas crescente
Curva de aprendizadoMédiaBaixa

Comparação prática em um projeto demo

  • Lefthook executando todos os hooks em 10.72seg
    • O Eslint ainda é o que leva mais tempo e há espaço para otimização e um futuro ajuste. Talvez implementar cache para eslint448118308-10e777ff-e5a5-4bfd-9143-6c91f6d5664d.png
  • Husky executando apenas lint em 14.96s. Capture-2026-03-05-121153.png

Comparativo de Performance na prática

Durante testes no projeto, observamos uma diferença significativa no tempo de execução dos Git hooks entre Husky e Lefthook:

FerramentaHooks executadosTempo total
HuskyApenas Lint14.96s
LefthookLint + Prettier + Console.log10.72s

Mesmo executando mais tarefas, o Lefthook foi 28.3% mais rápido que o Husky.

Essa diferença representa um ganho de 4.24 segundos em um cenário com apenas 3 arquivos modificados. Em cenários com mais arquivos ou em times maiores, o impacto acumulado pode ser ainda mais significativo.

Como o Lefthook executa os hooks em paralelo, o tempo total tende a crescer menos conforme aumenta a quantidade de arquivos, proporcionando melhor escalabilidade e eficiência no fluxo de trabalho.

Benefícios Esperados

  • Redução significativa no tempo de execução dos hooks, aumentando a produtividade.

  • Configuração mais simples e organizada, facilitando a manutenção e onboarding de novos colaboradores.

  • Maior flexibilidade para projetos que utilizam múltiplas linguagens.

  • Arquivo package.json mais limpo e fácil de gerenciar.

Impactos e Riscos

  • Curva de aprendizado inicial para a equipe se familiarizar com Lefthook.

  • Necessidade de atualização dos scripts e configuração dos hooks.

  • Risco mínimo de incompatibilidade, mitigado por testes prévios.

Guia de migração

1. Configuração do Lefthook (lefthook.yml)

  • Configuração otimizada para o projeto
  • Hooks configurados: commit-msg, pre-commit, pre-push
  • Execução paralela habilitada para melhor performance
  • Auto-staging de arquivos corrigidos (stage_fixed: true)
  • Verificação de console.log esquecidos

2. Package.json

  • Script prepare alterado de husky install para lefthook install

3. Commitlint Configuration

  • Configuração simplificada com regras padrão do conventional commits

4. Utilização do diretório .husky

Os arquivos referentes aos git hooks foram gerados automaticamente pelo lefthook reaproveitando o diretório .husky por padrão da ferramenta.

Comandos Executados nos Hooks

commit-msg

  • yarn commitlint --edit .git/COMMIT_EDITMSG

pre-commit (execução paralela)

  • lint: yarn eslint {staged_files} --fix
    • Arquivos: {src,apps,libs,test}/**/*.{ts,tsx}
    • Auto-staging habilitado
  • format: yarn prettier --write {staged_files}
    • Arquivos: {src,apps,libs,test}/**/*.{ts,tsx}
    • Auto-staging habilitado
  • no-console: Verificação de console.log esquecidos
    • Arquivos: {src,apps,libs,test}/**/*.{ts,tsx}
    • Bloqueia commit se encontrar console.

pre-push (execução paralela)

  • test: yarn test:cov:local

Otimizações Implementadas

Performance

  • Execução paralela: parallel: true nos hooks pre-commit e pre-push
  • Auto-staging: stage_fixed: true para lint e format
  • Globs específicos: Apenas arquivos TypeScript/TSX relevantes

Qualidade de Código

  • ESLint com auto-fix: Corrige problemas automaticamente
  • Prettier: Formatação consistente
  • Console detection: Previne console.log em produção
  • Testes com coverage: Garante qualidade antes do push

Instalação

Para instalar os hooks do Lefthook:

yarn lefthook install

Verificação

Para verificar se os hooks estão funcionando:

# Testar commitlint
echo "feat: test commit message" | yarn commitlint

# Testar hooks individualmente
yarn lefthook run commit-msg
yarn lefthook run pre-commit
yarn lefthook run pre-push

# Verificar configuração
yarn lefthook version

Regras do Commitlint

O projeto agora usa as regras padrão do conventional commits:

  • Tipos permitidos: feat, fix, docs, style, refactor, perf, test, chore, ci, build, revert
  • Header máximo: 140 caracteres
  • Body máximo por linha: 280 caracteres

Conclusão

No fim das contas, essa migração começou como um experimento simples: entender se existia uma forma mais eficiente de executar os Git hooks no projeto.

A troca do Husky pelo Lefthook acabou trazendo alguns benefícios claros. A execução paralela reduz significativamente o tempo total dos hooks, a configuração em YAML deixa a estrutura mais organizada e a independência do Node.js torna a ferramenta mais flexível para diferentes stacks.

Na prática, a diferença mais perceptível está na experiência do desenvolvedor. Quando os hooks executam mais rápido, o fluxo de commit fica mais fluido e a fricção no dia a dia diminui. Pode parecer um ganho pequeno isoladamente, mas esse tipo de melhoria incremental no tooling impacta diretamente a produtividade ao longo do tempo.

O Husky continua sendo uma ferramenta sólida e amplamente utilizada no ecossistema JavaScript. Mas para cenários onde performance, paralelismo e organização da configuração são prioridades, o Lefthook se mostrou uma alternativa bastante interessante.