Três camadas no lemon-code: o que nunca roda, o que depende do modo de permissão e o que sempre passa por você
English summary: lemon-code's three guardrail layers: a destructive blocklist that no mode can disable, permission modes that set autonomy, path-based approval checks and secret masking, with stronger executor containment still proposed.
Publicado: 28 de outubro de 2026
Tempo de leitura: 9 min
Série: lemon-code em 30 dias, parte 5 de 13
A flag --yolo da CLI seleciona bypassPermissions, o modo mais permissivo. Ela pula prompts de permissão, mas a blocklist segue ativa: se o modelo propuser rm -rf ~, a resposta é não.
Essa recusa não vem do modelo nem de um prompt pedindo cuidado. Vem de uma regra em código que nenhum modo de permissão desliga. Este post mostra como o lemon-code organiza os guardrails em três camadas e por que a ordem delas importa.
--yolo seleciona bypassPermissions.plan é só leitura; dontAsk nega ações que precisariam de aprovação.Imagine um prédio comercial. Na portaria há uma lista de coisas que não entram de jeito nenhum, com ou sem crachá. Depois vem o crachá, que define em quais andares você circula. E para entrar na sala do cofre, alguém precisa abrir a porta com você.
No agente é igual:
A portaria é a primeira camada. Ela fica antes de tudo, então nenhum crachá passa por cima.
A primeira camada é uma lista de padrões com motivo. O código do lemon-code tem esta forma:
// blocklist destrutiva mínima (reescrita e simplificada)
const DESTRUCTIVE: Array<{ pattern: RegExp; reason: string }> = [
{ pattern: /\brm\s+-rf\s+\/(\s|$)/, reason: "apagar a raiz" },
{ pattern: /\brm\s+-rf\s+(~|\$HOME)(\s|$)/, reason: "apagar o home" },
{ pattern: /\bmkfs\b/, reason: "formatar partição" },
{ pattern: /\bdd\b.*\bof=\/dev\/(sd[a-z]|hd[a-z]|nvme\d|disk\d)\b/i, reason: "gravar em dispositivo de bloco" },
];
export function isDestructive(command: string) {
const hit = DESTRUCTIVE.find((e) => e.pattern.test(command.trim()));
return hit ? { blocked: true, reason: hit.reason } : { blocked: false, reason: "" };
}
console.log(isDestructive("rm -rf ~")); // { blocked: true, reason: "apagar o home" }
console.log(isDestructive("rm -rf ./dist")); // { blocked: false, reason: "" }
Repare que a função não recebe o modo. Ela não tem como ser relaxada por configuração, e isso é proposital.
Produtos gratuitos e pagos para transformar ideias em uma base que você consegue executar.
13 produtos disponíveisContinue explorando tópicos similares
Eu pagava API para tarefas que o Claude Code ou o Codex, já logados na minha máquina, resolveriam. A regra CLI-first do lemon-code cabe em quatro linhas de precedência.
Meu agente escolhia o modelo e eu não sabia por quê. Hoje cada escolha vem com uma linha como 'anthropic score 71.5 (risk +20, order +50)'. Este post mostra como chegar nisso.
O lemon-code tem seis ADRs com o número 0049, todas criadas no mesmo dia. Esse erro ensina mais sobre memória de projeto com vários agentes do que qualquer ADR bem numerada.
Checklist prático para validar segurança, custos, avaliações e observabilidade antes de colocar seu app com IA em produção.
Templates testados em produção, usados por desenvolvedores. Economize semanas de setup no seu próximo projeto.
A DESTRUCTIVE_BLOCKLIST cobre operações catastróficas ou irreversíveis: apagar a raiz ou o home, chmod 777 recursivo na raiz, mkfs, dd gravando em dispositivo de bloco, e DROP DATABASE ou DROP TABLE sem alvo específico. Vale até em bypassPermissions.
Uma blocklist por regex nunca é completa. Ela não substitui sandbox. O papel dela é pegar o erro grosseiro e barato de detectar, aquele que um modelo confuso pode produzir às três da manhã numa missão autônoma.
O modo define quanta autonomia o agente tem:
| Modo | Comportamento |
|---|---|
default | pede permissão para ações sensíveis |
acceptEdits | aceita edições dentro do projeto, pergunta antes de comandos arriscados |
plan | só leitura: ler, listar, buscar; escrita e execução negadas |
dontAsk | não pergunta; o que exigiria aprovação é negado automaticamente |
bypassPermissions (--yolo na CLI) | pula prompts de permissão; a blocklist destrutiva continua ativa |
Dois modos merecem destaque. O plan é o que uso para explorar um repositório desconhecido: o agente lê sem alterar arquivos. dontAsk não é uma aprovação automática: ações que pediriam confirmação são negadas. Na CLI, a flag --yolo seleciona bypassPermissions.
Algumas ações passam por você conforme o modo e a regra aplicada: escrita fora da raiz do projeto, comandos sensíveis e operações de Git como push. O menu oferece aprovar uma vez, para a sessão, permanentemente ou negar.
O workspace entra nessa decisão: caminhos fora da raiz e diretórios protegidos podem acionar o fluxo de aprovação. Isso é uma checagem de caminho, não isolamento do processo inteiro.
Guardrail de execução não basta se a chave de API aparece no log. O lemon-code tem duas defesas:
[REDACTED] no terminal e na UI.Arquivos de configuração com credenciais recebem permissão 600 em sistemas POSIX; a tentativa é best-effort.
Parte das checagens de caminho já existe. A ADR 0024, ainda proposta, descreve contenção mais forte no executor: um workspace jail e regras explícitas para diretórios protegidos como .git/hooks. A blocklist e as aprovações reduzem riscos, mas não equivalem a um sandbox de processo.
Se você quer o modelo de ameaça completo para execução de código gerado por agente, escrevi sobre isso em Sandbox para agentes que executam código.
Guardrail bom é uma pilha em que a camada mais dura fica na frente. A blocklist não depende de modo, o modo define a autonomia e a aprovação cuida do que sobra. Nenhuma delas depende de o modelo se comportar bem.
Na sexta, o assunto muda de código para memória: como uso ADRs para manter vários agentes alinhados no mesmo projeto.
Se o seu time está liberando agentes de código com acesso ao ambiente local e quer revisar o modelo de permissões, é um trabalho que faço na LEMON.DEV.