Vai al contenuto principale
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 - commitla nel tuo repository e ogni sviluppatore otterrà la stessa rete di sicurezza per gli agenti.

Ambiti di configurazione

Esistono tre ambiti di configurazione, valutati in ordine di priorità:
AmbitoPercorso fileScopo
project.failproofai/policies-config.jsonImpostazioni per-repo, commitmate nel controllo versione
local.failproofai/policies-config.local.jsonOverride personali per-repo, gitignored
global~/.failproofai/policies-config.jsonImpostazioni predefinite 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.
project:  ["block-sudo"]
local:    ["block-rm-rf"]
global:   ["block-sudo", "sanitize-api-keys"]

resolved: ["block-sudo", "block-rm-rf", "sanitize-api-keys"]  ← unione deduplicated
policyParams - il primo ambito che definisce i parametri per una determinata policy vince completamente. Non c’è merge profondo dei valori all’interno dei parametri di una policy.
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
project:  (nessuna voce block-sudo)
local:    (nessuna voce block-sudo)
global:   block-sudo → { allowPatterns: ["sudo systemctl status"] }

resolved: { allowPatterns: ["sudo systemctl status"] }  ← ricade su global
customPoliciesPath - il primo ambito che lo definisce vince. llm - il primo ambito che lo definisce vince.

Formato del file di configurazione

