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

# Configuração

> Formato do arquivo de configuração, sistema de três escopos e regras de mesclagem

failproofai usa arquivos de configuração JSON para controlar quais políticas estão ativas, como elas se comportam e de onde as políticas personalizadas são carregadas. A configuração foi projetada para ser fácil de compartilhar com sua equipe — faça o commit no seu repositório e todos os desenvolvedores terão a mesma rede de segurança para agentes.

***

## Escopos de configuração

Existem três escopos de configuração, avaliados em ordem de prioridade:

| Escopo      | Caminho do arquivo                        | Finalidade                                                      |
| ----------- | ----------------------------------------- | --------------------------------------------------------------- |
| **project** | `.failproofai/policies-config.json`       | Configurações por repositório, commitadas no controle de versão |
| **local**   | `.failproofai/policies-config.local.json` | Substituições pessoais por repositório, incluídas no gitignore  |
| **global**  | `~/.failproofai/policies-config.json`     | Padrões do usuário aplicados em todos os projetos               |

Quando failproofai recebe um evento de hook, ele carrega e mescla os três arquivos que existirem para o diretório de trabalho atual.

### Regras de mesclagem

**`enabledPolicies`** — a união dos três escopos. Uma política habilitada em qualquer nível fica ativa.

```text theme={null}
project:  ["block-sudo"]
local:    ["block-rm-rf"]
global:   ["block-sudo", "sanitize-api-keys"]

resolved: ["block-sudo", "block-rm-rf", "sanitize-api-keys"]  ← união sem duplicatas
```

**`policyParams`** — o primeiro escopo que define os parâmetros para uma política específica vence por completo. Não há mesclagem profunda de valores dentro dos parâmetros de uma política.

```text theme={null}
project:  block-sudo → { allowPatterns: ["sudo apt-get update"] }
global:   block-sudo → { allowPatterns: ["sudo systemctl status"] }

resolved: { allowPatterns: ["sudo apt-get update"] }   ← project vence, global ignorado
```

```text theme={null}
project:  (sem entrada para block-sudo)
local:    (sem entrada para block-sudo)
global:   block-sudo → { allowPatterns: ["sudo systemctl status"] }

resolved: { allowPatterns: ["sudo systemctl status"] }  ← cai para o global
```

**`customPoliciesPath`** — o primeiro escopo que o define vence.

**`llm`** — o primeiro escopo que o define vence.

***

## Formato do arquivo de configuração

```json theme={null}
{
  "enabledPolicies": [
    "block-sudo",
    "block-rm-rf",
    "block-push-master",
    "sanitize-api-keys",
    "sanitize-jwt",
    "block-env-files",
    "block-read-outside-cwd"
  ],
  "policyParams": {
    "block-sudo": {
      "allowPatterns": ["sudo systemctl status", "sudo journalctl"]
    },
    "block-push-master": {
      "protectedBranches": ["main", "release", "prod"]
    },
    "block-rm-rf": {
      "allowPaths": ["/tmp"]
    },
    "block-read-outside-cwd": {
      "allowPaths": ["/shared/data", "/opt/company"]
    },
    "sanitize-api-keys": {
      "additionalPatterns": [
        { "regex": "myco_[A-Za-z0-9]{32}", "label": "MyCo API key" }
      ]
    },
    "warn-large-file-write": {
      "thresholdKb": 512
    }
  },
  "customPoliciesPath": "/home/alice/myproject/my-policies.js"
}
```

***

## Referência de campos

### `enabledPolicies`

Tipo: `string[]`

Lista de nomes de políticas a serem habilitadas. Os nomes devem corresponder exatamente aos identificadores de política exibidos por `failproofai policies`. Consulte [Políticas Integradas](/pt-br/built-in-policies) para ver a lista completa.

Políticas que não estejam em `enabledPolicies` ficam inativas, mesmo que tenham entradas em `policyParams`.

### `policyParams`

Tipo: `Record<string, Record<string, unknown>>`

Substituições de parâmetros por política. A chave externa é o nome da política; as chaves internas são específicas de cada política. Cada política documenta seus parâmetros disponíveis em [Políticas Integradas](/pt-br/built-in-policies).

Se uma política tiver parâmetros mas você não os especificar, os padrões internos da política serão usados. Usuários que não configurarem `policyParams` terão comportamento idêntico ao das versões anteriores.

