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

# Configurazione

> Formato file di configurazione, sistema a tre livelli e regole di merge

failproofai utilizza file di configurazione JSON per controllare quali policy sono attive, come si comportano e da dove vengono caricate le policy personalizzate. La configurazione è progettata per essere facile da condividere con il tuo team - commitatela nel tuo repo e ogni sviluppatore avrà la stessa rete di protezione dell'agent.

***

## Ambiti di configurazione

Ci sono tre ambiti di configurazione, valutati in ordine di priorità:

| Ambito      | Percorso file                             | Scopo                                                 |
| ----------- | ----------------------------------------- | ----------------------------------------------------- |
| **project** | `.failproofai/policies-config.json`       | Impostazioni per-repo, committate nel version control |
| **local**   | `.failproofai/policies-config.local.json` | Override personali per-repo, gitignorate              |
| **global**  | `~/.failproofai/policies-config.json`     | Default a livello utente su tutti i progetti          |

Quando failproofai riceve un evento hook, carica e unisce tutti e tre i file che esistono per la directory di lavoro corrente.

### Regole di merge

**`enabledPolicies`** - l'unione di tutti e tre gli ambiti. Una policy abilitata a qualsiasi livello è attiva.

```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"]  ← unione deduplificata
```

**`policyParams`** - il primo ambito che definisce parametri per una data policy vince interamente. Non c'è merging profondo di valori all'interno dei parametri di una policy.

```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 vince, global ignorato
```

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

