> ## Documentation Index
> Fetch the complete documentation index at: https://chatcli.edilsonfreitas.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Segurança do Modo Coder (Governanca)

> Entenda como funciona o sistema de governanca e permissões do Modo Coder.

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

<CardGroup cols={3}>
  <Card title="Allow (Permitido)" icon="circle-check">
    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`).
  </Card>

  <Card title="Deny (Bloqueado)" icon="circle-xmark">
    A ação e bloqueada silenciosamente (ou com erro para a IA). Ideal para proteger arquivos sensiveis ou comandos destrutivos.
  </Card>

  <Card title="Ask (Perguntar)" icon="circle-question">
    O ChatCLI pausa e exibe um menu interativo para você decidir. Este e o **padrão** para ações não configuradas.
  </Card>
</CardGroup>

### 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.

<Tip>
  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.
</Tip>

### 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).

***

## Menu de Aprovação Interativo

Quando uma ação cai no estado "Ask", você vera uma caixa de segurança com informações contextuais sobre a acao:

```text theme={"system"}
+========================================================+
|              SECURITY CHECK                             |
+========================================================+
 Acao:   Escrever arquivo
         arquivo: main.go
 Regra:  nenhuma regra para '@coder write'
 --------------------------------------------------------
 Escolha:
   [y] Sim, executar (uma vez)
   [a] Permitir sempre (@coder write)
   [n] Não, pular
   [d] Bloquear sempre (@coder write)

 > _
```

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

| Subcomando | Label no Prompt | Detalhes Exibidos |
| - | - | - |
| `exec` | Executar comando no shell | `$ <comando>`, `dir: <cwd>` |
| `test` | Executar testes | `$ <comando>`, `dir: <cwd>` |
| `write` | Escrever arquivo | `arquivo: <path>` |
| `patch` | Modificar arquivo (patch) | `arquivo: <path>` |
| `read` | Ler arquivo | `arquivo: <path>` |
| `search` | Pesquisar no código | `termo: <pattern>`, `dir: <path>` |
| `tree` | Listar estrutura de diretorios | `dir: <path>` |

### 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:

```text theme={"system"}
+========================================================+
|              SECURITY CHECK                             |
+========================================================+
 Agent:  shell
 Tarefa: Executar testes do modulo auth
 --------------------------------------------------------
 Acao:   Executar comando no shell
         $ go test ./pkg/auth/...
 Regra:  nenhuma regra para '@coder exec'
 --------------------------------------------------------
```

<Info>Isso permite que você saiba **exatamente** qual agent está solicitando a ação e por que, facilitando decisoes de segurança informadas.</Info>

### Opcoes

<Steps>
  <Step title="y (Yes)">
    Executa apenas desta vez. Na proxima, perguntara novamente.
  </Step>

  <Step title="a (Always)">
    Cria uma regra permanente de **ALLOW** para esse comando (ex: libera todas as escritas com `@coder write`).
  </Step>

  <Step title="n (No)">
    Pula a execução. A IA recebe um erro informando que o usuário negou.
  </Step>

  <Step title="d (Deny)">
    Cria uma regra permanente de **DENY**. A ação será bloqueada automaticamente no futuro.
  </Step>
</Steps>

<Note>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.</Note>

***

## 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`

<Tabs>
  <Tab title="Com merge (local + global)">
    Se `merge: true`, as regras locais **mesclam** com a global (local sobrescreve padroes iguais).

    ```json theme={"system"}
    {
      "merge": true,
      "rules": [
        { "pattern": "@coder write", "action": "ask" },
        { "pattern": "@coder exec --cmd 'rm -rf'", "action": "deny" }
      ]
    }
    ```
  </Tab>

  <Tab title="Sem merge (somente local)">
    Se `merge: false` ou ausente, **somente** a policy local e usada.

    ```json theme={"system"}
    {
      "rules": [
        { "pattern": "@coder read", "action": "allow" },
        { "pattern": "@coder write", "action": "ask" }
      ]
    }
    ```
  </Tab>
</Tabs>

### Exemplo de Política (coder\_policy.json)

```json theme={"system"}
{
  "rules": [
    {
      "pattern": "@coder read",
      "action": "allow"
    },
    {
      "pattern": "@coder git-status",
      "action": "allow"
    },
    {
      "pattern": "@coder write",
      "action": "ask"
    },
    {
      "action": "deny",
      "pattern": "@coder exec --cmd 'rm -rf'"
    }
  ]
}
```

***

## Matching com Word Boundary

O sistema de policies usa **matching com word boundary**, garantindo que regras não casem parcialmente com subcomandos diferentes:

| Regra | Comando | Resultado |
| - | - | - |
| `@coder read` = allow | `@coder read file.txt` | Permitido |
| `@coder read` = allow | `@coder readlink /tmp` | **Não casa** (vai para Ask) |
| `@coder read --file /etc` = deny | `@coder read --file /etc/passwd` | Deny (path-prefix match) |

<Tip>Isso significa que `@coder read` **nunca** vai liberar `@coder readlink` ou `@coder readwrite` acidentalmente.</Tip>

***

## Validação de Comandos (50+ Padroes)

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

<CardGroup cols={2}>
  <Card title="Destruicao de dados" icon="trash">
    `rm -rf`, `dd if=`, `mkfs`, `drop database`
  </Card>

  <Card title="Execução remota" icon="globe">
    `curl | bash`, `base64 | sh`
  </Card>

  <Card title="Injecao de código" icon="syringe">
    `python -c`, `eval`, `$(curl ...)`
  </Card>

  <Card title="Substituicao de processos" icon="arrows-left-right">
    `<(cmd)`, `>(cmd)`
  </Card>

  <Card title="Manipulacao de kernel" icon="microchip">
    `insmod`, `modprobe`, `rmmod`
  </Card>

  <Card title="Evasao" icon="mask">
    `${IFS;cmd}`, `VAR=x; bash`
  </Card>
