Eu perdi uma tarde inteira debugando um bug que não existia.
O problema? O Claude Code estava rodando com as variáveis de ambiente do projeto anterior. Eu tinha feito cd para outro repositório, mas o ambiente não acompanhou. A API apontava para staging enquanto eu jurava que estava em produção. O banco era outro. O token era de outro cliente.
Se você tem mais de um projeto na sua software house — e eu sei que você tem — já passou por isso. Talvez não com IA, mas com aquele dev júnior que rodou o script no ambiente errado. Ou com você mesmo às 23h tentando entregar antes do deploy de sexta.
A boa notícia: desde a versão 2.1.83, o Claude Code resolve isso com dois hooks que a maioria dos devs ainda não conhece. CwdChanged e FileChanged — o sistema de environment reativo que faz o Claude Code se adaptar automaticamente ao contexto.
O que são CwdChanged e FileChanged
Hooks no Claude Code são comandos que executam automaticamente em momentos específicos do ciclo de vida da ferramenta. Se você acompanha o blog, já falamos sobre HTTP Hooks para controle centralizado, StopFailure como alarme de incêndio e Conditional Hooks if para filtragem cirúrgica.
CwdChanged e FileChanged são diferentes dos hooks que controlam ferramentas. Eles não bloqueiam nem aprovam nada. Eles reagem ao ambiente — e é isso que os torna poderosos.
CwdChanged — reage quando o diretório muda
Dispara toda vez que o Claude Code muda de diretório de trabalho. Se o Claude executa um cd ../outro-projeto, o hook roda imediatamente. Você recebe o diretório anterior e o novo:
{
"hook_event_name": "CwdChanged",
"cwd": "/home/dev/projeto-b",
"previous_cwd": "/home/dev/projeto-a"
}
Não tem matcher — sempre dispara em qualquer mudança de diretório. É intencional. Mudança de diretório é um sinal forte de que o contexto mudou.
FileChanged — reage quando um arquivo muda no disco
Dispara quando um arquivo monitorado é criado, modificado ou deletado. Você escolhe quais arquivos monitorar pelo matcher:
{
"hooks": {
"FileChanged": [
{
"matcher": ".envrc|.env|.tool-versions",
"hooks": [
{
"type": "command",
"command": "/path/to/reload-env.sh"
}
]
}
]
}
}
O hook recebe o caminho completo do arquivo e o tipo de mudança (created, modified ou deleted). Se o Claude editou seu .env ou se você mudou manualmente — o hook pega.
Como funciona na prática
O segredo desses dois hooks está em uma variável de ambiente que a maioria dos devs desconhece: CLAUDE_ENV_FILE.
Quando um hook CwdChanged ou FileChanged roda, ele tem acesso a essa variável. É um caminho para um arquivo temporário que o Claude Code lê antes de cada comando Bash. Qualquer variável que você escrever nesse arquivo persiste para todos os comandos subsequentes da sessão.
O setup que toda software house deveria ter
Se sua equipe já usa direnv (e se não usa, deveria), a integração é uma linha:
{
"hooks": {
"CwdChanged": [
{
"hooks": [
{
"type": "command",
"command": "direnv export bash >> \"$CLAUDE_ENV_FILE\""
}
]
}
]
}
}
O que acontece: toda vez que o Claude muda de diretório, o direnv exporta as variáveis corretas daquele diretório e grava no CLAUDE_ENV_FILE. O próximo comando Bash que o Claude rodar já usa o ambiente certo.
Para projetos sem direnv
Se você não usa direnv mas tem .env por projeto, combina CwdChanged com FileChanged:
{
"hooks": {
"CwdChanged": [
{
"hooks": [
{
"type": "command",
"command": "if [ -f \"$PWD/.env\" ] && [ -n \"$CLAUDE_ENV_FILE\" ]; then cat \"$PWD/.env\" >> \"$CLAUDE_ENV_FILE\"; fi"
}
]
}
],
"FileChanged": [
{
"matcher": ".env|.envrc",
"hooks": [
{
"type": "command",
"command": "if [ -n \"$CLAUDE_ENV_FILE\" ]; then cat \"$(jq -r '.file_path' < /dev/stdin)\" >> \"$CLAUDE_ENV_FILE\"; fi"
}
]
}
]
}
}
Agora o Claude carrega o .env ao entrar num diretório e recarrega se alguém modificar o arquivo durante a sessão.
Monorepos: o cenário onde isso brilha
Na minha experiência com 300+ software houses, a maioria dos projetos modernos são monorepos ou multi-repos com contextos diferentes. Um repositório com:
/
├── apps/
│ ├── api/ → Node 20, DATABASE_URL=postgres://prod
│ ├── admin/ → Node 18, API_URL=http://localhost:3001
│ └── mobile-bff/ → Node 20, API_URL=http://localhost:3000
├── packages/
│ └── shared/ → sem variáveis específicas
└── infra/
└── terraform/ → AWS_PROFILE=production
Cada diretório tem seu próprio .env, sua versão de Node, suas credenciais. Sem CwdChanged, o Claude usa as variáveis do diretório onde você iniciou a sessão — para tudo. Com CwdChanged, ele se adapta a cada contexto automaticamente.
Por que isso importa para sua Software House
O custo invisível do .env errado
Quantas horas sua equipe já perdeu debugando problemas que eram, na verdade, variáveis de ambiente erradas? Na minha experiência, esse é um dos bugs mais frustrantes porque:
- Não aparece no código — o código está correto, o ambiente que está errado
- Não aparece no log — porque o log mostra que a operação executou, só no banco/API/serviço errado
- Não é reproduzível por todos — porque cada dev tem um setup ligeiramente diferente
Um dado que me chocou: 96% das organizações sofrem com secrets sprawl — credenciais e configurações espalhadas por repositórios, arquivos de configuração e scripts de deploy sem controle centralizado. E 88% dos data breaches envolvem credenciais comprometidas.
CwdChanged e FileChanged não resolvem security diretamente, mas resolvem o problema raiz: garantir que o ambiente correto esteja ativo no momento correto.
Para times que usam Claude Code em automação
Se sua software house já usa Claude Code em pipelines — com o modo --bare ou headless — os hooks de environment management são ainda mais críticos. Um agent que roda tarefas em múltiplos diretórios precisa ter o ambiente correto em cada um.
Cenários reais:
- Agent de code review que navega entre packages de um monorepo e precisa rodar testes com variáveis diferentes para cada um
- Agent de migração que precisa acessar bancos diferentes conforme o diretório do microserviço
- Agent de deploy que alterna entre ambientes staging/production conforme o diretório
O watchPaths: FileChanged dinâmico
Um detalhe que pouca gente sabe: o CwdChanged pode retornar watchPaths no stdout para configurar dinamicamente quais arquivos o FileChanged deve monitorar. Ou seja, ao mudar de diretório, você pode dizer “agora monitore esses arquivos específicos deste projeto”.
Isso é poderoso para monorepos onde cada subprojeto tem arquivos de configuração com nomes diferentes.
O que torna esses hooks especiais
Diferente dos hooks de ferramentas (PreToolUse, PostToolUse), CwdChanged e FileChanged não têm decision control. Eles não bloqueiam nem aprovam nada. Rodam puramente por efeitos colaterais — e é exatamente o que você quer para environment management.
Essa distinção arquitetural é importante:
- Hooks de ferramenta: “Posso executar esse comando?” → decisão
- Hooks de ambiente: “O contexto mudou” → adaptação
É a diferença entre um guarda e um sensor. O guarda decide se você passa. O sensor ajusta a temperatura quando você entra na sala.
Comparação: antes e depois
| Cenário | Sem hooks | Com CwdChanged/FileChanged |
|---|---|---|
| — | — | — |
cd para outro projeto |
Variáveis antigas persistem | Environment recarregado automaticamente |
.env editado manualmente |
Claude não percebe | FileChanged recarrega instantaneamente |
| Monorepo com 5 services | Mesmo ambiente para todos | Ambiente correto por diretório |
| Agent navegando entre repos | Bugs fantasma por variáveis erradas | Zero intervenção manual |
| direnv já configurado | Não funciona no Claude Code | Integração nativa com 1 linha |
O que eu penso
Na minha experiência mentorando mais de 300 software houses, environment management é um daqueles problemas que todo mundo tem mas ninguém resolve direito. Cada dev tem seu jeitinho, cada projeto tem sua convenção, e quando a IA entra no meio — rodando comandos em nome do dev — o problema multiplica.
CwdChanged e FileChanged são elegantes porque não inventam nada novo. Eles se plugam no que já existe: direnv, .env files, scripts de setup. A abordagem do Claude Code aqui é reativa, não prescritiva. Ele não te obriga a mudar seu workflow — ele se adapta ao seu workflow.
Se sua software house usa Claude Code para qualquer coisa além de perguntas simples, configure esses hooks. Leva 5 minutos. Economiza horas de debug por mês.
Como configurar em 5 minutos
- Abra
~/.claude/settings.json(global) ou.claude/settings.json(por projeto) - Adicione o hook CwdChanged com direnv ou com leitura de
.env - Adicione o hook FileChanged monitorando
.env,.envrc,.tool-versions - Teste: abra o Claude Code, mude de diretório, e verifique com
echo $MINHA_VARIAVEL
Se quiser ir além, combine com os Conditional Hooks if para filtrar quando os hooks devem processar variáveis sensíveis.
—
Se você quer implementar esse nível de automação inteligente na sua software house, com IA que realmente entende o contexto de cada projeto, a hora é agora. As ferramentas estão prontas — falta só configurar.
Sou Thulio, mentoro 300+ SHs desde 2016.




