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

  1. Claude Code instalado e autenticado no projeto.
  2. Um CLAUDE.md com stack, comandos e regras de domínio.
  3. Permissões que liberam testes e lint sem perguntar, pedem confirmação para migrations e bloqueiam leitura de segredos e comandos destrutivos.
  4. Um hook que formata com Pint e roda PHPStan a cada arquivo PHP editado, devolvendo os erros para o próprio agente corrigir.
  5. Os comandos /teste e /revisar, versionados no repositório.
  6. 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).
  • jq instalado (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:

  1. 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.
  2. Pedir confirmação no que muda estado. Instalar pacote e rodar migration passam por você.
  3. Bloquear o irreversível. migrate:fresh e db:wipe apagam o banco local (e, com um .env errado, outro banco). git push fica 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

  1. 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.
  2. 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 o deny em cat, e por isso o .env local deve ter só credenciais de sandbox. A proteção real é não ter segredo de produção na sua máquina.
  3. .env.example bloqueado junto. A regra Read(./.env.*) também pega o .env.example. Se o agente precisa dele para saber quais variáveis existem, documente as variáveis no CLAUDE.md ou troque por regras explícitas (.env.testing, .env.staging).
  4. Hook que não dispara. Quase sempre é falta de chmod +x, jq não instalado ou caminho relativo. Rode o teste com echo do passo 4; se funcionar fora, o problema está no matcher ou no JSON do settings.
  5. PHPStan lento a cada edição. Em projetos grandes, analisar a cada arquivo atrasa o ciclo. Mantenha o Pint no PostToolUse e mova o PHPStan para o evento Stop, que roda quando o agente termina a resposta, analisando os arquivos alterados no git diff --name-only.
  6. Sessão longa com contexto contaminado. Depois de uma tarefa grande, o agente carrega decisões antigas para a próxima. Use /clear entre 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.