</CardGroup>

Você pode adicionar padroes customizados via `CHATCLI_AGENT_DENYLIST`:

```bash theme={"system"}
export CHATCLI_AGENT_DENYLIST="terraform destroy;kubectl delete namespace"
```

<Info>Para a lista completa de protecoes de segurança do ChatCLI, veja a [documentação de Segurança e Hardening](/pt/security/overview).</Info>

***

## 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`:

| Modo | Escritas em arquivos | Rede | Quando usar |
| - | - | - | - |
| `off` (padrão) | sem restrição | liberada | Confiar apenas no validador + política |
| `workspace` | confinadas ao workspace **e aos caches de build** | liberada | Conter escritas acidentais fora do projeto |
| `strict` | confinadas ao workspace e aos caches de build | **cortada** (sem rede) | Builds e testes totalmente offline e contidos |

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**:

| Plataforma | Backend | Mecanismo |
| - | - | - |
| **macOS** | `sandbox-exec` (nativo) | Profile SBPL gerado: escritas confinadas, rede negada no `strict` |
| **Linux** | `bubblewrap` (`bwrap`) | Root read-only, workspace + caches montados read-write, `--unshare-net` no `strict` |
| **Qualquer SO** (Windows, \*BSD, ou como fallback) | **Docker / Podman** | Workspace montado read-write num container, `--network none` no `strict` |

**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`).

<Warning>
  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.
</Warning>

***

## 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.

<Info>Esse mecanismo e transparente — você não precisa fazer nada. O security check aparece exatamente uma vez por acao.</Info>

***

## Boas Praticas

<Steps>
  <Step title="Inicie com Cautela">
    Mantenha os comandos de escrita (`write`, `patch`, `exec`) como `ask` até sentir confianca no agente.
  </Step>

  <Step title="Libere Leituras">
    Geralmente, e seguro dar "Always" para `coder read`, `coder tree`, `coder search` e Git read-only (`git-status`, `git-diff`, `git-log`).
  </Step>

  <Step title="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`.
  </Step>

  <Step title="Exec Seguro">
    O `@coder exec` bloqueia padroes perigosos por padrão (50+ regras). Use `--allow-unsafe` apenas quando necessário.
  </Step>
</Steps>

***

## 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

| Regra | Ação no Worker |
| - | - |
| **allow** | Ação executada automaticamente pelo worker |
| **deny** | Ação bloqueada; o worker recebe `[BLOCKED BY POLICY]` e continua seu fluxo |
| **ask** | O worker **pausa**, o spinner de progresso e suspenso, e o prompt de segurança e exibido |

<Note>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.</Note>

***

## Regras Ask em Superfícies Unattended (ACP, MCP, Gateway, one-shot headless)

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:

| Superfície | O que uma regra `ask` faz |
| - | - |
| **ACP** (IDE) | Abre o dialog nativo da IDE via `session/request_permission` com o vocabulário completo do terminal — *Allow* / *Always allow* / *Reject* / *Always reject*; as opções *always* persistem uma regra exatamente como `a`/`d` no prompt do terminal. Negação bloqueia e o modelo replaneja. A espera é limitada pela mesma `CHATCLI_MCP_PERMISSION_TIMEOUT` (default `600s`); um dialog sem resposta nega fail-safe com feedback de pedido sem resposta |
| **MCP** com capability `elicitation` | Abre um formulário via `elicitation/create` no cliente com a mesma decisão de quatro opções; opções *always* persistem regras. A espera é limitada por `CHATCLI_MCP_PERMISSION_TIMEOUT` (default `600s`): um formulário sem resposta nega fail-safe e o modelo é informado de que o pedido ficou sem resposta. `CHATCLI_MCP_ELICITATION=off` desliga os formulários por completo |
| **MCP** sem a capability | Auto-aprova (contrato histórico); comandos exec perigosos continuam recusados in-band |
| **Gateway daemon** | Auto-aprova — o operador optou por autonomia total na borda de mensageria |
| **One-shot sem terminal** (`chatcli -p "/coder …"` vindo de script, CI, pipe ou [`chatcli eval`](/pt/agents/harness/evals)) | Nega na hora, fail-safe: ninguém pode responder o prompt, que de outra forma esperaria até o timeout da execução. Workers paralelos recebem a mesma negação. O modelo é avisado de que a ação precisa de aprovação e não foi executada (não que você recusou) e segue sem ela. Use uma regra `allow` explícita, ou o automode da sessão, para o que uma execução headless precisa fazer |

<Note>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.</Note>

Regras `deny` bloqueiam em **todas** as superfícies, e a [validação de comandos perigosos](#validacao-de-comandos-50-padroes) 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**:

| Comando | Efeito |
| - | - |
| `/policy` ou `/policy status` | Mostra o modo atual, a contagem de regras e o arquivo de política |
| `/policy mode auto` | **Automode**: todo veredito `ask` da política auto-aprova nesta sessão |
| `/policy mode interactive` | Volta ao padrão: `ask` pede aprovaçã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](#validacao-de-comandos-50-padroes)** 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](#ordem-de-prioridade-do-policy_manager) 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:

| Variável | Valores | Descrição |
| - | - | - |
| `CHATCLI_CODER_UI` | `full` (padrão), `minimal` | Estilo da interface |
| `CHATCLI_CODER_BANNER` | `true` (padrão), `false` | Mostra/oculta o cheat sheet |

<Tip>Essas configurações aparecem em `/status` e `/config`.</Tip>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.