Lição 9 de 10: Permissões e os seis modos
- Modelo mental das duas camadas: as regras allow/deny/ask no
settings.jsone os seis modos de permissão por cima delas - A escada de autonomia: allowlist → auto mode → sandbox → bypass só dentro de container, e onde você está hoje
- A regra dura que não tem exceção: nunca rodar bypassPermissions num filesystem real com
.envpresente
Esta lição é sobre permissões: o que o Claude executa sem te perguntar. O modelo tem duas camadas, e a versão antiga desta lição só cobria a primeira.
As duas camadas
Quando o Claude quer editar um arquivo, rodar um comando de shell ou fazer uma requisição de rede, duas coisas decidem o que acontece:
- As regras que você escreve no :
allow,deny,ask. É a camada fina, comando a comando. - O da sessão, uma chave que muda o piso: o que roda sem perguntar, antes mesmo de olhar as regras. São seis modos.
A versão anterior desta lição parava na camada 1. Ela continua certa e você começa por ela. Mas hoje o modo é o que mais muda seu dia, então a segunda metade da lição é sobre os seis modos e a escada de autonomia que eles formam.
Camada 1 — o fragmento que você já tem
Se você seguiu a lição de bootstrap, o seu projeto já tem um .claude/settings.json: é o arquivo que o template do curso trouxe. Abre ele. Se ainda não tem (projeto começado do zero, sem o template), crie o arquivo com esse conteúdo. De qualquer jeito, o que você vai ver é algo assim:
{
"permissions": {
"allow": [
"Read(*)",
"Bash(git status*)",
"Bash(npm run dev*)",
"Bash(npm test*)",
"Bash(npx tsc --noEmit)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(sudo *)",
"Bash(curl * | sh)",
"Bash(npm publish*)",
"Read(.env)",
"Read(.env.*)",
"Read(.claude/settings.local.json)"
]
}
}Duas listas, três decisões. Toda vez que o Claude tenta rodar algo:
- allow — casa com
permissions.allow. Roda direto, sem perguntar.npm run dev,git status -s. - deny — casa com
permissions.deny. Recusa direto, sem perguntar.rm -rf node_modules,npm publish. - ask — não casa com nenhuma das duas. Aparece
Do you want to proceed? [y/n]e espera você.
Deny vence allow. Mesmo que Bash(*) estivesse no allow (favor não fazer), rm -rf continuaria bloqueado.
A regra prática da camada 1 fica curta: poucos comandos repetidos e seguros no allow; as coisas que você nunca quer que aconteçam no deny; e tudo mais em ask. O settings.local.json (gitignored) é o seu allow pessoal pra esse projeto, sem afetar quem clonar. Mesma sintaxe, e nenhum dos dois arquivos aceita secret (credencial vai em .env.local).
Camada 2 — os seis modos
Aqui é o que a versão antiga não cobria. O modo de permissão muda o piso da sessão: o que roda sem prompt antes de olhar as regras. Você troca de modo com Shift+Tab no CLI (ou pelo seletor de modo no VS Code, no Desktop e no claude.ai); cada Shift+Tab avança um modo. Três modos sempre aparecem nessa troca (default, acceptEdits, plan); os outros três dependem da sua conta ou de como você iniciou a sessão, e eu explico cada um na hora. A doc oficial lista os seis, com o que cada um deixa rodar sem perguntar:
A regra que segura tudo isso de pé, e que você precisa decorar, é uma frase verbatim da doc:
Auto mode: tirar os prompts sem ficar cego
auto é o modo que mais muda a sensação do dia a dia, e merece um parágrafo a mais. A razão está em um número que a Anthropic mediu:
O classificador é um modelo, não uma lista fixa: ele decide caso a caso e pode errar (a própria doc avisa isso, logo abaixo). Mas a doc descreve a direção dele com exemplos. Tende a bloquear: baixar e executar código (curl | bash), mandar dado sensível pra fora, deploy e migração de produção, deleção em massa, git push --force ou push direto na main. Tende a deixar passar: operação local na sua pasta, instalar dependência já declarada no lockfile, requisição HTTP de leitura, push pra branch que você mesmo começou.
Duas coisas importam na prática:
- Entrar no
autoderruba as regras largas. A doc é explícita: ao entrar no modo, as regras amplas de execução arbitrária são descartadas. SãoBash(*), interpretadores com wildcard comoBash(python*), e comandos de package manager. As regras estreitas comoBash(npm test)continuam valendo, e as largas voltam quando você sai do modo. Noauto, o que segura a barra é o classificador, não o seu allowlist largo. - O
autodesiste e volta a perguntar. Quando o classificador bloqueia ações demais (a doc cita um limite por sequência e um limite no total da sessão), o modo pausa e o Claude Code volta a te perguntar. Você aprova a ação pendente e oautoretoma; ele não roda solto bloqueando indefinidamente.
A sandbox: quem impõe o limite é o sistema operacional
Tem mais uma peça, e ela é de natureza diferente. Modo e regra são checados pelo Claude Code antes do comando rodar, com base no texto do comando. A é imposta pelo sistema operacional no processo em execução. Então ela vale mesmo que o comando faça mais do que o nome dele sugere.
Com a sandbox ligada no modo auto-allow, os comandos de Bash rodam sem prompt porque o limite do SO já os contém, e você pode auto-liberar mais com menos medo. Mas o "auto-allow" da sandbox guarda freios, também verbatim da doc:
- "Explicit deny rules are always respected" — seu
denycontinua valendo. - "
rmorrmdircommands that target/, your home directory, or other critical system paths still trigger a permission prompt" — apagar a raiz ou o home sempre pergunta, sandbox ou não.
A escada de autonomia
Junte as peças e você tem uma escada, do mais seguro pro mais perigoso. Suba um degrau por vez, e só quando o atrito do degrau atual estiver te atrapalhando de verdade.
Allowlist (camada 1). Você fica em default e move pra allow os poucos comandos repetidos e seguros. É onde você começa e onde a maioria dos projetos fica bem por muito tempo. Atrito: você ainda aprova prompt pra coisa nova.
Auto mode. Quando o atrito de aprovar prompt vira reflexo (os tais 93%), suba pro auto. Você troca o prompt pelo classificador, que bloqueia ação arriscada e desiste pra te perguntar se bloquear demais. O guardrail continua de pé.
Sandbox. O próximo degrau é deixar o SO conter o que o comando alcança, em vez de só confiar no texto do comando. Quando a sandbox está ligada, você pode auto-liberar Bash com menos medo, porque o deny e o freio do rm / continuam valendo. Sandbox e auto mode combinam. A ativação muda por sistema e tem opções de configuração; o passo a passo está na doc de sandboxing. O Lab desta lição não chega a ligar a sandbox, então não se preocupe se você ainda não fez isso.
Bypass, só dentro de container. bypassPermissions pula tudo. Ele tem um lugar: container, VM ou dev container isolado, de preferência sem internet, onde o Claude Code não consegue danificar a sua máquina. A própria doc: "Only use this mode in isolated environments like containers, VMs, or dev containers without internet access."
Lab: leia o setup, suba um degrau de propósito
O objetivo é sentir as duas camadas na mão: as regras e os modos.
Leia o settings.json que o template trouxe. Antes de mudar nada, entenda o que está lá:
Abra o `.claude/settings.json` e me explique, em duas listas:
1. Cada entrada do `allow` — o que o comando faz, e por que está seguro pra rodar sem perguntar.
2. Cada entrada do `deny` — o que o comando faria, e por que você nunca quer que isso aconteça.
Mantenha curto: 1 linha por entrada.Adicione até 3 entradas novas ao seu allow. Pegue comandos que o Claude vai rodar repetidamente no seu projeto. Como decidir o que serve pro seu caso: pense num comando que você já viu cair no [y/n] mais de uma vez, que é de leitura ou de rotina (não muda dado de produção), e escreva a entrada com prefixo longo o bastante pra não abrir mais do que você quer.
Lembre da regra de matching desta lição: * casa com qualquer coisa depois do que vem antes dele. Então o que restringe a entrada é o começo: texto depois do * não filtra nada. Exemplos de entradas com prefixo seguro, conforme a sua stack:
Bash(grep -r *)— buscas no projeto (toda stack).Bash(npm run lint*)— um script específico do seupackage.json(Node).Bash(npm run db:*)— scripts de banco, se você temdb:migrate,db:seedetc. (Postgres/Supabase).Bash(pytest*),Bash(ruff *)— se o seu projeto é Python.
Se você está começando e ainda não sabe quais comandos vai rodar, não force: adicione um só (um grep ou um lint que você já usa) e deixe o resto pra depois. Não escolha prefixos curtos como Bash(npm *) ou Bash(git *): eles abrem npm publish e git push --force.
Adicione estas entradas ao `permissions.allow` do `.claude/settings.json`, mantendo o resto do arquivo exatamente como está. Se alguma já existir, não duplique:
-
-
-
Mostre o diff antes de aplicar.Aprove o diff se as entradas estão lá e o resto não foi tocado.
Se você versiona o projeto com git, vale fechar com um commit dessa mudança. Se faz tempo que você não commita, o comando é git commit e o "body" é só a parte longa da mensagem, abaixo do título. Use ela pra anotar por que cada entrada é segura pra allow. Daqui a 6 meses você vai querer essa justificativa. (Se você ainda não usa git neste projeto, pule esta parte; não é pré-requisito do resto do Lab.)
Cicle os modos com Shift+Tab e leia o status. Aperte Shift+Tab e veja o modo mudar na barra de status: default → acceptEdits → plan. Cada um muda o que roda sem prompt. Se você só vê esses três, está tudo certo: o auto é um research preview e pode não aparecer na sua conta ou na sua versão do CLI; o bypassPermissions só entra no ciclo se você iniciou a sessão com a flag dele. Não é erro seu; siga com os modos que aparecem. Volte pro default antes de seguir.
Explique, pra esta sessão: em qual modo de permissão eu estou agora, e o que muda no que você roda sem me perguntar se eu trocar pra acceptEdits. Não rode nada — só explique.Confirme onde está a sua escada. Responda pra você mesmo: hoje você está no degrau 1 (allowlist). Qual atrito te faria subir pro auto? E o que precisaria estar verdadeiro pra você considerar o bypass? (Resposta certa pro bypass: estar dentro de um container isolado. Em qualquer outro lugar, a resposta é "não".)
Você terminou quando
Você consegue, sem hesitar: ler o allow/deny do seu settings.json e justificar cada entrada; nomear os seis modos e o que cada um deixa rodar sem perguntar; dizer por que escrever em .git/.env/.mcp.json nunca é auto-aprovado fora do bypass; e situar-se na escada de autonomia, sabendo que o bypass mora dentro de um container e nunca no seu filesystem real com .env presente.
Veja isso ao vivo
Sessão real apertando o allowlist de um projeto depois do quinto [y/n] consecutivo, e decidindo entre subir pro auto ou ficar na camada 1: