Skip to main content
O ChatCLI foi projetado para ser uma ferramenta poderosa, mas o poder exige controle. No Modo Coder (/coder), a IA tem capacidade de ler, escrever, criar e executar comandos no seu sistema. Para garantir que você esteja sempre no comando, implementamos um sistema de governanca inspirado no ClaudeCode.

Como Funciona?

Toda a vez que a IA sugere uma ação (como criar um arquivo ou rodar um script), o ChatCLI verifica as suas regras de segurança locais antes de executar.

Os 3 Estados de Permissao

Allow (Permitido)

A ação e executada automaticamente, sem interrupcao. Ideal para comandos de leitura (read, tree, search) e Git read-only (git-status, git-diff, git-log, git-changed, git-branch).

Deny (Bloqueado)

A ação e bloqueada silenciosamente (ou com erro para a IA). Ideal para proteger arquivos sensiveis ou comandos destrutivos.

Ask (Perguntar)

O ChatCLI pausa e exibe um menu interativo para você decidir. Este e o padrão para ações não configuradas.

Ordem de prioridade do policy_manager

Quando o agente solicita uma ação, o policy_manager avalia as regras na ordem abaixo (a primeira que aplica vence):
  1. Deny rules — regras explícitas do usuário sempre ganham
  2. Safety-immune — operações que SEMPRE pedem confirmação (@coder exec)
  3. Allow vs Ask explícito — padrão mais longo (longest pattern wins)
  4. Read-only exec heuristic — @coder exec com comando comprovadamente read-only auto-allow
  5. Capability gate (novo) — plugins que declaram IsReadOnly=true via interface de capability auto-allow
  6. Default — Ask
A camada 5 cobre @read, @search, @tree, @websearch, @webfetch (GET), @scheduler query/list, @coder read/search/tree — todos passam sem prompt enquanto write/exec continuam gated.
Deny rules sempre ganham do capability gate. Você pode bloquear @websearch em ambiente corporativo via regra @websearch → Deny mesmo que o plugin advertise read-only.

Proteção contra typeahead (input guard)

Quando o LLM está streamando e a security box aparece, qualquer caractere que você tenha digitado antes do prompt mostrar é descartado automaticamente. Três camadas:
  • Flush kernel TTY — TCIFLUSH (Linux), TIOCFLUSH (BSD/Darwin), FlushConsoleInputBuffer (Windows) descarta bytes na fila do kernel.
  • Drain channel — esvazia o canal centralizado de stdin não-bloqueante (10 linhas de buffer).
  • Intent debounce — descarta qualquer input que chegue nos primeiros 250ms após o prompt aparecer (humanos não respondem tão rápido a uma UI nova).
Sem isso, digitar acidentalmente durante o stream do LLM faria a security box consumir os bytes prontos como resposta de y/n. Instruções são preservadas, respostas não. Uma linha completa que você enviou para o agente (por exemplo atualize também o changelog) nunca responde ao prompt, mas também não é mais jogada fora: o drain a reenfileira e ela chega ao modelo na próxima fronteira de turno. Do drain, só continuam descartadas as linhas em forma de resposta de prompt (y, n, yes, no, sim, a, always, d, deny ou Enter vazio).
Quando uma ação cai no estado “Ask”, você vera uma caixa de segurança com informações contextuais sobre a acao:
O prompt exibe a acao em linguagem humana (ex.: “Escrever arquivo”, “Executar comando no shell”, “Modificar arquivo (patch)”) e os detalhes parseados dos argumentos JSON, em vez de mostrar JSON bruto.

Tipos de Ação Reconhecidos

Prompt com Contexto no Modo Paralelo

Quando a ação e solicitada por um worker do modo multi-agent, o prompt inclui informações adicionais sobre qual agent está requisitando:
Isso permite que você saiba exatamente qual agent está solicitando a ação e por que, facilitando decisoes de segurança informadas.

Opcoes

1

y (Yes)

Executa apenas desta vez. Na proxima, perguntara novamente.
2

