Para o Claude Code render num projeto Laravel, ele precisa de quatro coisas: um CLAUDE.md curto com as regras que não estão no código, permissões em .claude/settings.json que bloqueiam o que é perigoso, um hook que roda Pint e PHPStan depois de cada edição e comandos personalizados para tarefas repetidas, como escrever testes e revisar o diff. Com isso, o agente escreve código no padrão do projeto e você para de corrigir as mesmas coisas em toda sessão.
Em sistema financeiro isso pesa mais. Um agente que não sabe que valor é inteiro em centavos, que job dentro de transação precisa de afterCommit ou que nunca deve ler o .env de homologação causa estrago rápido. O que segue é a configuração que eu uso como base nos meus projetos Laravel.
O que você vai ter funcionando no final
- Claude Code instalado e autenticado no projeto.
- Um
CLAUDE.mdcom stack, comandos e regras de domínio. - Permissões que liberam testes e lint sem perguntar, pedem confirmação para migrations e bloqueiam leitura de segredos e comandos destrutivos.
- Um hook que formata com Pint e roda PHPStan a cada arquivo PHP editado, devolvendo os erros para o próprio agente corrigir.
- Os comandos
/testee/revisar, versionados no repositório. - Um script de revisão headless antes do push.
Pré-requisitos:
- Laravel 11 ou 12 com PHP 8.2+.
- Node.js 18+ (para instalar o Claude Code via npm).
- Pest ou PHPUnit, Laravel Pint (já vem no skeleton) e, de preferência, Larastan (PHPStan com regras do Laravel).
jqinstalado (o hook usa para ler o JSON que o Claude Code manda).- Uma assinatura Claude (Pro ou Max) ou uma chave de API do Anthropic Console.
1. Como instalar e autenticar o Claude Code?
O Claude Code é o agente de terminal da Anthropic: ele lê arquivos, edita código e executa comandos no seu projeto, sempre dentro das permissões que você define.
npm install -g @anthropic-ai/claude-code cd ~/projetos/minha-app-laravel claude
Na primeira execução ele pede login. Você escolhe entre a conta Claude (assinatura) ou cobrança por uso via API. Para quem usa todo dia, a assinatura costuma ser mais previsível; para uso em CI, a chave de API é o caminho.
Se você ainda não usa Larastan, instale agora, porque o hook do passo 4 depende dele:
composer require --dev larastan/larastan
# phpstan.neon includes: - vendor/larastan/larastan/extension.neon parameters: paths: - app/ level: 5
2. Como escrever um CLAUDE.md que o agente realmente segue?
O CLAUDE.md é um arquivo Markdown na raiz do projeto que o Claude Code carrega no contexto de toda sessão. Dentro do claude, rode:
/init
Ele gera um rascunho analisando o repositório. O rascunho costuma vir longo e descritivo demais. Eu apago quase tudo e deixo só o que o agente não consegue deduzir lendo o código: comandos, convenções e regras de domínio. Cada linha desse arquivo consome contexto em todas as sessões, então ele precisa ser curto.
# Projeto API Laravel 12 + PostgreSQL 16 + Redis (filas com Horizon). Testes com Pest. ## Comandos - Testes: `php artisan test --parallel` - Um arquivo: `vendor/bin/pest tests/Feature/Payments/RefundTest.php` - Lint: `vendor/bin/pint` | Análise: `vendor/bin/phpstan analyse` ## Regras de domínio (não negociáveis) - Dinheiro é sempre inteiro em centavos (`bigint`). Nunca float, nunca decimal em PHP. - Escrita em saldo usa `DB::transaction` + `lockForUpdate()` na conta. - Job ou evento disparado dentro de transação usa `afterCommit()`. - Webhook é idempotente: grava o id do evento com índice único antes de processar. - Nunca altere migration existente. Crie uma nova. ## Testes - `RefreshDatabase` em testes de feature. - Toda chamada HTTP externa usa `Http::fake()`. Teste que bate em API real é bug. - Nunca ajuste uma asserção para o teste passar. Se o teste falhar, explique o motivo.
As regras de domínio são as que mais economizam retrabalho. Sem elas, o agente escreve o código "normal" de Laravel, que funciona no CRUD e quebra em dinheiro. A regra de lockForUpdate vem do problema que descrevi em como evitar race condition no saldo da conta digital, e a de afterCommit vem do bug silencioso de jobs disparados dentro de transação. Escreva a regra em uma linha, no imperativo, e deixe o porquê para a documentação.
Preferências pessoais (idioma das respostas, estilo de commit) ficam em ~/.claude/CLAUDE.md, que vale para todos os projetos e não vai para o repositório.
3. Como configurar permissões para o Claude Code não ler o .env nem rodar comando destrutivo?
As permissões ficam em .claude/settings.json (versionado, vale para o time) e .claude/settings.local.json (pessoal, fora do Git). As regras têm três níveis: allow executa sem perguntar, ask sempre pede confirmação e deny bloqueia. Quando uma regra de deny casa, ela vence as outras.
{ "permissions": { "allow": [ "Bash(php artisan test:*)", "Bash(vendor/bin/pest:*)", "Bash(vendor/bin/pint:*)", "Bash(vendor/bin/phpstan:*)", "Bash(git status)", "Bash(git diff:*)", "Bash(git log:*)" ], "ask": [ "Bash(composer require:*)", "Bash(php artisan migrate:*)" ], "deny": [ "Read(./.env)", "Read(./.env.*)", "Bash(cat .env:*)", "Bash(php artisan migrate:fresh:*)", "Bash(php artisan db:wipe:*)", "Bash(git push:*)", "Bash(curl:*)" ] } }
O raciocínio:
- Liberar o ciclo de feedback. Testes, Pint, PHPStan e leitura do Git rodam sem confirmação. Se o agente precisa pedir permissão para rodar teste, você vai aprovar no automático e a permissão perde o sentido.
- Pedir confirmação no que muda estado. Instalar pacote e rodar migration passam por você.
- Bloquear o irreversível.
migrate:freshedb:wipeapagam o banco local (e, com um.enverrado, outro banco).git pushfica com você.curlé bloqueado para o agente não sair chamando API de gateway com credencial de sandbox.
4. Como rodar Pint e PHPStan automaticamente a cada edição do Claude Code?
Hooks são comandos de shell que o Claude Code executa em eventos do ciclo dele. O PostToolUse roda depois que uma ferramenta termina; com o matcher certo, ele dispara a cada arquivo editado ou criado. O hook recebe um JSON no stdin com os dados da ferramenta, incluindo tool_input.file_path.
Crie o script:
#!/usr/bin/env bash # .claude/hooks/php-quality.sh set -uo pipefail file=$(jq -r '.tool_input.file_path // empty') [[ "$file" == *.php ]] || exit 0 cd "$CLAUDE_PROJECT_DIR" || exit 0 vendor/bin/pint "$file" --quiet if ! out=$(vendor/bin/phpstan analyse "$file" --no-progress --error-format=raw --memory-limit=1G 2>&1); then echo "PHPStan encontrou problemas em $file:" >&2 echo "$out" >&2 exit 2 fi exit 0
chmod +x .claude/hooks/php-quality.sh
E registre no mesmo .claude/settings.json, ao lado de permissions:
{ "hooks": { "PostToolUse": [ { "matcher": "Edit|MultiEdit|Write", "hooks": [ { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/php-quality.sh" } ] } ] } }
O detalhe que faz diferença é o exit 2. Com esse código de saída, o stderr volta para o Claude Code como feedback, e ele corrige o erro de tipo na sequência, sem você intervir. Pint formata em silêncio; o agente nem precisa saber.
Para testar sem abrir o Claude Code, simule o JSON:
echo '{"tool_input":{"file_path":"app/Models/User.php"}}' \ | CLAUDE_PROJECT_DIR=$(pwd) .claude/hooks/php-quality.sh; echo "exit: $?"
5. Como criar um comando para o Claude Code escrever testes Pest?
Comandos personalizados são arquivos Markdown em .claude/commands/. O nome do arquivo vira o comando, e $ARGUMENTS é substituído pelo que você digitar depois dele.
--- description: Escreve testes Pest para uma classe do projeto argument-hint: <caminho da classe> --- Leia a classe em $ARGUMENTS e as classes que ela usa diretamente. 1. Antes de escrever código, liste os comportamentos que precisam de teste: caminho feliz, validações, erros de integração externa e casos de borda com valores (zero, um centavo, valor máximo, estorno parcial). 2. Espere minha confirmação da lista. 3. Escreva os testes em Pest seguindo os testes existentes em tests/Feature. 4. Use Http::fake() para toda chamada externa e Queue::fake() ou Event::fake() quando a classe disparar jobs ou eventos. 5. Rode apenas o arquivo novo com vendor/bin/pest. 6. Se um teste falhar, NÃO altere a asserção. Diga se o problema parece estar no teste ou na classe e pare.
Uso: /teste app/Services/Payments/RefundService.php.
O passo 2 é o mais importante. Revisar uma lista de dez comportamentos leva um minuto; revisar duzentas linhas de teste que cobrem o que não importa leva muito mais. E o passo 6 evita o pior vício de agente: fazer o teste passar ajustando a expectativa ao bug. Para classes que chamam LLM, o mesmo vale com as técnicas de Http::fake, respostas gravadas e evals para código que usa LLM.
6. Como usar o Claude Code para revisar o diff antes do pull request?
Crie .claude/commands/revisar.md:
--- description: Revisa o diff da branch atual contra a main --- Rode `git diff main...HEAD` e revise as mudanças. Procure, nesta ordem: 1. Valores monetários com float, decimal em PHP ou arredondamento implícito. 2. Escrita em saldo sem transação e lock. 3. Jobs/eventos dentro de transação sem afterCommit. 4. Webhooks ou jobs sem idempotência. 5. Queries N+1 e falta de índice em colunas novas usadas em WHERE. 6. Dados pessoais (CPF, e-mail, telefone) indo para log. 7. Código novo sem teste. Responda só com problemas encontrados, cada um com arquivo, linha e sugestão. Não elogie, não resuma o diff e não edite arquivos.
O "não edite arquivos" separa revisão de correção. Primeiro você lê os apontamentos e decide; depois pede a correção do que concordar.
7. Como rodar a revisão do Claude Code antes do push, sem abrir o terminal interativo?
O modo headless (claude -p) recebe um prompt, executa e imprime a resposta. Dá para mandar o diff pelo stdin:
#!/usr/bin/env bash # bin/ai-review set -euo pipefail diff=$(git diff origin/main...HEAD -- '*.php' 'database/**') if [[ -z "$diff" ]]; then echo "Nada para revisar." exit 0 fi echo "$diff" | claude -p "Revise este diff seguindo o checklist do arquivo .claude/commands/revisar.md (ignore a instrução de rodar git diff, o diff está no stdin). Responda só com problemas."
chmod +x bin/ai-review ./bin/ai-review
Eu deixo como script manual, não como hook de Git obrigatório. Revisão que bloqueia push por alucinação do modelo gera atrito e o time desativa em uma semana.
Erros comuns
- CLAUDE.md virou documentação. Arquivo de várias páginas dilui as regras que importam e gasta contexto em toda sessão. Se a regra está no código ou no PHPStan, tire do arquivo.
- Achar que
Read(./.env)protege os segredos. Ele bloqueia a ferramenta de leitura, mas o agente ainda pode chegar ao arquivo por outro comando de shell que você liberou. Por isso odenyemcat, e por isso o.envlocal deve ter só credenciais de sandbox. A proteção real é não ter segredo de produção na sua máquina. .env.examplebloqueado junto. A regraRead(./.env.*)também pega o.env.example. Se o agente precisa dele para saber quais variáveis existem, documente as variáveis noCLAUDE.mdou troque por regras explícitas (.env.testing,.env.staging).- Hook que não dispara. Quase sempre é falta de
chmod +x,jqnão instalado ou caminho relativo. Rode o teste comechodo passo 4; se funcionar fora, o problema está nomatcherou no JSON do settings. - PHPStan lento a cada edição. Em projetos grandes, analisar a cada arquivo atrasa o ciclo. Mantenha o Pint no
PostToolUsee mova o PHPStan para o eventoStop, que roda quando o agente termina a resposta, analisando os arquivos alterados nogit diff --name-only. - Sessão longa com contexto contaminado. Depois de uma tarefa grande, o agente carrega decisões antigas para a próxima. Use
/clearentre tarefas não relacionadas e o plan mode (Shift+Tab) para revisar o plano antes de qualquer edição em código de pagamento.
Por onde começar
Não configure tudo de uma vez. Comece pelas permissões do passo 3 e pelo bloco "Regras de domínio" do CLAUDE.md, que são os que evitam dano. Depois adicione o hook do Pint. Os comandos personalizados nascem naturalmente: toda vez que você digitar o mesmo prompt pela terceira vez, transforme em arquivo em .claude/commands/ e faça commit. Em poucas semanas o diretório .claude/ vira a documentação mais atualizada das convenções do projeto, porque é a que é usada todo dia.
Perguntas frequentes
O Claude Code funciona com a assinatura do Claude ou só com chave de API?
Funciona com os dois. Você pode logar com a conta Claude (planos Pro ou Max) ou usar cobrança por uso via Anthropic Console. Para CI e scripts automatizados, a chave de API é mais prática.
Devo commitar a pasta .claude no repositório?
Sim para settings.json, commands/ e hooks/, porque padronizam o time. O settings.local.json é pessoal e fica fora do Git.
O Claude Code envia meu código para a Anthropic?
Sim, o conteúdo que o agente lê é enviado para a API para ser processado. Por isso as regras de deny para segredos e a recomendação de não ter credencial de produção no ambiente local.
Dá para usar junto com o Cursor?
Dá. O Claude Code roda no terminal, inclusive no terminal integrado do Cursor ou do VS Code. Muita gente usa o editor para edições pontuais e o Claude Code para tarefas de vários arquivos.
A revisão com IA substitui code review humano?
Não. Ela pega bem os padrões do checklist (float em dinheiro, falta de lock, N+1), mas não sabe se a regra de negócio está certa. Use como primeira passada, antes de pedir revisão a outra pessoa.