{
  "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 dei campi

enabledPolicies

Tipo: string[] Elenco di nomi di policy da abilitare. I nomi devono corrispondere esattamente agli identificatori di policy mostrati da failproofai policies. Consulta Built-in Policies per l’elenco completo. Le policy non in enabledPolicies sono inattive, anche se hanno voci in policyParams.

policyParams

Tipo: 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. Se una policy ha parametri ma non li specifichi, vengono utilizzati i valori predefiniti della policy. Gli utenti che non configurano affatto policyParams ottengono un comportamento identico alle versioni precedenti. Le chiavi sconosciute all’interno del blocco dei parametri di una policy vengono silenziosamente ignorate al momento dell’esecuzione dell’hook, ma contrassegnate come avvisi quando esegui failproofai policies.

hint (multi-policy)

Tipo: string (opzionale) Un messaggio aggiunto al motivo quando una policy restituisce deny o instruct. Usalo per dare a Claude una guida fruibile senza modificare la policy stessa. Funziona con qualsiasi tipo di policy — built-in, personalizzate (custom/), convenzione di progetto (.failproofai-project/), o convenzione utente (.failproofai-user/).
{
  "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 vede: “Force-pushing is blocked. Try creating a fresh branch instead.” I valori non stringa e le stringhe vuote vengono silenziosamente ignorati. Se hint non è impostato, il comportamento è invariato (retrocompatibile).

customPoliciesPath

Tipo: string (percorso assoluto) Percorso di un file JavaScript contenente policy di hook personalizzate. Viene impostato automaticamente da failproofai policies --install --custom <path> (il percorso viene risolto in assoluto prima di essere memorizzato). Il file viene caricato di nuovo su ogni evento hook - non c’è caching. Consulta Custom Policies per i dettagli di authoring.

Policy basate su convenzione

Oltre al customPoliciesPath esplicito, failproofai scopre e carica automaticamente i file di policy dalle directory .failproofai/policies/:
LivelloDirectoryAmbito
Project.failproofai/policies/Condiviso con il team tramite controllo versione
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). Altri file nella directory vengono ignorati. Nessuna configurazione necessaria: Le policy di convenzione non richiedono voci in policies-config.json. Basta rilasciare i file nella directory e verranno raccolti al prossimo evento hook. Caricamento unificato: Entrambe le directory di convenzione di progetto e utente vengono scansionate. Tutti i file corrispondenti da entrambi i livelli vengono caricati (a differenza di customPoliciesPath che utilizza il primo ambito vince). Consulta Custom Policies per ulteriori dettagli ed esempi.

llm

Tipo: object (opzionale) Configurazione del client LLM per le policy che effettuano chiamate AI. Non richiesto per la maggior parte delle configurazioni.
{
  "llm": {
    "model": "claude-sonnet-4-6",
    "apiKey": "sk-ant-..."
  }
}

Gestione della configurazione dalla CLI

I comandi policies --install e policies --uninstall scrivono nel file delle impostazioni hook della tua CLI agente (i punti di ingresso hook), mentre policies-config.json è il file che gestisci direttamente. I due sono separati:
  • Impostazioni CLI agente — dice all’agente di chiamare failproofai --hook <event> su ogni tool use:
    • 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 ambito local. Le voci di hook utilizzano i campi di comando bash/powershell con chiave OS di Copilot con timeoutSec; il file porta un marcatore di livello superiore version: 1. Il supporto di Copilot CLI è beta mentre verifichiamo lo schema di registrazione di events.jsonl (che i documenti pubblici non specificano) rispetto a più sessioni nel mondo reale.
    • Cursor Agent (beta): ~/.cursor/hooks.json (user), <cwd>/.cursor/hooks.json (project) — Cursor non ha ambito local. Le voci di hook utilizzano il modulo a forma di Claude {type, command, timeout} (nessuna divisione bash/powershell), ma memorizzate sotto chiavi di evento camelCase (preToolUse, beforeSubmitPrompt, …) in un array piatto per lo schema di hook di Cursor](https://cursor.com/docs/hooks); il file porta un marcatore di livello superiore version: 1. Il gestore canonicalizza camelCase → PascalCase tramite CURSOR_EVENT_MAP in modo che le policy builtin esistenti si attivino invariate. Il supporto di Cursor Agent è beta mentre verifichiamo il formato di trascrizione di Cursor su disco (non specificato nei documenti pubblici) rispetto a più installazioni nel 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 ambito local. A differenza degli altri sei CLI, OpenCode ha nessun sistema di hook di comando esterno: carica i plugin JS/TS in-process esplicitamente registrati tramite l’array plugin: [] in opencode.json (l’auto-discovery da .opencode/plugins/ non è il modo in cui i plugin si caricano su opencode v1.14.33). L’installazione rilascia un piccolo plugin shim generato che esegue in subprocess il binario failproofai e traduce la risposta JSON a forma di Claude del binario nella semantica del plugin: throw new Error() per il deny di evento tool (annulla la chiamata dello strumento), client.session.prompt(...) per instruct E per Stop / SubagentStop deny (invia il motivo di deny come il prossimo messaggio utente — l’unico canale di retry forzato poiché session.idle è solo notifica e il lancio da esso è un no-op), e no-op per allow. Lo shim canonicalizza sia i nomi degli strumenti (minuscolo → PascalCase tramite OPENCODE_TOOL_MAP) che le chiavi degli argomenti di input degli strumenti (camelCase → snake_case tramite OPENCODE_TOOL_INPUT_MAP per Read / Write / Edit, ad es. filePathfile_path, oldStringold_string) prima di inoltrarli al binario, quindi i builtin di controllo del percorso come block-read-outside-cwd, block-env-files, e block-secrets-write si attivano invariati sulle chiamate di tool di OpenCode. Le sessioni vivono nel database SQLite di opencode a ~/.local/share/opencode/opencode.db; il visualizzatore di sessioni del dashboard li legge tramite opencode db --format json e opencode export <id>. Il supporto di OpenCode è beta mentre verifichiamo il comportamento su versioni e rispetto a più sessioni nel mondo reale. Consulta la documentazione dei plugin OpenCode.
    • Pi (beta): ~/.pi/agent/settings.json (user), <cwd>/.pi/settings.json (project) — Pi non ha ambito local. Pi carica pacchetti di estensione 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 iscrive agli eventi tool_call / user_bash / input / session_start di Pi e esegue il shelling in failproofai --hook <Event> --cli pi; il gestore canonicalizza underscore_lower_snake_case → PascalCase tramite PI_EVENT_MAP in modo che le policy builtin esistenti si attivino invariate. Gli argomenti di input degli strumenti vengono anche canonicalizzati tramite PI_TOOL_INPUT_MAP (Pi’s Read / Write / Edit forniscono path piuttosto che file_path; il mapping della chiave di livello superiore consente a block-env-files e block-secrets-write di attivarsi — block-read-outside-cwd aveva già un fallback path). Il supporto di Pi è beta mentre l’API di estensione di Pi e il layout del log di sessione si stabilizzano.
    • Gemini CLI (beta): ~/.gemini/settings.json (user), <cwd>/.gemini/settings.json (project) — Gemini non ha ambito local (documenta un ambito system a /etc/gemini-cli/settings.json che failproofai non espone). Le voci di hook utilizzano il modulo {type, command, timeout} di Claude racchiuso nello schema matcher {matcher, hooks: [...]} di Gemini con matcher: "*" per impostazione predefinita. Gli eventi sono PascalCase (SessionStart, BeforeAgent, AfterAgent, BeforeModel, AfterModel, BeforeToolSelection, BeforeTool, AfterTool, PreCompress, Notification, SessionEnd); il gestore mappa ai nomi canonici di Claude tramite GEMINI_EVENT_MAP. I nomi degli strumenti sono snake_case (run_shell_command, read_file, write_file, replace, …) — il gestore canonicalizza tramite GEMINI_TOOL_MAP in modo che i policy builtin esistenti si attivino invariati. L’evaluator di policy emette la forma piatta {decision: "deny", reason} di Gemini (preferita per il contratto exit-0 della regola d’oro di Gemini), {hookSpecificOutput: {hookEventName, additionalContext}} per l’iniezione di contesto su BeforeAgent / AfterTool / SessionStart, e {decision: "block", reason} su AfterAgent per la semantica di retry forzato. Il supporto di Gemini CLI è beta mentre aumentiamo la copertura nel mondo reale. Consulta la documentazione degli hook di Gemini CLI.
  • policies-config.json — dice a failproofai quali policy valutare e con quali parametri (condiviso su tutti i CLI agente)
Passa --cli claude|codex|copilot|cursor|opencode|pi|gemini per target un agente specifico (spazio-separato o ripetuto per qualsiasi sottoinsieme):
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 gemini --scope project
failproofai policies --install --cli claude codex copilot cursor opencode pi gemini
Quando --cli è omesso, failproofai rileva quali CLI agente sono installati (which claude / which codex / which copilot / which cursor-agent / which opencode / which pi / which gemini):
  • Un CLI rilevato — seleziona automaticamente quel CLI senza richiedere conferma.
  • Più CLI rilevati in un terminale interattivo — mostra un prompt single-select con freccia raggruppato 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 supportato non rilevato come opzione di installazione anticipata (↑↓ 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 richiedere conferma.
  • Nessuno rilevato — ricade su claude, con un avviso che nessun binario agente è stato trovato in PATH; il comando hook viene comunque scritto in modo che si attivi non appena ne installi uno.
Puoi modificare policies-config.json direttamente in qualsiasi momento; le modifiche hanno effetto immediatamente sul prossimo evento hook senza necessità di riavvio.

Esempio: configurazione a livello di progetto con impostazioni predefinite del team

Commita .failproofai/policies-config.json nel tuo repository:
{
  "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.