a (Always)

Cria uma regra permanente de ALLOW para esse comando (ex: libera todas as escritas com @coder write).
3

n (No)

Pula a execução. A IA recebe um erro informando que o usuário negou.
4

d (Deny)

Cria uma regra permanente de DENY. A ação será bloqueada automaticamente no futuro.
Para comandos exec, as opções “Always” e “Deny Forever” não são disponibilizadas, pois cada execução e única e requer aprovação individual.

Gerenciamento de Regras

As regras são salvas localmente em ~/.chatcli/coder_policy.json. Você pode editar esse arquivo manualmente se desejar, mas o menu interativo e a forma mais facil de configurar. O matching usa o subcomando efetivo do @coder mesmo quando args e JSON (ex.: {"cmd":"read"} vira @coder read).

Policy Local (Por Projeto)

Você pode adicionar uma policy local no diretório do projeto:
  • Local: ./coder_policy.json
  • Global: ~/.chatcli/coder_policy.json
Se merge: true, as regras locais mesclam com a global (local sobrescreve padroes iguais).

Exemplo de Política (coder_policy.json)


Matching com Word Boundary

O sistema de policies usa matching com word boundary, garantindo que regras não casem parcialmente com subcomandos diferentes:
Isso significa que @coder read nunca vai liberar @coder readlink ou @coder readwrite acidentalmente.

Validação de Comandos (50+ Padroes)

Alem da governanca de policies, o @coder exec válida cada comando contra 50+ padroes regex que detectam:

Destruicao de dados

rm -rf, dd if=, mkfs, drop database

Execução remota

curl | bash, base64 | sh

Injecao de código

python -c, eval, $(curl ...)

Substituicao de processos

<(cmd), >(cmd)

Manipulacao de kernel

insmod, modprobe, rmmod

Evasao

${IFS;cmd}, VAR=x; bash
Você pode adicionar padroes customizados via CHATCLI_AGENT_DENYLIST:
Para a lista completa de protecoes de segurança do ChatCLI, veja a documentação de Segurança e Hardening.

Sandbox de Exec (confinamento no nível do SO)

O validador de comandos e a política de permissões controlam o que um comando pode rodar. O sandbox de exec é uma segunda camada, complementar, que confina o que um comando permitido pode tocar — escritas em arquivos e rede — usando o próprio sandboxing do sistema operacional. É opt-in e desligado por padrão, selecionado por CHATCLI_CODER_SANDBOX: Em workspace e strict, as escritas são permitidas no workspace mais uma allowlist generosa de caches de toolchain — cache de módulos Go / GOCACHE, .npm, .cargo, .rustup, .gradle, .m2, ~/.chatcli e o diretório temporário — para que builds comuns continuem funcionando enquanto escritas fora disso são bloqueadas.

Backends — confinamento em qualquer SO

O ChatCLI escolhe o backend mais forte disponível no host, e o backend de container faz o confinamento funcionar em qualquer sistema operacional, Windows incluído: Ordem de seleção: um pedido explícito de container (CHATCLI_CODER_SANDBOX=docker, podman ou container) vence; senão o backend nativo é usado; se nenhum existir, o backend de container portátil assume; só quando nenhum backend está instalado é que degrada para sem confinamento — imprimindo uma nota de uma linha, nunca falhando o comando. A imagem do container é configurável com CHATCLI_CODER_SANDBOX_IMAGE (padrão alpine:3).
O sandbox é opt-in de propósito: um build silenciosamente confinado que não consegue alcançar seu cache de módulos é pior do que sandbox nenhum. Ligue de forma deliberada.Com o backend de container, o comando roda dentro da imagem — então toolchains do host (go, node, …) só estão disponíveis se a imagem os trouxer. Aponte CHATCLI_CODER_SANDBOX_IMAGE para uma imagem que carregue seu toolchain, ou use os backends nativos de macOS/Linux quando precisar das ferramentas do host.

Deduplicação de Tool Calls

