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

# Configuración

> Formato de archivo de configuración, sistema de tres ámbitos y reglas de combinación

failproofai utiliza archivos de configuración JSON para controlar qué políticas están activas, cómo se comportan y desde dónde se cargan las políticas personalizadas. La configuración está diseñada para compartirse fácilmente con tu equipo: confírmala en tu repositorio y todos los desarrolladores tendrán la misma red de seguridad para el agente.

***

## Ámbitos de configuración

Existen tres ámbitos de configuración, evaluados en orden de prioridad:

| Ámbito      | Ruta del archivo                          | Propósito                                                         |
| ----------- | ----------------------------------------- | ----------------------------------------------------------------- |
| **project** | `.failproofai/policies-config.json`       | Configuración por repositorio, confirmada en control de versiones |
| **local**   | `.failproofai/policies-config.local.json` | Sobreescrituras personales por repositorio, ignoradas por git     |
| **global**  | `~/.failproofai/policies-config.json`     | Valores predeterminados de usuario para todos los proyectos       |

Cuando failproofai recibe un evento de hook, carga y combina los tres archivos que existen para el directorio de trabajo actual.

### Reglas de combinación

**`enabledPolicies`** — la unión de los tres ámbitos. Una política habilitada en cualquier nivel está activa.

```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ón sin duplicados
```

**`policyParams`** — el primer ámbito que define parámetros para una política determinada gana por completo. No hay combinación profunda de valores dentro de los parámetros de una 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 gana, global se ignora
```

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

resolved: { allowPatterns: ["sudo systemctl status"] }  ← se aplica global como respaldo
```

**`customPoliciesPath`** — el primer ámbito que lo defina gana.

**`llm`** — el primer ámbito que lo defina gana.

***

## Formato del archivo de configuración

```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"
}
```

***

## Referencia de campos

### `enabledPolicies`

Tipo: `string[]`

Lista de nombres de políticas a habilitar. Los nombres deben coincidir exactamente con los identificadores de política que muestra `failproofai policies`. Consulta [Políticas integradas](/es/built-in-policies) para ver la lista completa.

Las políticas que no están en `enabledPolicies` están inactivas, aunque tengan entradas en `policyParams`.

### `policyParams`

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

Sobreescrituras de parámetros por política. La clave exterior es el nombre de la política; las claves internas son específicas de cada política. Cada política documenta sus parámetros disponibles en [Políticas integradas](/es/built-in-policies).

Si una política tiene parámetros pero no los especificas, se utilizan los valores predeterminados integrados de la política. Los usuarios que no configuran `policyParams` en absoluto obtienen un comportamiento idéntico al de versiones anteriores.

Las claves desconocidas dentro del bloque de parámetros de una política se ignoran silenciosamente en el momento de la ejecución del hook, pero se marcan como advertencias cuando ejecutas `failproofai policies`.

#### `hint` (transversal)

Tipo: `string` (opcional)

Un mensaje que se añade al motivo cuando una política devuelve `deny` o `instruct`. Úsalo para darle a Claude orientación accionable sin modificar la política en sí.

