Pular para o conteúdo

Builder OS

Builder · OS
L09 · Permissões
~13 MIN DE LEITURA

Lição 9 de 10: Permissões e os seis modos

lição 9/10 do Módulo 1
AO FIM, VOCÊ VAI TER
  • Modelo mental das duas camadas: as regras allow/deny/ask no settings.json e 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 .env presente

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:

  1. As regras que você escreve no : allow, deny, ask. É a camada fina, comando a comando.
  2. 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:

  1. Entrar no auto derruba as regras largas. A doc é explícita: ao entrar no modo, as regras amplas de execução arbitrária são descartadas. São Bash(*), interpretadores com wildcard como Bash(python*), e comandos de package manager. As regras estreitas como Bash(npm test) continuam valendo, e as largas voltam quando você sai do modo. No auto, o que segura a barra é o classificador, não o seu allowlist largo.
  2. O auto desiste 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 o auto retoma; 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 deny continua valendo.
  • "rm or rmdir commands 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á:

prompt · text
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 seu package.json (Node).
  • Bash(npm run db:*) — scripts de banco, se você tem db:migrate, db:seed etc. (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.

prompt · text
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.
ENTRADA_1[ENTRADA_1]primeira entrada nova, com prefixo longo. Ex: Bash(grep -r *)
ENTRADA_2[ENTRADA_2]segunda. Repita a primeira se você só tem 1.
ENTRADA_3[ENTRADA_3]terceira. Repita a primeira se você só tem 1 ou 2.

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: defaultacceptEditsplan. 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.

prompt · text
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: