工具库OpenCode发布于 2026/07/31作者 koala已人工审核5 分钟

AI 真的会无视 CLAUDE.md:给 Claude Code、Codex、Cursor、OpenCode 加一条硬护栏

规则能告诉 AI 应该怎么做,但不能代替权限控制。四个主流 AI 编程工具的生产边界配置一次讲清。

AI Agent 硬护栏:黑色安全闸门拦截高风险操作

前言

最近写 Agent 相关配置时,我一直在想一件事:我们到底该怎么相信 AI 会遵守项目规则?

很多项目里都有类似的说明:不要改生产配置不要碰 .env不要执行删除命令。我们会把它写进 CLAUDE.mdAGENTS.md,或者 Cursor Rules。平时看起来没问题,Agent 也大多数时候会照做。

但有一天,它真的改了 config/production/ 里的连接串,你才会发现:这类规则写得再清楚,也只是上下文,不是权限。

这篇文章不讲怎么把 prompt 写得更长。我们直接解决一个更实际的问题:怎样让 Agent 在动手之前被拦下来。

本文你能学到什么

看完这篇文章,你应该能搞清楚三件事:

不会也没关系,下面所有例子都围绕同一个小场景展开,直接替换路径就能放进自己的项目。

先看一个很容易忽略的问题

假设你写了这样一段规则:

## Production boundary

Never modify files under config/production/.
Never run destructive commands in this repository.
Ask for human confirmation before any production operation.

这段话当然应该保留。它能让 Agent 理解项目边界,也能减少无谓的尝试。

但这里有的小伙伴可能会问:既然写了 Never,它为什么还可能不遵守?

因为语言模型不是规则引擎。它每一次响应都在根据当前上下文生成“最合适”的下一步;任务越复杂、上下文越长,规则越可能被别的信息稀释或误解。文件写入和 Shell 命令却不是概率事件,一旦执行,副作用就已经发生了。

所以我们在项目里最好分两层处理:

这一层解决什么问题放在哪里
软规则告诉 Agent 应该怎样做CLAUDE.mdAGENTS.md、Cursor Rules
硬护栏在操作发生前允许或拒绝Hook、权限、Sandbox、CI

软规则负责“讲道理”,硬护栏负责“关门”。生产边界必须放在第二层。

好了,开始我们的正文学习吧。

Claude Code:用 PreToolUse 在执行前拒绝

Claude Code 的 PreToolUse Hook 会在工具参数生成后、真正执行前运行。Hook 输出 deny,这次工具调用就不会继续。

先创建 .claude/settings.json

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash|Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/guard-production.sh"
          }
        ]
      }
    ]
  }
}

再创建 .claude/hooks/guard-production.sh

#!/usr/bin/env bash
set -euo pipefail

input="$(cat)"
tool="$(jq -r '.tool_name' <<<"$input")"

if [[ "$tool" == "Bash" ]]; then
  value="$(jq -r '.tool_input.command // ""' <<<"$input")"
else
  value="$(jq -r '.tool_input.file_path // ""' <<<"$input")"
fi

if [[ "$value" == *"config/production/"* ]] || [[ "$value" =~ (^|[[:space:];|&])rm[[:space:]]+-[[:alpha:]]*r[[:alpha:]]*f ]]; then
  jq -n '{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:"Production boundary: operation blocked."}}'
fi

最后执行:

chmod +x .claude/hooks/guard-production.sh

这段脚本做的事情很简单:Bash 取命令文本,编辑工具取目标文件路径;只要碰到生产目录或 rm -rf,就拒绝。

不过别把它理解成万能安全脚本。find -delete、Python、Node 也能删文件。这个 Hook 的价值是把已知高风险操作提前挡住;更底层的文件权限和 Sandbox 还是要开。Claude Code 也支持用 filesystem.denyReadcredentials.envVars 保护密钥与凭证。

Codex:项目 .codex/config.toml 也可以挂 Hook

Codex 现在同样支持生命周期 Hook。对于文件编辑和命令执行,最常用的还是 PreToolUse

在项目根目录新建 .codex/config.toml

[[hooks.PreToolUse]]
matcher = "^(Bash|apply_patch)$"

[[hooks.PreToolUse.hooks]]
type = "command"
command = 'python3 .codex/hooks/guard_production.py'
timeout = 5
statusMessage = "Checking production boundary"

然后新建 .codex/hooks/guard_production.py

#!/usr/bin/env python3
import json, re, sys

event = json.load(sys.stdin)
command = event.get("tool_input", {}).get("command", "")

blocked = (
    "config/production/" in command
    or re.search(r"(^|[\s;|&])rm\s+-[a-zA-Z]*r[a-zA-Z]*f", command)
)

if blocked:
    print(json.dumps({"hookSpecificOutput": {
        "hookEventName": "PreToolUse",
        "permissionDecision": "deny",
        "permissionDecisionReason": "Production boundary: operation blocked."
    }}))