Funciona con cualquier tipo de política: integrada, personalizada (`custom/`), convención de proyecto (`.failproofai-project/`) o convención de usuario (`.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."
    }
  }
}
```

Cuando `block-force-push` deniega, Claude ve: *"Se ha bloqueado el force-push. Try creating a fresh branch instead."*

Los valores que no son cadenas de texto y las cadenas vacías se ignoran silenciosamente. Si no se define `hint`, el comportamiento no cambia (compatible con versiones anteriores).

### `customPoliciesPath`

Tipo: `string` (ruta absoluta)

Ruta a un archivo JavaScript que contiene políticas de hook personalizadas. Este valor lo establece automáticamente `failproofai policies --install --custom <path>` (la ruta se resuelve a absoluta antes de almacenarse).

El archivo se carga de nuevo en cada evento de hook; no hay caché. Consulta [Políticas personalizadas](/es/custom-policies) para ver los detalles de creación.

### Políticas basadas en convenciones

Además del `customPoliciesPath` explícito, failproofai descubre y carga automáticamente archivos de políticas desde directorios `.failproofai/policies/`:

| Nivel    | Directorio                 | Ámbito                                                 |
| -------- | -------------------------- | ------------------------------------------------------ |
| Proyecto | `.failproofai/policies/`   | Compartido con el equipo mediante control de versiones |
| Usuario  | `~/.failproofai/policies/` | Personal, se aplica a todos los proyectos              |

**Coincidencia de archivos:** Solo se cargan los archivos que coincidan con `*policies.{js,mjs,ts}` (p. ej., `security-policies.mjs`, `workflow-policies.js`). Los demás archivos del directorio se ignoran.

**Sin configuración necesaria:** Las políticas de convención no requieren entradas en `policies-config.json`. Simplemente coloca los archivos en el directorio y se detectarán en el próximo evento de hook.

**Carga por unión:** Se analizan tanto el directorio de convenciones del proyecto como el del usuario. Se cargan todos los archivos coincidentes de ambos niveles (a diferencia de `customPoliciesPath`, que usa el primero que gana por ámbito).

Consulta [Políticas personalizadas](/es/custom-policies) para más detalles y ejemplos.

### `llm`

Tipo: `object` (opcional)

Configuración del cliente LLM para políticas que realizan llamadas a IA. No es necesario en la mayoría de los casos.

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

***

## Gestión de la configuración desde la CLI

Los comandos `policies --install` y `policies --uninstall` escriben en el archivo de configuración de hooks de tu CLI de agente (los puntos de entrada del hook), mientras que `policies-config.json` es el archivo que gestionas directamente. Son dos cosas separadas:

* **Configuración de la CLI del agente** — indica al agente que llame a `failproofai --hook <event>` en cada uso de herramienta:
  * **Claude Code**: `~/.claude/settings.json` (usuario), `<cwd>/.claude/settings.json` (proyecto), `<cwd>/.claude/settings.local.json` (local)
  * **OpenAI Codex**: `~/.codex/hooks.json` (usuario), `<cwd>/.codex/hooks.json` (proyecto) — Codex no tiene ámbito `local`
  * **GitHub Copilot CLI *(beta)***: `~/.copilot/hooks/failproofai.json` (usuario), `<cwd>/.github/hooks/failproofai.json` (proyecto) — Copilot no tiene ámbito `local`. Las entradas de hook usan los campos de comando `bash`/`powershell` de Copilot según el sistema operativo con `timeoutSec`; el archivo lleva un marcador `version: 1` de nivel superior. El soporte de Copilot CLI está en **beta** mientras verificamos el esquema de registros `events.jsonl` (que la documentación pública no especifica) con más sesiones reales.
  * **Cursor Agent *(beta)***: `~/.cursor/hooks.json` (usuario), `<cwd>/.cursor/hooks.json` (proyecto) — Cursor no tiene ámbito `local`. Las entradas de hook usan la forma de Claude `{type, command, timeout}` (sin división `bash`/`powershell`), pero almacenadas bajo claves de evento en camelCase (`preToolUse`, `beforeSubmitPrompt`, …) en un array plano según el [esquema de hooks de Cursor](https://cursor.com/docs/hooks); el archivo lleva un marcador `version: 1` de nivel superior. El manejador canonicaliza camelCase → PascalCase mediante `CURSOR_EVENT_MAP`, de modo que las políticas integradas existentes se activan sin cambios. El soporte de Cursor Agent está en **beta** mientras verificamos el formato en disco de la transcripción de Cursor (no especificado en la documentación pública) con más instalaciones reales.
  * **OpenCode *(beta)***: `~/.config/opencode/opencode.json` + `~/.config/opencode/plugins/failproofai.mjs` (usuario), `<cwd>/.opencode/opencode.json` + `<cwd>/.opencode/plugins/failproofai.mjs` (proyecto) — OpenCode no tiene ámbito `local`. A diferencia de las otras cinco CLIs, OpenCode **no tiene un sistema de hooks de comandos externos**: carga plugins JS/TS en proceso registrados explícitamente mediante el array `plugin: []` en `opencode.json` (el autodescubrimiento desde `.opencode/plugins/` **no** es cómo se cargan los plugins en opencode v1.14.33). La instalación coloca un pequeño shim de plugin generado que llama al binario failproofai como subproceso y traduce la respuesta JSON de forma Claude del binario de vuelta a la semántica del plugin: `throw new Error()` para denegar eventos de herramienta (cancela la llamada a la herramienta), `client.session.prompt(...)` para instruct Y para `Stop` / `SubagentStop` deny (envía el motivo de denegación como el siguiente mensaje del usuario — el único canal de reintento forzado, ya que `session.idle` es solo notificación y lanzar desde él es un no-op), y no-op para allow. El shim canonicaliza tanto los nombres de herramientas (minúsculas → PascalCase mediante `OPENCODE_TOOL_MAP`) como las claves de argumentos de entrada de herramientas (camelCase → snake\_case mediante `OPENCODE_TOOL_INPUT_MAP` para `Read` / `Write` / `Edit`, p. ej. `filePath` → `file_path`, `oldString` → `old_string`) antes de reenviar al binario, de modo que las políticas integradas de verificación de rutas como `block-read-outside-cwd`, `block-env-files` y `block-secrets-write` se activan sin cambios en las llamadas a herramientas de OpenCode. Las sesiones viven en la base de datos SQLite de opencode en `~/.local/share/opencode/opencode.db`; el visor de sesiones del panel las lee mediante `opencode db --format json` y `opencode export <id>`. El soporte de OpenCode está en **beta** mientras verificamos el comportamiento en distintas versiones y con más sesiones reales. Consulta la [documentación de plugins de OpenCode](https://opencode.ai/docs/plugins/).
  * **Pi *(beta)***: `~/.pi/agent/settings.json` (usuario), `<cwd>/.pi/settings.json` (proyecto) — Pi no tiene ámbito `local`. Pi carga paquetes de extensiones TypeScript al inicio; el archivo de configuración es un array de cadenas plano `{"packages": ["./relative/path", …]}`. failproofai escribe una única entrada en el array de packages apuntando a su directorio `pi-extension/` integrado. La extensión se suscribe internamente a los eventos `tool_call` / `user_bash` / `input` / `session_start` de Pi y ejecuta `failproofai --hook <Event> --cli pi` como proceso hijo; el manejador canonicaliza eventos de snake\_case en minúsculas → PascalCase mediante `PI_EVENT_MAP` para que las políticas integradas existentes se activen sin cambios. Los argumentos de entrada de herramientas también se canonizan mediante `PI_TOOL_INPUT_MAP` (Pi's Read / Write / Edit entregan `path` en lugar de `file_path`; mapear la clave de nivel superior permite que `block-env-files` y `block-secrets-write` se activen — `block-read-outside-cwd` ya tenía un respaldo con `path`). El soporte de Pi está en **beta** mientras la API de extensiones de Pi y el diseño del registro de sesiones se estabilizan.
  * **Hermes (hermes-agent)**: `~/.hermes/config.yaml` (**solo ámbito de usuario** — Hermes no tiene configuración de proyecto/local). Hermes es una **pasarela** de Slack/Telegram, por lo que una instalación intercepta las llamadas a herramientas de todas las plataformas (Slack/Telegram/cli/cron) **y** de los subagentes internos. Las entradas de hook son un par `{command, timeout}` (tiempo de espera en **segundos**) bajo un mapa `hooks:` indexado por los eventos snake\_case de Hermes (`pre_tool_call` / `post_tool_call` / `on_session_start` / `on_session_end` / `subagent_stop`); el manejador canonicaliza los eventos mediante `HERMES_EVENT_MAP` y los nombres de herramientas mediante `HERMES_TOOL_MAP` para que las políticas integradas se activen sin cambios. La configuración se edita mediante un round-trip YAML `Document` que preserva los comentarios, de modo que los demás ajustes del operador sobreviven, y la instalación establece `hooks_auto_accept: true` para que la pasarela sin cabeza (sin TTY) ejecute los hooks sin solicitud de consentimiento. El evaluador emite el contrato stdout `{"decision":"block","reason"}` de Hermes (Hermes ignora los códigos de salida). **Limitaciones:** Hermes no tiene un evento `Stop` de fin de turno, por lo que las políticas integradas `require-*-before-stop` nunca se activan para él (no aplicable, no roto); `instruct` degrada a allow con nota registrada (sin canal de contexto adicional); y la redacción de secretos en la salida (`sanitize-*`) no puede reescribir la salida de herramientas a través del contrato de hook de shell. Hermes es también una fuente de **auditoría** sin conexión — el panel lee sus sesiones de pasarela directamente desde `~/.hermes/state.db`.
* **`policies-config.json`** — indica a failproofai qué políticas evaluar y con qué parámetros (compartido entre todas las CLIs de agentes)

Pasa `--cli claude|codex|copilot|cursor|opencode|pi|hermes` para apuntar a un agente específico (separados por espacios o repetidos para cualquier 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
```

Cuando se omite `--cli`, `failproofai` detecta qué CLIs de agentes están instaladas (`which claude` / `which codex` / `which copilot` / `which cursor-agent` / `which opencode` / `which pi` / `which hermes`):

* **Una CLI detectada** — la selecciona automáticamente sin solicitar confirmación.
* **Múltiples CLIs detectadas** en un terminal interactivo — muestra un prompt de selección única con teclas de flecha, agrupado en una sección `Detected (N)` (con una fila agregada `Install for all N detected` + cada CLI detectada individualmente) y una sección `Not installed (M) · install hooks ahead of time` que lista cada CLI compatible no detectada como opción de instalación anticipada (↑↓ para moverse, Enter para seleccionar, ^C para salir). El flujo de desinstalación muestra solo la sección Detected.
* **Múltiples CLIs detectadas** en una ejecución no interactiva (CI, sin TTY) — instala para todas las CLIs detectadas sin solicitar confirmación.
* **Ninguna detectada** — recurre a `claude`, con una advertencia de que no se encontró ningún binario de agente en el PATH; el comando de hook se escribe de todas formas para que se active en cuanto instales uno.

Puedes editar `policies-config.json` directamente en cualquier momento; los cambios surten efecto inmediatamente en el próximo evento de hook sin necesidad de reiniciar.

***

## Ejemplo: configuración a nivel de proyecto con valores predeterminados del equipo

Confirma `.failproofai/policies-config.json` en tu repositorio:

```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 desarrollador puede entonces crear `.failproofai/policies-config.local.json` (ignorado por git) para sobreescrituras personales sin afectar a sus compañeros de equipo.
