Skip to main content
failproofai 使用 JSON 配置文件来控制哪些策略处于启用状态、策略的行为方式,以及自定义策略的加载路径。配置设计上便于团队共享——将其提交到仓库,每位开发者都能获得相同的 AI 代理安全防护。

配置作用域

共有三个配置作用域,按优先级顺序评估: 当 failproofai 收到 hook 事件时,会加载并合并当前工作目录下所有已存在的三个文件。

合并规则

enabledPolicies — 取三个作用域的并集。任意级别启用的策略都会生效。
policyParams — 对某个策略最先定义其参数的作用域完全胜出,不会对策略参数内的值进行深度合并。
customPoliciesPath — 最先定义该字段的作用域胜出。 llm — 最先定义该字段的作用域胜出。

配置文件格式


字段参考

enabledPolicies

类型:string[] 需要启用的策略名称列表。名称必须与 failproofai policies 显示的策略标识符完全匹配。完整列表请参见内置策略 不在 enabledPolicies 中的策略将处于非活跃状态,即便在 policyParams 中为其配置了条目也不例外。

policyParams

类型:Record<string, Record<string, unknown>> 各策略的参数覆盖配置。外层键为策略名称,内层键为各策略专属的配置项。每个策略的可用参数请参见内置策略 如果策略有参数但未指定,则使用策略的内置默认值。未配置 policyParams 的用户其行为与之前版本完全一致。 策略参数块中未知的键在 hook 触发时会被静默忽略,但在运行 failproofai policies 时会作为警告标记出来。

hint(通用配置项)

类型:string(可选) 当策略返回 denyinstruct 时,附加到原因后面的消息。可用于在不修改策略本身的情况下,向 Claude 提供可操作的指引。 适用于任何类型的策略——内置策略、自定义策略(custom/)、项目约定策略(.failproofai-project/)或用户约定策略(.failproofai-user/)。
当 block-force-push 拒绝操作时,Claude 会看到:“Force-pushing is blocked. Try creating a fresh branch instead.” 非字符串值和空字符串会被静默忽略。若未设置 hint,行为保持不变(向后兼容)。

customPoliciesPath

类型:string(绝对路径) 包含自定义 hook 策略的 JavaScript 文件路径。该值由 failproofai policies --install --custom <path> 自动设置(路径在存储前会被解析为绝对路径)。 每次 hook 事件触发时都会重新加载该文件,不进行缓存。有关编写自定义策略的详情,请参见自定义策略

基于约定的策略

除了显式的 customPoliciesPath 外,failproofai 还会自动发现并加载 .failproofai/policies/ 目录中的策略文件: 文件匹配: 仅加载匹配 *policies.{js,mjs,ts} 的文件(例如 security-policies.mjsworkflow-policies.js),目录中的其他文件会被忽略。 无需配置: 约定策略无需在 policies-config.json 中添加任何条目,只需将文件放入对应目录,下次 hook 事件触发时即可自动生效。 联合加载: 项目和用户约定目录都会被扫描,两个级别中所有匹配的文件都会被加载(与 customPoliciesPath 采用首个作用域胜出的方式不同)。 更多详情和示例请参见自定义策略

llm

类型:object(可选) 供策略进行 AI 调用的 LLM 客户端配置,大多数场景下无需配置。

通过 CLI 管理配置