O ChatCLI possui um mecanismo de deduplicação que garante que cada tool call seja verificada e executada exatamente uma vez.

O Problema

Quando a IA responde com tool calls em formato XML (ex: <tool_call name="@coder" args='{"cmd":"read",...}' />), o parser do ChatCLI usa dois métodos de extracao:
  1. Parser XML — extrai tags <tool_call> completas
  2. Parser JSON — procura objetos JSON que representem tool calls (para modelos que respondem em JSON puro)
O JSON embutido dentro do atributo args do XML (ex: {"cmd":"read",...}) poderia ser incorretamente reconhecido pelo parser JSON como uma segunda tool call. Sem deduplicação, isso causaria:
  • Security check exibido duas vezes para a mesma acao
  • A mesma ação executada duas vezes

A Solucao

O ParseToolCalls aplica deduplicação automatica: tool calls extraidas pelo parser JSON que já existam como parte de uma tool call XML são descartadas. A comparacao usa o nome da tool, os argumentos e o texto bruto para detectar duplicatas.
Esse mecanismo e transparente — você não precisa fazer nada. O security check aparece exatamente uma vez por acao.

Boas Praticas

1

Inicie com Cautela

Mantenha os comandos de escrita (write, patch, exec) como ask até sentir confianca no agente.
2

Libere Leituras

Geralmente, e seguro dar “Always” para coder read, coder tree, coder search e Git read-only (git-status, git-diff, git-log).
3

Seja Especifico

O matching usa word boundary para prefixos de subcomando e path-prefix para argumentos. Você pode liberar coder exec --cmd 'ls mas bloquear coder exec --cmd 'rm.
4

Exec Seguro

O @coder exec bloqueia padroes perigosos por padrão (50+ regras). Use --allow-unsafe apenas quando necessário.

Governanca no Modo Multi-Agent (Paralelo)

As policies de segurança são totalmente respeitadas pelos workers do modo multi-agent. Quando o /coder ou /agent opera em modo paralelo, cada worker verifica as regras do coder_policy.json antes de executar qualquer acao.

Comportamento

Os prompts de segurança de múltiplos workers são serializados — apenas um prompt por vez e exibido, evitando sobreposicao visual. Regras criadas durante a sessão (via “Always” ou “Deny”) são imediatamente visiveis para todos os workers subsequentes.

Regras Ask em Superfícies Unattended (ACP, MCP, Gateway)

No terminal interativo uma regra ask mostra o prompt de segurança. Em superfícies unattended — onde o stdin carrega um protocolo ou ninguém está olhando — a regra é resolvida por superfície:
Comandos exec nunca recebem as opções always em nenhuma superfície — a mesma restrição do prompt interativo, já que qualquer comando shell pode ser destrutivo.
Regras deny bloqueiam em todas as superfícies, e a validação de comandos perigosos se aplica em qualquer lugar independente da política. Um cliente que não implementa o round-trip de permissão (responde method not found) cai no contrato de auto-approve em vez de ter toda ação gateada negada.

Modo de Política da Sessão (/policy)

Às vezes você quer que a sessão simplesmente flua — um refactor longo que você já confia, um run roteirizado — sem aprovar cada ask um por um. O /policy alterna o modo de política da sessão: O que o automode não muda:
  • Regras deny continuam bloqueando — elas resolvem antes do ask na checagem de política.
  • A validação de comandos perigosos continua ativa.
  • Operações safety-immune (rm -rf, sudo, force push, …) continuam perguntando — o automode amplia a conveniência, nunca o raio de destruição que o tier safety-immune protege.
O modo nunca é persistido: toda sessão nova começa interativa. Cada auto-aprovação é logada para auditoria, e o modo atual fica visível em /policy status e no /config security. Disponível nas três superfícies: o REPL do terminal, o menu de slash commands do ACP na IDE, e o MCP via a action policy_mode da tool manage_session (name: auto | interactive | status).

UI do Modo Coder

Você pode controlar o estilo e o banner do /coder via variáveis de ambiente:
Essas configurações aparecem em /status e /config.