Chaves desconhecidas dentro do bloco de parâmetros de uma política são silenciosamente ignoradas no momento em que o hook é disparado, mas sinalizadas como avisos ao executar `failproofai policies`.

#### `hint` (transversal)

Tipo: `string` (opcional)

Uma mensagem anexada ao motivo quando uma política retorna `deny` ou `instruct`. Use para fornecer orientações práticas a Claude sem modificar a própria política.

Funciona com qualquer tipo de política — integradas, personalizadas (`custom/`), convenções de projeto (`.failproofai-project/`) ou convenções de usuário (`.failproofai-user/`).

```json theme={null}
{
  "policyParams": {
    "block-force-push": {
      "hint": "Try creating a fresh branch instead."
    },
    "block-sudo": {
      "allowPatterns": ["sudo apt-get"],
      "hint": "Use apt-get directly without sudo."
    },
    "custom/my-policy": {
      "hint": "Ask the user for approval first."
    }
  }
}
```

Quando `block-force-push` nega, Claude vê: *"Force-pushing is blocked. Try creating a fresh branch instead."*

Valores não-string e strings vazias são silenciosamente ignorados. Se `hint` não estiver definido, o comportamento permanece inalterado (compatível com versões anteriores).

### `customPoliciesPath`

Tipo: `string` (caminho absoluto)

Caminho para um arquivo JavaScript contendo políticas de hook personalizadas. Esse campo é configurado automaticamente por `failproofai policies --install --custom <path>` (o caminho é resolvido para absoluto antes de ser armazenado).

O arquivo é carregado do zero a cada evento de hook — não há cache. Consulte [Políticas Personalizadas](/pt-br/custom-policies) para detalhes de autoria.

### Políticas baseadas em convenção

Além do `customPoliciesPath` explícito, failproofai descobre e carrega automaticamente arquivos de política dos diretórios `.failproofai/policies/`:

| Nível   | Diretório                  | Escopo                                            |
| ------- | -------------------------- | ------------------------------------------------- |
| Projeto | `.failproofai/policies/`   | Compartilhado com a equipe via controle de versão |
| Usuário | `~/.failproofai/policies/` | Pessoal, aplicado a todos os projetos             |

**Correspondência de arquivos:** Apenas arquivos que correspondam a `*policies.{js,mjs,ts}` são carregados (por exemplo, `security-policies.mjs`, `workflow-policies.js`). Outros arquivos no diretório são ignorados.

**Sem configuração necessária:** Políticas de convenção não precisam de entradas em `policies-config.json`. Basta colocar os arquivos no diretório e eles serão detectados no próximo evento de hook.

**Carregamento por união:** Os diretórios de convenção do projeto e do usuário são verificados. Todos os arquivos correspondentes de ambos os níveis são carregados (ao contrário de `customPoliciesPath`, que utiliza o primeiro escopo que vencer).

Consulte [Políticas Personalizadas](/pt-br/custom-policies) para mais detalhes e exemplos.

### `llm`

Tipo: `object` (opcional)

Configuração do cliente LLM para políticas que fazem chamadas de IA. Não é necessário para a maioria das configurações.

```json theme={null}
{
  "llm": {
    "model": "claude-sonnet-4-6",
    "apiKey": "sk-ant-..."
  }
}
```

***

## Gerenciando a configuração pela CLI

Os comandos `policies --install` e `policies --uninstall` escrevem no arquivo de configurações de hook do seu agente CLI (os pontos de entrada dos hooks), enquanto `policies-config.json` é o arquivo que você gerencia diretamente. Os dois são independentes:

* **Configurações do agente CLI** — instrui o agente a chamar `failproofai --hook <event>` a cada uso de ferramenta:
  * **Claude Code**: `~/.claude/settings.json` (usuário), `<cwd>/.claude/settings.json` (projeto), `<cwd>/.claude/settings.local.json` (local)
  * **OpenAI Codex**: `~/.codex/hooks.json` (usuário), `<cwd>/.codex/hooks.json` (projeto) — o Codex não possui escopo `local`
  * **GitHub Copilot CLI *(beta)***: `~/.copilot/hooks/failproofai.json` (usuário), `<cwd>/.github/hooks/failproofai.json` (projeto) — o Copilot não possui escopo `local`. As entradas de hook usam os campos de comando `bash`/`powershell` com chave por SO do Copilot com `timeoutSec`; o arquivo carrega um marcador `version: 1` no nível superior. O suporte ao Copilot CLI está em **beta** enquanto verificamos o esquema de registros `events.jsonl` (não especificado na documentação pública) em mais sessões reais.
  * **Cursor Agent *(beta)***: `~/.cursor/hooks.json` (usuário), `<cwd>/.cursor/hooks.json` (projeto) — o Cursor não possui escopo `local`. As entradas de hook usam o formato Claude `{type, command, timeout}` (sem divisão `bash`/`powershell`), mas armazenadas sob chaves de evento em camelCase (`preToolUse`, `beforeSubmitPrompt`, …) em um array plano, conforme o [esquema de hooks](https://cursor.com/docs/hooks) do Cursor; o arquivo carrega um marcador `version: 1` no nível superior. O handler canonicaliza camelCase → PascalCase via `CURSOR_EVENT_MAP`, de modo que as políticas integradas existentes disparam sem alteração. O suporte ao Cursor Agent está em **beta** enquanto verificamos o formato em disco da transcrição do Cursor (não especificado na documentação pública) em mais instalações reais.
  * **OpenCode *(beta)***: `~/.config/opencode/opencode.json` + `~/.config/opencode/plugins/failproofai.mjs` (usuário), `<cwd>/.opencode/opencode.json` + `<cwd>/.opencode/plugins/failproofai.mjs` (projeto) — o OpenCode não possui escopo `local`. Diferentemente dos outros cinco CLIs, o OpenCode **não possui sistema de hooks para comandos externos**: ele carrega plugins JS/TS em processo, explicitamente registrados pelo array `plugin: []` no `opencode.json` (a autodescoberta a partir de `.opencode/plugins/` **não** é como os plugins são carregados no opencode v1.14.33). A instalação deposita um pequeno shim de plugin gerado que chama o binário failproofai em subprocesso e traduz a resposta JSON no formato Claude do binário para a semântica do plugin: `throw new Error()` para negação em eventos de ferramenta (cancela a chamada da ferramenta), `client.session.prompt(...)` para instruct E para negação de `Stop` / `SubagentStop` (envia o motivo da negação como a próxima mensagem do usuário — o único canal de força de nova tentativa, já que `session.idle` é apenas de notificação e lançar exceção a partir dele é um no-op), e no-op para allow. O shim canonicaliza nomes de ferramentas (minúsculas → PascalCase via `OPENCODE_TOOL_MAP`) e chaves de argumentos de entrada de ferramentas (camelCase → snake\_case via `OPENCODE_TOOL_INPUT_MAP` para `Read` / `Write` / `Edit`, por exemplo `filePath` → `file_path`, `oldString` → `old_string`) antes de encaminhar ao binário, de modo que políticas integradas de verificação de caminho como `block-read-outside-cwd`, `block-env-files` e `block-secrets-write` disparam sem alteração em chamadas de ferramentas do OpenCode. As sessões ficam no banco de dados SQLite do opencode em `~/.local/share/opencode/opencode.db`; o visualizador de sessões do dashboard as lê via `opencode db --format json` e `opencode export <id>`. O suporte ao OpenCode está em **beta** enquanto verificamos o comportamento entre versões e em mais sessões reais. Consulte a [documentação de plugins do OpenCode](https://opencode.ai/docs/plugins/).
  * **Pi *(beta)***: `~/.pi/agent/settings.json` (usuário), `<cwd>/.pi/settings.json` (projeto) — o Pi não possui escopo `local`. O Pi carrega pacotes de extensão TypeScript na inicialização; o arquivo de configurações é um array de strings plano `{"packages": ["./relative/path", …]}`. failproofai escreve uma única entrada no array de pacotes apontando para seu diretório `pi-extension/` empacotado. A extensão subscreve internamente aos eventos `tool_call` / `user_bash` / `input` / `session_start` do Pi e executa `failproofai --hook <Event> --cli pi` em shell; o handler canonicaliza eventos via `PI_EVENT_MAP` (underscore\_lower\_snake\_case → PascalCase) para que as políticas integradas existentes disparem sem alteração. Os argumentos de entrada de ferramentas também são canonicalizados via `PI_TOOL_INPUT_MAP` (o Read / Write / Edit do Pi entregam `path` em vez de `file_path`; mapear a chave de nível superior permite que `block-env-files` e `block-secrets-write` disparem — `block-read-outside-cwd` já tinha um fallback para `path`). O suporte ao Pi está em **beta** enquanto a API de extensão do Pi e o layout do log de sessão se estabilizam.
  * **Hermes (hermes-agent)**: `~/.hermes/config.yaml` (**somente escopo de usuário** — o Hermes não possui configuração de projeto/local). O Hermes é um **gateway** para Slack/Telegram, portanto uma única instalação intercepta chamadas de ferramentas de todas as plataformas (Slack/Telegram/cli/cron) **e** de subagentes internos. As entradas de hook são um par `{command, timeout}` (timeout em **segundos**) sob um mapa `hooks:` com chave pelos eventos snake\_case do Hermes (`pre_tool_call` / `post_tool_call` / `on_session_start` / `on_session_end` / `subagent_stop`); o handler canonicaliza eventos via `HERMES_EVENT_MAP` e nomes de ferramentas via `HERMES_TOOL_MAP` para que as políticas integradas disparem sem alteração. A configuração é editada por meio de uma edição de ida e volta de `Document` YAML que preserva comentários, para que as outras configurações do operador sobrevivam, e a instalação define `hooks_auto_accept: true` para que o gateway headless (sem TTY) execute os hooks sem uma solicitação de consentimento. O avaliador emite o contrato stdout `{"decision":"block","reason"}` do Hermes (o Hermes ignora códigos de saída). **Limitações:** O Hermes não possui evento `Stop` de fim de turno, portanto as políticas integradas `require-*-before-stop` nunca disparam para ele (inaplicável, não quebrado); `instruct` é rebaixado para allow com nota registrada (sem canal de contexto adicional); e a redação de segredos na saída (`sanitize-*`) não pode reescrever a saída das ferramentas pelo contrato de hook de shell. O Hermes é **também** uma fonte de **auditoria** offline — o dashboard lê suas sessões de gateway diretamente de `~/.hermes/state.db`.
* **`policies-config.json`** — informa ao failproofai quais políticas avaliar e com quais parâmetros (compartilhado entre todos os agentes CLI)

Passe `--cli claude|codex|copilot|cursor|opencode|pi|hermes` para direcionar um agente específico (separado por espaço ou repetido para qualquer subconjunto):

```bash theme={null}
failproofai policies --install --cli codex --scope project
failproofai policies --install --cli copilot --scope project
failproofai policies --install --cli cursor --scope project
failproofai policies --install --cli opencode --scope project
failproofai policies --install --cli pi --scope project
failproofai policies --install --cli hermes --scope user
failproofai policies --install --cli claude codex copilot cursor opencode pi
```

Quando `--cli` é omitido, `failproofai` detecta quais agentes CLI estão instalados (`which claude` / `which codex` / `which copilot` / `which cursor-agent` / `which opencode` / `which pi` / `which hermes`):

* **Um CLI detectado** — seleciona automaticamente esse CLI sem solicitar confirmação.
* **Vários CLIs detectados** em um terminal interativo — exibe um prompt de seleção única com teclas de seta, agrupado em uma seção `Detected (N)` (com uma linha agregada `Install for all N detected` + cada CLI detectado individualmente) e uma seção `Not installed (M) · install hooks ahead of time` listando todos os CLIs suportados não detectados como opções de instalação antecipada (↑↓ para mover, Enter para selecionar, ^C para sair). O fluxo de desinstalação exibe apenas a seção Detected.
* **Vários CLIs detectados** em uma execução não interativa (CI, sem TTY) — instala para todos os CLIs detectados sem solicitar confirmação.
* **Nenhum detectado** — retorna para `claude`, com um aviso de que nenhum binário de agente foi encontrado no PATH; o comando de hook ainda é escrito para que seja ativado assim que você instalar um.

Você pode editar `policies-config.json` diretamente a qualquer momento; as alterações entram em vigor imediatamente no próximo evento de hook, sem necessidade de reinicialização.

***

## Exemplo: configuração no nível de projeto com padrões da equipe

Faça o commit de `.failproofai/policies-config.json` no seu repositório:

```json theme={null}
{
  "enabledPolicies": [
    "block-sudo",
    "block-rm-rf",
    "block-push-master",
    "sanitize-api-keys",
    "block-env-files"
  ],
  "policyParams": {
    "block-push-master": {
      "protectedBranches": ["main", "release", "hotfix"]
    }
  }
}
```

Cada desenvolvedor pode então criar `.failproofai/policies-config.local.json` (incluído no gitignore) para substituições pessoais sem afetar os colegas de equipe.
