OpenCode 的权限系统:让自动化在可控范围内运行

在使用 AI 编程助手时,信任和可控是一对永恒的矛盾------既希望工具能自动完成大量工作,又不希望它越权执行危险操作。OpenCode 通过一套灵活的权限配置,让开发者在"自动运行""弹窗询问"和"直接阻止"之间找到平衡点。

从旧版的 tools 到新的 permission

在 v1.1.1 版本之前,OpenCode 用一个布尔型的 tools 配置来控制工具调用是否需要审批。这种开关过于粗糙,无法针对不同操作做精细化管理。新版本中,这个旧配置已被合并进 permission 字段,功能更强大,同时保留了对旧配置的兼容,已有的项目不会受到影响。

三个动作:允许、询问、拒绝

每个权限规则最终都会落到三种处理方式之一:

  • allow:自动执行,无需打扰使用者。
  • ask:弹出确认框,等待人为批准。
  • deny:直接拦截,不会执行。

这种三态模型覆盖了从完全信任到严格禁止的各类场景。

全局与局部:从简单到精细的配置方式

最简单的配置是直接给所有操作指定一个统一策略。例如,让所有工具调用都先询问:

json 复制代码
{
  "$schema": "https://opencode.ai/config.json",
  "permission": "ask"
}

也可以用 "allow" 彻底放开所有操作,不过在生产环境中很少会这么用。

更常见的做法是用对象按工具分类。下面这个例子设置了全局默认"询问",但对 bash 命令和 edit 编辑操作单独放行或拒绝:

json 复制代码
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "*": "ask",
    "bash": "allow",
    "edit": "deny"
  }
}

这里的 "*" 是一个通配符,代表所有未单独列出的工具。规则合并时,具体的工具规则会覆盖全局规则。

精细到参数级别的颗粒度

OpenCode 的权限系统甚至可以匹配命令的具体参数。通过对象语法,能让同一工具在不同输入下表现出不同行为。一个典型的例子是对 bash 做区别对待:

json 复制代码
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "bash": {
      "*": "ask",
      "git *": "allow",
      "npm *": "allow",
      "rm *": "deny",
      "grep *": "allow"
    },
    "edit": {
      "*": "deny",
      "packages/web/src/content/docs/*.mdx": "allow"
    }
  }
}

这段配置的意思是:运行 shell 命令时,默认需要询问,但所有 gitnpmgrep 开头的命令自动放行,而 rm 删除命令则坚决阻止。对于文件编辑操作,全局禁止修改,唯独允许改动 packages/web/src/content/docs/ 路径下的 .mdx 文件。

匹配规则按顺序评估,最后匹配到的规则生效 。常见的套路是把 "*" 兜底规则写在最前面,然后再写更具体的例外情况,这样后面的规则就能覆盖前面的全局默认。这种"先宽后紧"的写法非常直观。

通配符的用法

模式匹配用到了简单的通配符语法:

  • * 匹配任意数量的字符(包括零个)。
  • ? 匹配恰好一个字符。
  • 其他字符会按字面量精确匹配。

这跟常见的 shell glob 很像,学习成本几乎为零。

巧用 home 目录扩展