resolved: { allowPatterns: ["sudo systemctl status"] }  ← fallback a global
```

**`customPoliciesPath`** - il primo ambito che lo definisce vince.

**`llm`** - il primo ambito che lo definisce vince.

***

## Formato file di configurazione

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

***

## Riferimento campi

### `enabledPolicies`

Type: `string[]`

Elenco dei nomi di policy da abilitare. I nomi devono corrispondere esattamente agli identificatori di policy mostrati da `failproofai policies`. Vedi [Built-in Policies](/it/built-in-policies) per l'elenco completo.

Le policy non in `enabledPolicies` sono inattive, anche se hanno voci in `policyParams`.

### `policyParams`

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

Override di parametri per-policy. La chiave esterna è il nome della policy; le chiavi interne sono specifiche della policy. Ogni policy documenta i suoi parametri disponibili in [Built-in Policies](/it/built-in-policies).

Se una policy ha parametri ma non li specifichi, vengono utilizzati i default built-in della policy. Gli utenti che non configurano `policyParams` affatto otterranno un comportamento identico alle versioni precedenti.

Le chiavi sconosciute all'interno del blocco dei parametri di una policy sono silenziosamente ignorate al momento dello scatto dell'hook ma segnalate come avvisi quando esegui `failproofai policies`.

#### `hint` (cross-cutting)

Type: `string` (optional)

Un messaggio aggiunto alla ragione quando una policy restituisce `deny` o `instruct`. Usalo per fornire a Claude una guida praticabile senza modificare la policy stessa.

Funziona con qualsiasi tipo di policy — built-in, custom (`custom/`), project convention (`.failproofai-project/`), o user convention (`.failproofai-user/`).

```json theme={null}
{
  "policyParams": {
    "block-force-push": {
      "hint": "Prova a creare invece un nuovo branch."
    },
    "block-sudo": {
      "allowPatterns": ["sudo apt-get"],
      "hint": "Usa apt-get direttamente senza sudo."
    },
    "custom/my-policy": {
      "hint": "Chiedi l'approvazione all'utente prima."
    }
  }
}
```

Quando `block-force-push` nega, Claude vede: *"Il force-push è bloccato. Prova a creare invece un nuovo branch."*

I valori non-string e le stringhe vuote sono silenziosamente ignorati. Se `hint` non è impostato, il comportamento è invariato (backward-compatible).

### `customPoliciesPath`

Type: `string` (absolute path)

Percorso di un file JavaScript contenente policy hook personalizzate. Questo è impostato automaticamente da `failproofai policies --install --custom <path>` (il percorso è risolto ad assoluto prima di essere memorizzato).

Il file viene caricato fresco ad ogni evento hook - non c'è caching. Vedi [Custom Policies](/it/custom-policies) per i dettagli di authoring.

### Policy basate su convenzione

In aggiunta a `customPoliciesPath` esplicito, failproofai scopre automaticamente e carica file di policy dalle directory `.failproofai/policies/`:

| Livello | Directory                  | Ambito                                        |
| ------- | -------------------------- | --------------------------------------------- |
| Project | `.failproofai/policies/`   | Condiviso con il team tramite version control |
| User    | `~/.failproofai/policies/` | Personale, si applica a tutti i progetti      |

**Corrispondenza file:** Solo i file che corrispondono a `*policies.{js,mjs,ts}` vengono caricati (ad es. `security-policies.mjs`, `workflow-policies.js`). Gli altri file nella directory sono ignorati.

**Nessuna configurazione necessaria:** Le policy di convenzione non richiedono voci in `policies-config.json`. Basta inserire i file nella directory e verranno raccolti al prossimo evento hook.

**Caricamento unione:** Entrambe le directory di convenzione di project e user vengono scansionate. Tutti i file corrispondenti da entrambi i livelli vengono caricati (a differenza di `customPoliciesPath` che usa il primo-ambito-vince).

Vedi [Custom Policies](/it/custom-policies) per più dettagli ed esempi.

### `llm`

Type: `object` (optional)

Configurazione del client LLM per le policy che effettuano chiamate AI. Non richiesta per la maggior parte delle configurazioni.

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

***

## Gestione della configurazione dalla CLI

I comandi `policies --install` e `policies --uninstall` scrivono nel file di impostazioni hook della CLI del tuo agent (i punti di ingresso dell'hook), mentre `policies-config.json` è il file che gestisci direttamente. I due sono separati:

* **Impostazioni agent CLI** — dice all'agent di chiamare `failproofai --hook <event>` ad ogni uso di strumento:
  * **Claude Code**: `~/.claude/settings.json` (user), `<cwd>/.claude/settings.json` (project), `<cwd>/.claude/settings.local.json` (local)
  * **OpenAI Codex**: `~/.codex/hooks.json` (user), `<cwd>/.codex/hooks.json` (project) — Codex non ha un ambito `local`
  * **GitHub Copilot CLI *(beta)***: `~/.copilot/hooks/failproofai.json` (user), `<cwd>/.github/hooks/failproofai.json` (project) — Copilot non ha un ambito `local`. Le voci hook usano i campi di comando `bash`/`powershell` di Copilot con chiave OS e `timeoutSec`; il file porta un marcatore `version: 1` di alto livello. Il supporto di Copilot CLI è **beta** mentre verifichiamo lo schema del record `events.jsonl` (che la documentazione pubblica non specifica) rispetto a più sessioni del mondo reale.
  * **Cursor Agent *(beta)***: `~/.cursor/hooks.json` (user), `<cwd>/.cursor/hooks.json` (project) — Cursor non ha un ambito `local`. Le voci hook usano la forma `{type, command, timeout}` a forma di Claude (senza split `bash`/`powershell`), ma memorizzate sotto chiavi di evento camelCase (`preToolUse`, `beforeSubmitPrompt`, …) in un array piatto per lo [schema degli hook](https://cursor.com/docs/hooks) di Cursor; il file porta un marcatore `version: 1` di alto livello. Il gestore canonicalizza camelCase → PascalCase tramite `CURSOR_EVENT_MAP` quindi le policy built-in esistenti si attivano invariate. Il supporto di Cursor Agent è **beta** mentre verifichiamo il formato del transcript di Cursor su disco (non specificato nella documentazione pubblica) rispetto a più installazioni del mondo reale.
  * **OpenCode *(beta)***: `~/.config/opencode/opencode.json` + `~/.config/opencode/plugins/failproofai.mjs` (user), `<cwd>/.opencode/opencode.json` + `<cwd>/.opencode/plugins/failproofai.mjs` (project) — OpenCode non ha un ambito `local`. A differenza degli altri cinque CLI, OpenCode ha **nessun sistema di hook per comando esterno**: carica plugin JS/TS in-process esplicitamente registrati tramite l'array `plugin: []` in `opencode.json` (l'auto-discovery da `.opencode/plugins/` **non** è come i plugin vengono caricati su opencode v1.14.33). L'installazione rilascia un piccolo shim plugin generato che subprocess-chiama il binario failproofai e traduce la risposta JSON a forma di Claude del binario di nuovo in semantica plugin: `throw new Error()` per tool-event deny (cancella la chiamata dello strumento), `client.session.prompt(...)` per instruct E per deny di `Stop` / `SubagentStop` (invia la ragione di deny come prossimo messaggio utente — l'unico canale force-retry dal momento che `session.idle` è notification-only e gettare da essa è un no-op), e no-op per allow. Lo shim canonicalizza sia i nomi di strumento (lowercase → PascalCase tramite `OPENCODE_TOOL_MAP`) che le chiavi degli argomenti di input dello strumento (camelCase → snake\_case tramite `OPENCODE_TOOL_INPUT_MAP` per `Read` / `Write` / `Edit`, ad es. `filePath` → `file_path`, `oldString` → `old_string`) prima di inoltrarsi al binario, così il controllo dei percorsi built-in come `block-read-outside-cwd`, `block-env-files`, e `block-secrets-write` si attivano invariate sulle chiamate agli strumenti di OpenCode. Le sessioni vivono nel DB SQLite di opencode presso `~/.local/share/opencode/opencode.db`; il visualizzatore di sessioni della dashboard li legge tramite `opencode db --format json` e `opencode export <id>`. Il supporto di OpenCode è **beta** mentre verifichiamo il comportamento attraverso versioni e rispetto a più sessioni del mondo reale. Vedi la [documentazione dei plugin di OpenCode](https://opencode.ai/docs/plugins/).
  * **Pi *(beta)***: `~/.pi/agent/settings.json` (user), `<cwd>/.pi/settings.json` (project) — Pi non ha un ambito `local`. Pi carica pacchetti di estensioni TypeScript all'avvio; il file di impostazioni è un array di stringhe piatto `{"packages": ["./relative/path", …]}`. failproofai scrive una singola voce dell'array dei pacchetti che punta alla sua directory `pi-extension/` in bundle. L'estensione internamente si sottoscrive agli eventi `tool_call` / `user_bash` / `input` / `session_start` di Pi e guscio fuori a `failproofai --hook <Event> --cli pi`; il gestore canonicalizza underscore\_lower\_snake\_case → PascalCase tramite `PI_EVENT_MAP` quindi le policy built-in esistenti si attivano invariate. Gli argomenti di input dello strumento sono anche canonicalizzati tramite `PI_TOOL_INPUT_MAP` (Pi's Read / Write / Edit forniscono `path` piuttosto che `file_path`; mappare la chiave di top-level lascia che `block-env-files` e `block-secrets-write` si attivino — `block-read-outside-cwd` già aveva un fallback `path`). Il supporto di Pi è **beta** mentre l'API di estensione di Pi e il layout del log di sessione si stabilizzano.
  * **Hermes (hermes-agent)**: `~/.hermes/config.yaml` (**ambito utente solo** — Hermes non ha configurazione project/local). Hermes è un gateway **Slack/Telegram**, quindi un'installazione intercetta le chiamate di strumento da ogni piattaforma (Slack/Telegram/cli/cron) **e** subagent interni. Le voci hook sono una coppia `{command, timeout}` (timeout in **secondi**) sotto una mappa `hooks:` codificata dagli eventi snake\_case di Hermes (`pre_tool_call` / `post_tool_call` / `on_session_start` / `on_session_end` / `subagent_stop`); il gestore canonicalizza gli eventi tramite `HERMES_EVENT_MAP` e i nomi di strumento tramite `HERMES_TOOL_MAP` quindi le policy built-in si attivano invariate. La configurazione è modificata tramite una `Document` YAML di preservazione dei commenti round-trip in modo che le altre impostazioni dell'operatore sopravvivano, e l'installazione imposta `hooks_auto_accept: true` così il gateway headless (no TTY) esegue gli hook senza un prompt di consenso. L'evaluator emette il contratto stdout `{"decision":"block","reason"}` di Hermes (Hermes ignora i codici di uscita). **Limitazioni:** Hermes non ha un evento end-turn `Stop`, quindi le policy built-in `require-*-before-stop` non si attivano mai per esso (inapplicabile, non rotto); `instruct` degrada a allow-with-logged-note (nessun canale additional-context); e la redazione di secret di output (`sanitize-*`) non può riscrivere l'output dello strumento sul contratto dell'hook di shell. Hermes è **anche** una fonte di **audit** offline — la dashboard legge le sue sessioni di gateway direttamente da `~/.hermes/state.db`.
* **`policies-config.json`** — dice a failproofai quali policy valutare e con quali parametri (condiviso su tutti gli agent CLI)

Passa `--cli claude|codex|copilot|cursor|opencode|pi|hermes` per indirizzare un agent specifico (space-separated o ripetuto per qualsiasi subset):

```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` è omesso, `failproofai` rileva quali agent CLI sono installati (`which claude` / `which codex` / `which copilot` / `which cursor-agent` / `which opencode` / `which pi` / `which hermes`):

* **Un CLI rilevato** — auto-seleziona quel CLI senza chiedere.
* **Più CLI rilevati** in un terminale interattivo — mostra un prompt single-select con tasti freccia raggruppati in una sezione `Detected (N)` (con una riga aggregata `Install for all N detected` + ogni CLI rilevato singolarmente) e una sezione `Not installed (M) · install hooks ahead of time` che elenca ogni CLI non rilevato supportato come opzione forward-install (↑↓ per muoversi, Enter per selezionare, ^C per uscire). Il flusso di disinstallazione mostra solo la sezione Detected.
* **Più CLI rilevati** in un'esecuzione non-interattiva (CI, no TTY) — installa per tutti i CLI rilevati senza chiedere.
* **Nessuno rilevato** — fallback a `claude`, con un avviso che nessun binario di agent è stato trovato in PATH; il comando hook è ancora scritto quindi si attiva non appena ne installi uno.

Puoi modificare `policies-config.json` direttamente in qualsiasi momento; le modifiche hanno effetto immediatamente al prossimo evento hook senza necessità di restart.

***

## Esempio: configurazione a livello di project con default del team

Committa `.failproofai/policies-config.json` nel tuo repo:

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

Ogni sviluppatore può quindi creare `.failproofai/policies-config.local.json` (gitignored) per override personali senza influenzare i compagni di squadra.
