# Como configurar o Claude Code em projetos Laravel: CLAUDE.md, hooks e comandos

> Passo a passo para deixar o Claude Code útil num projeto Laravel: CLAUDE.md enxuto, permissões que protegem o .env, hook com Pint e PHPStan e comandos para testes e revisão.

Por Lucas Roberto · IA · publicado em 2026-10-10 · 9 min de leitura
Versão web: https://lucasroberto.com/blog/como-configurar-o-claude-code-em-projetos-laravel-claudemd-hooks-e-comandos

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.

```bash
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:

```bash
composer require --dev larastan/larastan
```

```yaml
# 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.

```markdown
# 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](/blog/como-evitar-race-condition-no-saldo-da-conta-digital-com-laravel-e-postgresql), e a de `afterCommit` vem do [bug silencioso de jobs disparados dentro de transação](/blog/jobs-disparados-dentro-de-transacao-o-bug-silencioso-do-aftercommit-no-laravel). 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.

```json
{
  "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:

```bash
#!/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
```

```bash
chmod +x .claude/hooks/php-quality.sh
```

E registre no mesmo `.claude/settings.json`, ao lado de `permissions`:

```json
{
  "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:

```bash
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.

```markdown
---
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](/blog/como-testar-codigo-que-usa-llm-no-laravel-httpfake-respostas-gravadas-e-evals).

## 6. Como usar o Claude Code para revisar o diff antes do pull request?

Crie `.claude/commands/revisar.md`:

```markdown
---
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:

```bash
#!/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."
```

```bash
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.

---

Lucas Roberto é desenvolvedor back-end e fundador da Granpag. Mais textos: https://lucasroberto.com/blog