在写路径模式时,可以用 ~$HOME 代表当前用户的 home 目录。例如 ~/projects/* 会展开为 /Users/用户名/projects/*。这个特性在配置 external_directory 规则时格外方便。

安全关卡:外部目录与死循环检测

除了按照工具划分权限,OpenCode 还内置了两个特殊的安全守卫:

external_directory 会在工具调用涉及工作目录之外的文件路径时触发。比如,即便用 ~ 展开了路径,那个路径如果不在 OpenCode 的启动工作区内,仍然被视为外部目录。想让 AI 读写外部目录,必须显式授权。

举个例子,允许访问 ~/projects/personal/ 下的所有内容:

json 复制代码
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "external_directory": {
      "~/projects/personal/**": "allow"
    }
  }
}

一旦某个外部目录被允许,它会继承当前工作区的默认权限。默认情况下 read 是允许的,因此读取外部文件不会受阻。如果只想让 AI 看但不能改,可以在 edit 权限里单独加上拒绝规则:

json 复制代码
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "external_directory": {
      "~/projects/personal/**": "allow"
    },
    "edit": {
      "~/projects/personal/**": "deny"
    }
  }
}

这样既开放了阅读,又保护了文件不被意外修改。

doom_loop 则是另一个智能防护:当同一个工具调用在输入完全不变的情况下重复出现三次,说明系统可能陷入了死循环,此时 OpenCode 会主动弹窗询问,避免空转消耗资源。这个权限默认就是 "ask",通常不需要改动。

完整的权限清单

OpenCode 可配置的权限覆盖了所有核心操作,每一项都以工具名称作为键:

  • read:读取文件,匹配文件路径。
  • edit:所有文件修改(包括编辑、写入、补丁)。
  • glob:文件名匹配搜索,匹配 glob 模式。
  • grep:内容搜索,匹配正则表达式。
  • bash :执行 shell 命令,匹配解析后的命令(如 git status --porcelain)。
  • task:启动子任务代理,匹配子代理的类型。
  • skill:加载技能模块,匹配技能名称。
  • lsp:执行 LSP 查询(目前不支持颗粒度控制)。
  • question:运行中向使用者提问。
  • webfetch:抓取 URL,匹配目标网址。
  • websearch:网络搜索,匹配查询字符串。
  • external_directory:工具操作触碰到项目工作目录外的路径时触发。
  • doom_loop:同一工具调用输入完全一致且连续重复 3 次时触发。
开箱即用的默认值

如果不在配置文件里写任何 permission 内容,OpenCode 会以一套相当宽松但又兼顾安全的默认规则启动:

  • 大多数权限默认 "allow",即自动执行。
  • doom_loopexternal_directory 默认 "ask",避免无限循环和越界访问。
  • read 虽然全局允许,但对 .env 文件做了特殊处理:默认拒绝读取 .env.env.*,但放行 .env.example。这个内置规则可以有效防止敏感环境变量被意外泄露。

等效的默认配置可以理解为:

json 复制代码
{
  "permission": {
    "read": {
      "*": "allow",
      "*.env": "deny",
      "*.env.*": "deny",
      "*.env.example": "allow"
    }
  }
}
询问弹窗的三个选项

当某个操作被设置为 "ask" 后,OpenCode 的界面会弹出确认框,提供三个选择:

  • once:仅批准本次请求。
  • always :根据工具建议的模式,批准当前会话中所有匹配的后续请求(比如 bash 会建议允许类似 git status* 这样的安全前缀)。
  • reject:拒绝本次请求,不执行。

这种即时的会话级授权,让开发者在交互中慢慢教会工具哪些操作可以放心自动化。

代理人(Agent)的权限覆盖

OpenCode 支持为不同的代理人(子任务)单独设置权限。代理人的权限配置会与全局配置合并,并且代理人规则拥有更高的优先级。

例如,全局配置里 git commit * 被直接拒绝,但在一个名为 "build" 的代理人中,可能希望提交操作变为询问,以便在构建脚本中灵活判断:

json 复制代码
{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "bash": {
      "*": "ask",
      "git *": "allow",
      "git commit *": "deny",
      "git push *": "deny",
      "grep *": "allow"
    }
  },
  "agent": {
    "build": {
      "permission": {
        "bash": {
          "*": "ask",
          "git *": "allow",
          "git commit *": "ask",
          "git push *": "deny",
          "grep *": "allow"
        }
      }
    }
  }
}

此外,代理人权限也可以在 Markdown 格式的代理定义文件中直接声明:

markdown 复制代码
---
description: Code review without edits
mode: subagent
permission:
  edit: deny
  bash: ask
  webfetch: deny
---

Only analyze code and suggest changes.

这种内联配置让代理人模块既自我描述又行为可控。

一些使用细节

权限模式匹配时要注意参数的完整性。例如,"grep *" 能够匹配 grep pattern file.txt,而单独一个 "grep" 规则会因为不包含参数部分而匹配失败,导致操作被拦截。同样,像 git status 这样的命令如果没有参数能正常执行,但一旦带上参数,就需要用 "git status *" 来覆盖。熟悉这些细节后,配置起来会得心应手。

OpenCode 的权限系统从全局开关进化成了可以针对命令、路径、甚至是特定代理人的精细网络。对于追求效率又害怕失控的团队来说,这套机制恰好填补了"想用 AI 但又不敢完全放手"的中间地带。

相关推荐
HIT_Weston1 天前
86、【Agent】【OpenCode】bash 工具提示词(完结)
人工智能·agent·opencode
程序员柒叔1 天前
OpenCode 一周动态-2026-W20
人工智能·github·copilot·agent·opencode
HIT_Weston1 天前
85、【Agent】【OpenCode】bash 工具提示词(HEREDOC)
人工智能·agent·opencode
HIT_Weston2 天前
83、【Agent】【OpenCode】bash 工具提示词(commit 注意事项)(一)
人工智能·agent·opencode
闲人编程2 天前
Agent的安全边界:如何防止AI失控(对齐问题)
网络·python·ai·agent·权限·智能体·cai
芯码学徒3 天前
vscode上如何免费使用opencode插件
ide·vscode·编辑器·opencode
HIT_Weston3 天前
82、【Agent】【OpenCode】bash 工具提示词(amend 风险)
人工智能·agent·opencode
HIT_Weston3 天前
81、【Agent】【OpenCode】bash 工具提示词(git 提交规则)
人工智能·agent·opencode
g5zhu58964 天前
opencode无网环境-引用上下文失效问题
opencode