policies --installpolicies --uninstall 命令会写入代理 CLI 的 hook 设置文件(hook 入口点),而 policies-config.json 是由你直接管理的文件,两者相互独立:
  • 代理 CLI 设置 — 告知代理在每次工具调用时执行 failproofai --hook <event>
    • Claude Code~/.claude/settings.json(用户级)、<cwd>/.claude/settings.json(项目级)、<cwd>/.claude/settings.local.json(本地级)
    • OpenAI Codex~/.codex/hooks.json(用户级)、<cwd>/.codex/hooks.json(项目级)——Codex 没有 local 作用域
    • GitHub Copilot CLI (beta)~/.copilot/hooks/failproofai.json(用户级)、<cwd>/.github/hooks/failproofai.json(项目级)——Copilot 没有 local 作用域。Hook 条目使用 Copilot 基于操作系统的 bash/powershell 命令字段,并带有 timeoutSec;文件顶层包含 version: 1 标记。Copilot CLI 支持目前为 beta 版本,我们正在针对更多实际会话验证 events.jsonl 记录模式(公开文档中未作说明)。
    • Cursor Agent (beta)~/.cursor/hooks.json(用户级)、<cwd>/.cursor/hooks.json(项目级)——Cursor 没有 local 作用域。Hook 条目使用 Claude 风格的 {type, command, timeout} 格式(无 bash/powershell 拆分),但按照 Cursor 的 hooks schema 以驼峰式事件键(preToolUsebeforeSubmitPrompt 等)存储在扁平数组中;文件顶层包含 version: 1 标记。处理器通过 CURSOR_EVENT_MAP 将驼峰式键规范化为帕斯卡式,使现有内置策略能够正常触发。Cursor Agent 支持目前为 beta 版本,我们正在针对更多实际安装验证 Cursor 的磁盘上转录格式(公开文档未作说明)。
    • OpenCode (beta)~/.config/opencode/opencode.json + ~/.config/opencode/plugins/failproofai.mjs(用户级)、<cwd>/.opencode/opencode.json + <cwd>/.opencode/plugins/failproofai.mjs(项目级)——OpenCode 没有 local 作用域。与其他五种 CLI 不同,OpenCode 没有外部命令 hook 系统:它通过 opencode.jsonplugin: [] 数组显式注册来加载进程内 JS/TS 插件(自动发现 .opencode/plugins/ 目录不是 opencode v1.14.33 插件的加载方式)。安装时会生成一个小型插件 shim,以子进程方式调用 failproofai 二进制文件,并将二进制文件的 Claude 风格 JSON 响应转换回插件语义:工具事件拒绝时 throw new Error()(取消工具调用);instruct 以及 Stop / SubagentStop 拒绝时调用 client.session.prompt(...)(将拒绝原因作为下一条用户消息提交——这是唯一的强制重试通道,因为 session.idle 仅用于通知,从中抛出异常无效);allow 时不执行任何操作。该 shim 在转发给二进制文件前会规范化工具名称(小写 → 帕斯卡式,通过 OPENCODE_TOOL_MAP)和工具输入参数键(驼峰式 → 下划线式,通过 OPENCODE_TOOL_INPUT_MAP 适用于 Read / Write / Edit,例如 filePathfile_patholdStringold_string),从而使 block-read-outside-cwdblock-env-filesblock-secrets-write 等路径检查内置策略在 OpenCode 工具调用中正常触发。会话存储在 ~/.local/share/opencode/opencode.db 的 SQLite 数据库中;仪表盘的会话查看器通过 opencode db --format jsonopencode export <id> 读取它们。OpenCode 支持目前为 beta 版本,我们正在跨版本和更多实际会话中验证其行为。详见 OpenCode plugins 文档
    • Pi (beta)~/.pi/agent/settings.json(用户级)、<cwd>/.pi/settings.json(项目级)——Pi 没有 local 作用域。Pi 在启动时加载 TypeScript 扩展包;设置文件是一个扁平字符串数组 {"packages": ["./relative/path", …]}。failproofai 在 packages 数组中写入一个指向其捆绑的 pi-extension/ 目录的条目。该扩展内部订阅 Pi 的 tool_call / user_bash / input / session_start 事件,并调用 failproofai --hook <Event> --cli pi;处理器通过 PI_EVENT_MAP 将下划线小写蛇形命名规范化为帕斯卡式,使现有内置策略正常触发。工具输入参数也通过 PI_TOOL_INPUT_MAP 规范化(Pi 的 Read / Write / Edit 使用 path 而非 file_path;映射顶层键后 block-env-filesblock-secrets-write 可正常触发——block-read-outside-cwd 本身已有 path 的回退逻辑)。Pi 支持目前为 beta 版本,有待 Pi 的扩展 API 和会话日志格式稳定。
    • Hermes (hermes-agent)~/.hermes/config.yaml仅用户作用域——Hermes 没有项目/本地配置)。Hermes 是一个 Slack/Telegram 网关,因此一次安装即可拦截来自所有平台(Slack/Telegram/cli/cron)以及内部子代理的工具调用。Hook 条目是 hooks: 映射下的 {command, timeout} 对(timeout 单位为),以 Hermes 的蛇形命名事件为键(pre_tool_call / post_tool_call / on_session_start / on_session_end / subagent_stop);处理器通过 HERMES_EVENT_MAP 规范化事件,通过 HERMES_TOOL_MAP 规范化工具名称,使内置策略正常触发。配置通过保留注释的 YAML Document 往返编辑,以确保操作者的其他设置不受影响;安装时将 hooks_auto_accept: true 设置为 true,以便无头网关(无 TTY)在无需确认提示的情况下运行 hook。评估器输出 Hermes 的 {"decision":"block","reason"} stdout 约定(Hermes 忽略退出码)。限制: Hermes 没有会话结束 Stop 事件,因此 require-*-before-stop 内置策略永远不会为其触发(不适用,并非故障);instruct 降级为允许并记录日志(无额外上下文通道);输出密钥清理(sanitize-*)无法通过 shell hook 约定重写工具输出。Hermes 同时也是一个离线审计数据源——仪表盘直接从 ~/.hermes/state.db 读取其网关会话。
  • policies-config.json — 告知 failproofai 评估哪些策略及其参数(在所有代理 CLI 之间共享)
通过 --cli claude|codex|copilot|cursor|opencode|pi|hermes 指定目标代理(可用空格分隔或重复指定多个):
省略 --cli 时,failproofai 会自动检测已安装的代理 CLI(which claude / which codex / which copilot / which cursor-agent / which opencode / which pi / which hermes):
  • 检测到一个 CLI — 自动选择该 CLI,无需提示。
  • 在交互式终端中检测到多个 CLI — 显示方向键单选菜单,分为 Detected (N) 区域(包含一个”为所有 N 个已检测到的 CLI 安装”的聚合行及各个已检测 CLI)和 Not installed (M) · install hooks ahead of time 区域(列出所有未检测到的受支持 CLI 作为提前安装选项)(↑↓ 移动,回车选择,^C 退出)。卸载流程仅显示 Detected 区域。
  • 在非交互式运行中检测到多个 CLI(CI、无 TTY)— 无需提示,为所有检测到的 CLI 安装。
  • 未检测到任何 CLI — 回退到 claude,并显示在 PATH 中未找到代理二进制文件的警告;hook 命令仍会被写入,一旦安装代理即可生效。
你可以随时直接编辑 policies-config.json,修改将在下一次 hook 事件触发时立即生效,无需重启。

示例:带团队默认配置的项目级配置

.failproofai/policies-config.json 提交到你的仓库:
每位开发者可以创建 .failproofai/policies-config.local.json(已加入 gitignore)进行个人覆盖配置,而不影响其他团队成员。