📂 Localizacao: 3 niveis
Claude Code resolve settings em tres niveis com precedencia. Coloque no nivel certo.
📐 Hierarquia de settings
1. PROJECT: .claude/settings.json (no repo atual) 2. USER: ~/.claude/settings.json (voce, cross-project) 3. GLOBAL: /etc/claude/settings.json (admin, multi-user) PRECEDENCIA: project > user > global MERGE: arrays se concatenam; objetos fazem merge profundo. .claude/settings.local.json = local-only, nao versionado (gitignore)
💡 Regra de decisao
Identidade pessoal → user. Hooks de projeto especifico → project. Compliance da empresa → global. Experimentos → local.
🧱 Estrutura basica
O schema do settings.json e simples: chave 'hooks' com array por evento.
📐 Estrutura minima
{
"hooks": {
"SessionStart": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "~/.memory/hooks/session_start.sh"
}
]
}
]
}
}
Leitura:
- "SessionStart": nome do evento (case-sensitive)
- "matcher": "" = sempre dispara
- "type": "command" = executa comando bash
- "command": o que rodar⚠️ Case sensitive
SessionStart com S maiusculo. sessionstart nao funciona. Claude Code e rigoroso nos nomes de eventos.
🔐 Permissoes: allow/deny/ask
Hooks executam comandos bash com suas permissoes. Precisa de allowlist para comandos sensitivos.
🛡️ Quando permissoes importam
Claude Code pede permissao para executar hooks de commands que nao estao na allowlist.
- •allow: comandos que rodam sem perguntar. Seus scripts proprios.
- •deny: comandos bloqueados mesmo se Claude tentar. rm -rf, curl para dominios perigosos.
- •ask: pede confirmacao a cada execucao. Default para comandos novos.
- •Para hooks: adicione o path completo do script em 'allow'.
🎯 Matchers: filtragem condicional
Matcher diz quando o hook dispara. Nao so se dispara, mas sob qual condicao.
🎪 Tipos de matcher
Por evento:
- •'' (vazio): sempre dispara. Comum em SessionStart.
- •'Bash': so quando a tool chamada e Bash. Comum em PreToolUse.
- •'Write|Edit': regex para multiplos. Hooks de compliance.
- •Array de objetos: cada objeto tem seu matcher e seus commands. Permite logica diferente por condicao.
💡 Matcher em UserPromptSubmit
Voce pode criar matcher por keyword no prompt. Ex: matcher de 'deploy|infra' dispara hook que carrega infra.md. Trilha 4 mostra.
📜 Exemplo completo comentado
Um settings.json de producao, linha a linha.
📐 Exemplo real
{
"hooks": {
"SessionStart": [{
"matcher": "",
"hooks": [{ "type": "command",
"command": "$CLAUDE_PROJECT_DIR/hooks/start.sh" }]
}],
"PreCompact": [{
"matcher": "",
"hooks": [{ "type": "command",
"command": "$CLAUDE_PROJECT_DIR/hooks/compact.sh" }]
}],
"UserPromptSubmit": [{
"matcher": "",
"hooks": [{ "type": "command",
"command": "$CLAUDE_PROJECT_DIR/hooks/router.sh" }]
}],
"SessionEnd": [{
"matcher": "",
"hooks": [{ "type": "command",
"command": "nohup $CLAUDE_PROJECT_DIR/hooks/end.sh &" }]
}]
}
}💡 Variaveis uteis
$CLAUDE_PROJECT_DIR resolve para o cwd do projeto atual. Use em paths para portabilidade.
⚠️ Armadilhas comuns
Bugs de primeira hora que custam horas. Conheca para evitar.
✓ Fazer
- ✓Usar $CLAUDE_PROJECT_DIR ou ~ para paths
- ✓Testar JSON com jq antes de salvar
- ✓Dar +x nos scripts (chmod +x)
- ✓Logar stderr para debug
✗ Evitar
- ✗Path relativo sem raiz (nao resolve)
- ✗Trailing comma no JSON (invalida)
- ✗Script sem shebang (#!/usr/bin/env bash)
- ✗Stdout vazio em vez de {}
📝 Resumo do Modulo
Proximo:
3.4 — Payload: stdin, stdout, additionalContext