Permissions — allow/deny, glob patterns, tool rules
TL;DR
Permissions controlam quais tool calls o Claude Code executa automaticamente vs. quais precisam de confirmação. A sintaxe é
"NomeTool(argumento)"no arrayallowoudenydesettings.json. Glob patterns com*funcionam para caminhos e argumentos de Bash. Deny sempre prevalece sobre allow.
O que é
Sem permissão configurada, cada tool call que o agente tenta fazer exige confirmação manual. Com permissões, você define quais ações são seguras o suficiente para rodar automaticamente — e quais jamais devem rodar sem revisão humana.
{
"permissions": {
"allow": ["Bash(npm test)", "Edit(*)"],
"deny": ["Bash(rm -rf *)"]
}
}Sintaxe geral
"NomeTool(padrão)"
- NomeTool: nome exato da tool (
Bash,Edit,Read,Write,WebFetch,WebSearch, etc.) - padrão: string que é comparada com o argumento da tool call
Para permitir uma tool sem restrição de argumento:
"Read(*)" // Qualquer leitura de arquivo
"Edit(*)" // Qualquer edição de arquivoBash — padrões de comando
Bash é a tool mais crítica de configurar, porque engloba todos os comandos shell.
Comandos exatos
"Bash(npm test)" // Apenas 'npm test' — não permite variações
"Bash(git status)"
"Bash(ls -la)"Glob com *
"Bash(npm test *)" // npm test e qualquer argumento depois
"Bash(npm run *)" // qualquer npm run <script>
"Bash(git *)" // qualquer subcomando git
"Bash(docker * ps)" // docker <algo> psCuidado com globs amplos
"Bash(git *)"permitegit push --force. Prefira listar os subcomandos específicos que você realmente usa.
Prefixo de comando
O padrão é verificado como prefixo da string do comando. "Bash(npm run)" permite npm run lint, npm run build, npm run test:watch.
Read/Edit/Write — padrões de caminho
Para tools de arquivo, o padrão é comparado com o caminho do arquivo.
"Read(*)" // Qualquer arquivo
"Edit(*)" // Qualquer arquivo
"Edit(src/*)" // Apenas arquivos em src/
"Edit(src/**/*.ts)" // TypeScript em qualquer subpasta de src/
"Write(tests/*)" // Escrever apenas em tests/WebFetch e WebSearch
"WebFetch(*)" // Qualquer URL
"WebFetch(https://docs.anthropic.com/*)" // Apenas domínio específico
"WebSearch(*)" // Qualquer pesquisaDeny sempre prevalece
Se um padrão está em deny, ele bloqueia mesmo que esteja em allow:
{
"permissions": {
"allow": ["Bash(git *)"], // permite qualquer git
"deny": ["Bash(git push *)"] // mas bloqueia push — PREVALECE
}
}Resultado: todos os git commands são permitidos, exceto push (qualquer variação).
Permissões por camada
As permissões do settings.json se combinam entre camadas (global + projeto + local) por união:
~/.claude/settings.json: allow: ["Bash(git status)", "Bash(git log)"]
.claude/settings.json: allow: ["Bash(npm test)"], deny: ["Bash(rm -rf *)"]
Resultado:
allow: ["Bash(git status)", "Bash(git log)", "Bash(npm test)"]
deny: ["Bash(rm -rf *)"]
Nota sobre merge de camadas
A documentação oficial indica que as camadas mais específicas sobrescrevem as mais gerais para
settings.json. Na prática, parapermissions.allow, o comportamento observado é de acumulação. Para evitar surpresas, liste explicitamente em cada camada o que você precisa.
Configuração recomendada por tipo de projeto
Qualquer projeto (global)
// ~/.claude/settings.json
{
"permissions": {
"allow": [
"Bash(git status)",
"Bash(git log)",
"Bash(git log *)",
"Bash(git diff)",
"Bash(git diff *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(ls)",
"Bash(ls *)",
"Bash(cat *)",
"Bash(find *)",
"Read(*)",
"Edit(*)"
],
"deny": [
"Bash(git push --force*)",
"Bash(git reset --hard*)",
"Bash(rm -rf *)",
"Bash(sudo *)"
]
}
}Projeto Node.js (projeto)
// .claude/settings.json
{
"permissions": {
"allow": [
"Bash(npm test)",
"Bash(npm test *)",
"Bash(npm run *)",
"Bash(npm install *)",
"Bash(npx *)"
],
"deny": [
"Bash(npm publish*)"
]
}
}Projeto Python (projeto)
// .claude/settings.json
{
"permissions": {
"allow": [
"Bash(pytest)",
"Bash(pytest *)",
"Bash(ruff check *)",
"Bash(ruff format *)",
"Bash(python *)",
"Bash(pip install *)"
]
}
}Armadilhas
Sem nenhum allow configurado: cada tool call pede confirmação. Inclua pelo menos Read(*), Edit(*), Bash(git status) para sessões produtivas.
Deny em Bash(*) bloqueia tudo: "deny": ["Bash(*)"] — o agente não consegue rodar absolutamente nada. Deny deve ser cirúrgico.
Glob muito amplo no allow: "Bash(*)" permite que o agente rode qualquer comando, incluindo destrutivos. Prefira listas explícitas de prefixos seguros.
Esquecer variações: "Bash(npm test)" não cobre npm test -- --watch. Adicione "Bash(npm test *)" para cobrir argumentos extras.
Veja também
- 04 - settings.json — contexto de onde permissions se encaixam
- 01 - Hierarquia de configuração — como permissões se combinam entre camadas
- 08 - Armadilhas de configuração — erros comuns de configuração
- Configuração — índice do galho