跳转到主要内容
failproofai 使用 JSON 配置文件来控制哪些策略处于激活状态、它们的行为方式以及从何处加载自定义策略。配置设计上便于与团队共享——将其提交到代码仓库,每位开发者都能获得相同的 Agent 安全防护。

配置作用域

共有三个配置作用域,按优先级顺序依次评估:
作用域文件路径用途
project.failproofai/policies-config.json每个仓库的配置,提交到版本控制
local.failproofai/policies-config.local.json个人的仓库级覆盖配置,已加入 gitignore
global~/.failproofai/policies-config.json适用于所有项目的用户级默认配置
当 failproofai 收到 hook 事件时,它会加载并合并当前工作目录下所有存在的三个文件。

合并规则

enabledPolicies — 取三个作用域的并集。任意级别启用的策略均处于激活状态。
project:  ["block-sudo"]
local:    ["block-rm-rf"]
global:   ["block-sudo", "sanitize-api-keys"]

resolved: ["block-sudo", "block-rm-rf", "sanitize-api-keys"]  ← 去重后的并集
policyParams — 最先为某个策略定义参数的作用域完全优先。策略参数内部的值不会进行深度合并。
project:  block-sudo → { allowPatterns: ["sudo apt-get update"] }
global:   block-sudo → { allowPatterns: ["sudo systemctl status"] }

resolved: { allowPatterns: ["sudo apt-get update"] }   ← project 优先,global 被忽略
project:  (无 block-sudo 条目)
local:    (无 block-sudo 条目)
global:   block-sudo → { allowPatterns: ["sudo systemctl status"] }

resolved: { allowPatterns: ["sudo systemctl status"] }  ← 向下回退至 global
customPoliciesPath — 最先定义的作用域优先。 llm — 最先定义的作用域优先。

配置文件格式

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

字段参考

enabledPolicies

类型:string[] 要启用的策略名称列表。名称必须与 failproofai policies 显示的策略标识符完全匹配。完整列表请参阅内置策略 不在 enabledPolicies 中的策略处于非激活状态,即使它们在 policyParams 中有条目也是如此。

policyParams

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

hint(通用参数)

类型:string(可选) 当策略返回 deny 或 instruct 时,附加到原因说明中的消息。使用它可以在不修改策略本身的情况下,为 Claude 提供可操作的指导。 适用于任何类型的策略——内置策略、自定义策略(custom/)、项目约定策略(.failproofai-project/)或用户约定策略(.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."
    }
  }
}
当 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/ 目录中发现并加载策略文件:
级别目录作用域
项目级.failproofai/policies/通过版本控制与团队共享
用户级~/.failproofai/policies/个人使用,适用于所有项目
文件匹配规则: 仅加载匹配 *policies.{js,mjs,ts} 的文件(例如 security-policies.mjsworkflow-policies.js),目录中的其他文件会被忽略。 无需配置: 约定策略不需要在 policies-config.json 中添加任何条目。只需将文件放入对应目录,下次 hook 事件触发时即会自动加载。 联合加载: 项目级和用户级约定目录都会被扫描。两个级别的所有匹配文件都会被加载(与 customPoliciesPath 遵循先定义者优先的规则不同)。 更多详情和示例请参阅自定义策略

llm

类型:object(可选) 供需要进行 AI 调用的策略使用的 LLM 客户端配置。大多数场景下无需配置。
{
  "llm": {
    "model": "claude-sonnet-4-6",
    "apiKey": "sk-ant-..."
  }
}

通过 CLI 管理配置