Codex 的 apply_patch 会把补丁内容放进 tool_input.command,所以这一个脚本能够同时检查补丁和 Bash 命令。首次启用项目 Hook 时,可以在 Codex 里用 /hooks 审阅并信任它。

这里还要补一句:项目 Hook 是开发团队的本地护栏,不是企业级的最终权限系统。生产身份、云密钥、部署权限仍然应该放在独立 IAM、CI 和受管策略里。Hook 拦的是“这次操作”,权限系统决定“它本来有没有资格操作”。

OpenCode:用插件的 tool.execute.before

OpenCode 的思路不太一样,它更像是在 Agent 运行时插一个插件。把下面代码放在 .opencode/plugins/guard-production.ts

import type { Plugin } from "@opencode-ai/plugin";

export const GuardProduction: Plugin = async () => ({
  "tool.execute.before": async (input, output) => {
    const raw = JSON.stringify(output.args ?? {});
    const dangerousRm = /(^|[\s;|&])rm\s+-[a-zA-Z]*r[a-zA-Z]*f/.test(raw);
    const writesProduction =
      ["write", "edit", "apply_patch"].includes(input.tool) &&
      raw.includes("config/production/");

    if (dangerousRm || writesProduction) {
      throw new Error("Production boundary: operation blocked.");
    }
  },
});

OpenCode 会加载 .opencode/plugins/ 下的本地插件。这里的关键点只有一个:tool.execute.before 是在内建工具真正执行前触发的,抛错就能把调用拦住。

另外,OpenCode 的 edit 权限覆盖 editwriteapply_patch。有的小伙伴只会盯着 write,结果补丁工具还是能改文件;这也是为什么例子里同时检查了三类写操作。

Cursor:Rules 不等于 Hook,先把权限收紧

Cursor 的 .cursor/rules/*.mdc 很适合放项目约定,但它和 CLAUDE.md 一样,解决的是“让模型知道规则”,不是“强制执行规则”。

Cursor 已经发布了 Beta Hooks,官方确认它可以用于审计、拦截命令和上下文脱敏。不过截至本文写作,官方公开文档还没有提供一个稳定、可复现的项目级 Hook 配置格式。

所以 Cursor 这里我不建议贴一段来历不明的 hooks.json。更实用的做法是:

  1. .cursor/rules/production.mdc 写清生产边界;
  2. 关闭自动执行,保留终端命令审批;
  3. 开启 Sandbox,只给工作区和必要的网络域名;
  4. 如果团队已经拿到 Hooks Beta,就按当前 Cursor 设置页生成的格式接入相同的检查逻辑;
  5. 不要在非交互 CLI 模式下把生产目录和部署凭证暴露给 Agent。

这部分配置看起来没那么“自动化”,但安全配置最怕伪确定性。一个版本已经失效的 Hook 配置,远不如一条仍然会弹出来的审批可靠。

最后再说三个容易踩的坑

第一,黑名单不是权限系统。 rm -rf 只是一个例子。不要试图列完所有危险命令,应该同时限制路径、目录权限、网络出口和生产身份。

第二,PostToolUse 不能回滚副作用。 它适合跑 lint、记审计日志、提醒 Agent 修复问题;但文件已经写了、命令已经跑了,再“阻止”已经晚了。真正的禁止要写在 PreToolUsetool.execute.before

第三,不要让密钥本来就暴露在 Agent 面前。 Hook 可以降低误操作概率,但它不是保险柜。.env、云凭证、SSH 私钥、生产数据库连接,都应该配合最小权限、短期凭证和隔离环境处理。

总结

很多开发者已经把项目规则写得很详细了,但这不代表规则一定会被 100% 执行。

CLAUDE.mdAGENTS.md、Cursor Rules 都有用,它们负责让 Agent 理解项目。真正不能出错的事情,则要在工具调用之前再加一道 Hook,并把最底层的权限交给 Sandbox、CI 和云 IAM。

如果你今天只想做一件事,我建议先选一个你绝对不能接受的操作,例如“不能改生产配置”,为它写一个 PreToolUse 拦截器,再故意测试一次违规操作。

因为没测过的护栏,很多时候也只是一段写得很认真的说明文档。

参考资料

  1. https://code.claude.com/docs/en/hooks
  2. https://code.claude.com/docs/en/settings
  3. https://learn.chatgpt.com/docs/hooks
  4. https://learn.chatgpt.com/docs/config-file/config-advanced
  5. https://dev.opencode.ai/docs/plugins/
  6. https://dev.opencode.ai/docs/tools/
  7. https://cursor.com/changelog/1-7
  8. https://docs.cursor.com/en/cli/using

Continue Reading

相关推荐

继续阅读同一工具与主题下的实战内容。