policies --installpolicies --uninstall 命令会写入 Agent CLI 的 hook 设置文件(hook 入口点),而 policies-config.json 是你直接管理的文件。两者是相互独立的:
  • Agent CLI 设置 — 指示 Agent 在每次工具调用时执行 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 记录的 schema(公开文档中未予说明)。
    • 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 将驼峰式名称规范化为 PascalCase,因此现有内置策略无需改动即可正常触发。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 在转发给二进制文件之前,会将工具名称(小写 → PascalCase,通过 OPENCODE_TOOL_MAP)和工具输入参数键(驼峰式 → 下划线式,通过 OPENCODE_TOOL_INPUT_MAP,适用于 Read / Write / Edit,例如 filePathfile_patholdStringold_string)进行规范化,因此 block-read-outside-cwdblock-env-filesblock-secrets-write 等路径检查内置策略在 OpenCode 工具调用时无需修改即可正常触发。会话保存在 OpenCode 的 SQLite 数据库 ~/.local/share/opencode/opencode.db 中;仪表盘的会话查看器通过 opencode db --format jsonopencode export <id> 读取这些数据。OpenCode 支持目前处于 beta 阶段,我们正在对照更多真实场景跨版本验证其行为。详见 OpenCode 插件文档
    • 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 将下划线小写命名规范化为 PascalCase,因此现有内置策略无需改动即可正常触发。工具输入参数也通过 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 和会话日志格式趋于稳定。
    • Gemini CLI (beta)~/.gemini/settings.json(用户级)、<cwd>/.gemini/settings.json(项目级)—— Gemini 没有 local 作用域(其文档中有位于 /etc/gemini-cli/settings.jsonsystem 作用域,failproofai 不对外暴露该作用域)。Hook 条目使用 Claude 的 {type, command, timeout} 格式,包裹在 Gemini 的 {matcher, hooks: [...]} matcher schema 中,默认 matcher: "*"。事件名称为 PascalCase(SessionStartBeforeAgentAfterAgentBeforeModelAfterModelBeforeToolSelectionBeforeToolAfterToolPreCompressNotificationSessionEnd);处理程序通过 GEMINI_EVENT_MAP 映射到 Claude 规范名称。工具名称为 snake_case(run_shell_commandread_filewrite_filereplace 等)——处理程序通过 GEMINI_TOOL_MAP 规范化,使现有内置策略无需改动即可正常触发。策略评估器输出 Gemini 的平铺 {decision: "deny", reason} 格式(符合 Gemini 的”黄金规则”退出码 0 约定),在 BeforeAgent / AfterTool / SessionStart 时输出 {hookSpecificOutput: {hookEventName, additionalContext}} 进行上下文注入,在 AfterAgent 时输出 {decision: "block", reason} 以实现强制重试语义。Gemini CLI 支持目前处于 beta 阶段,我们正在扩大真实场景的覆盖范围。详见 Gemini CLI hooks 文档
  • policies-config.json — 告知 failproofai 要评估哪些策略及其参数(在所有 Agent CLI 之间共享)
通过 --cli claude|codex|copilot|cursor|opencode|pi|gemini 指定目标 Agent(空格分隔或重复指定,可选任意组合):
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
省略 --cli 时,failproofai 会自动检测已安装的 Agent CLI(which claude / which codex / which copilot / which cursor-agent / which opencode / which pi / which gemini):
  • 检测到一个 CLI — 自动选择该 CLI,无需提示。
  • 检测到多个 CLI(交互式终端)— 显示方向键单选提示,分组展示:已检测 (N) 部分(包含一个”为所有 N 个已检测 CLI 安装”的聚合选项,以及各已检测 CLI 的单独选项)和未安装 (M) · 提前安装 hooks 部分(列出每个未检测到的受支持 CLI 作为预安装选项;↑↓ 移动,Enter 选择,^C 退出)。卸载流程只显示已检测部分。
  • 检测到多个 CLI(非交互式运行,如 CI 或无 TTY)— 为所有已检测 CLI 安装,无需提示。
  • 未检测到任何 CLI — 回退至 claude,并警告 PATH 中未找到 Agent 二进制文件;hook 命令仍会写入,待安装后即可激活。
你可以随时直接编辑 policies-config.json,更改在下次 hook 事件触发时立即生效,无需重启。

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

.failproofai/policies-config.json 提交到代码仓库:
{
  "enabledPolicies": [
    "block-sudo",
    "block-rm-rf",
    "block-push-master",
    "sanitize-api-keys",
    "block-env-files"
  ],
  "policyParams": {
    "block-push-master": {
      "protectedBranches": ["main", "release", "hotfix"]
    }
  }
}
每位开发者可以在本地创建 .failproofai/policies-config.local.json(已加入 gitignore),用于个人覆盖配置,而不会影响其他团队成员。