| 1 | # 插件包 |
| 2 | |
| 3 | > 英文原文:[PLUGIN_BUNDLES.md](../PLUGIN_BUNDLES.md)。 |
| 4 | > 最后与英文同步日期(last synced with English revision):2026-09-29。 |
| 5 | |
| 6 | Codewhale 的插件包边界刻意划得很小。这条边界在 v0.9.1 划下,v0.9.10 又审慎扩展: |
| 7 | 插件包可以借助 Codewhale 已有的引擎,贡献声明式的 Skills、MCP 配置、Commands、 |
| 8 | Agent profiles 和 Hooks。遇到不支持的声明,它只把这些声明记入清单,不会因此禁用 |
| 9 | 整个插件包——混合插件包依然可用。发现(discovery)本身从不执行、启用、信任、 |
| 10 | 下载、更新或安装任何东西。 |
| 11 | |
| 12 | 本文负责插件包的格式、发现、校验,以及信任/启用/运行时契约。 |
| 13 | [PLUGINS.md](./PLUGINS.md) 负责文件怎么写入磁盘、怎么删除,也就是 v0.9.4(#5182) |
| 14 | 加入的 `/plugin install`、`update`、`uninstall`、`suggest` 上手入口。 |
| 15 | 兼容的 Claude Code 插件包使用同一套原生适配器,其支持子集见 |
| 16 | [CLAUDE_PLUGIN_COMPAT.md](../CLAUDE_PLUGIN_COMPAT.md)。 |
| 17 | 可运行的原生示例,以及 OpenCode/DSH 数据如何显式转换,见 |
| 18 | [编写你的第一个插件](./PLUGIN_AUTHORING.md)。 |
| 19 | |
| 20 | ## 发现与优先级 |
| 21 | |
| 22 | Codewhale 只扫描自己的目录,在每个 `<name>/` 目录里查找以下清单之一: |
| 23 | `plugin.json`(原生 Agent Plugins v1.0.0 格式,自 v0.9.4 起)、 |
| 24 | `kimi.plugin.json`(兼容的 Kimi Skills/MCP 子集,自 v0.9.8 起)、 |
| 25 | `plugin.toml`(旧版 Codewhale 格式,仍可完整读取)、 |
| 26 | `.claude-plugin/plugin.json`(兼容的 Claude 子集,自 v0.9.13 起): |
| 27 | |
| 28 | - 用户级:`~/.codewhale/plugins/<name>/` |
| 29 | - 工作区级:`<workspace>/.codewhale/plugins/<name>/` |
| 30 | |
| 31 | 一个插件包若发布了多种格式,依次读 `plugin.json`、`kimi.plugin.json`、 |
| 32 | 旧版 `plugin.toml`,最后是 `.claude-plugin/plugin.json`。 |
| 33 | Computer Use 以内置插件包的形式随程序发布;它同样要先审查、再启用,才会激活。 |
| 34 | 内部优先级依次是内置、用户级、工作区级;同名插件包以先命中的为准。 |
| 35 | 这样,仓库就无法遮蔽已显式安装的用户级插件包。 |
| 36 | 符号链接形式的根目录、清单、组件路径和嵌套组件文件一律失败关闭。 |
| 37 | |
| 38 | 内嵌的 Computer Use 文件会实体化到 |
| 39 | `$CODEWHALE_HOME/builtin-plugins/snapshots/computer-use-<bundle-digest>/computer-use`。 |
| 40 | 每个进程只认自己那份内嵌摘要对应的发现根目录。所以并行构建各自保留完整、互不干扰的 |
| 41 | 源码树;发布方从不删除或覆盖已有的快照。复用时会逐字节核对内嵌内容、目录项、文件类型、 |
| 42 | 可执行标志和戳记。快照只要残缺或被改动,就一律拒绝,不做修复。 |
| 43 | 被中断的私有暂存目录不会被发现,也不会被复用。 |
| 44 | |
| 45 | 现有的按路径绑定插件身份与信任的规则继续适用:同一 home 下内嵌字节相同, |
| 46 | 就复用同一身份;字节有变,就必须重新审查并启用。从旧的、可变的 |
| 47 | `builtin-plugins/computer-use` 布局迁移过来,也要重新审查一次。 |
| 48 | 旧版插件包和回执原样保留,以便旧二进制继续运行;信任不会迁移。 |
| 49 | 诊断操作不会创建缺失的 Codewhale home。 |
| 50 | 选定的 home 本身可以是符号链接:创建任何内置路径之前,会先固定解析后的 home 目录。 |
| 51 | 内置缓存路径归 Codewhale 自有,其中的链接仍然失败关闭。 |
| 52 | |
| 53 | 新建的用户级和工作区级插件包一律未受信任且处于停用状态。发现过程是只读的, |
| 54 | 不会检查其他应用的扩展目录或凭据目录:`.claude/plugins`、`.cursor/plugins` |
| 55 | 这类环境根目录从不扫描。 |
| 56 | |
| 57 | v0.9.1 之前的 `overrides.json` 启用状态,刻意不作为信任导入;每个插件包都只能通过 |
| 58 | 下面这套审查来激活,该审查依据内容哈希和 `codewhale-plugin-capabilities-v3` 激活策略。 |
| 59 | |
| 60 | ## 清单 |
| 61 | |
| 62 | 所有受支持的编码格式都会解析成同一份内部清单,因此下游的校验、哈希、审查和运行时行为完全一致。 |
| 63 | 这些格式之间刻意不做磁盘上的自动迁移;`/plugin export <name> <target-dir>` |
| 64 | 会把已加载的插件包按 Agent Plugins v1.0.0 规范导出到一个目录,不改动已安装的那份。 |
| 65 | |
| 66 | ### `plugin.json`(Agent Plugins v1.0.0) |
| 67 | |
| 68 | 这份标准的清单根是封闭的:只允许 `$schema`、`name` 和几个可选的标准字段 |
| 69 | (`version`、`description`、`author`、`homepage`、`repository`、`license`、 |
| 70 | `keywords`、`extensions`)。出现未知的根键就是解析错误。客户端专用数据放在 |
| 71 | `extensions` 下,按反向域名命名空间归类。未知的厂商命名空间一律忽略,从不拒绝—— |
| 72 | 正因如此,为其他客户端编写的插件包才能在这里加载;而 Codewhale 自己的 |
| 73 | `extensions["net.codewhale"]` 命名空间里若出现未知键,则直接拒绝,不会静默丢弃。 |
| 74 | |
| 75 | 名称遵循标准规则:1–64 个小写 ASCII 字母、数字,或位于中间的单 `-`/`.`, |
| 76 | 首尾必须是字母或数字,不允许 `--` 或 `..`。插件包根目录下的 `skills/` 目录会自动识别; |
| 77 | 其他组件位置、`capabilities`、`when` 和 `display_name` 都放在 |
| 78 | `extensions["net.codewhale"]` 里。 |
| 79 | |
| 80 | MCP 服务器不能写在 `plugin.json` 里(根是封闭的);它们放在同级的 `mcp.json` 中, |
| 81 | 位于 `mcpServers` 下,传输方式为 `stdio`、`streamable-http` 或 `sse` |
| 82 | (`type` 可以省略,省略时根据 `command` 还是 `url` 推断)。 |
| 83 | Codewhale 独有的服务器选项——超时、工具过滤、基于环境变量的凭据、启用状态—— |
| 84 | 按服务器写在 `extensions["net.codewhale"]` 下。`env` 名称 `PLUGIN_ROOT` 和 |
| 85 | `PLUGIN_DATA` 由标准保留给宿主运行时,在插件定义里会被拒绝。 |
| 86 | |
| 87 | ### `plugin.toml`(旧版 Codewhale 格式) |
| 88 | |
| 89 | ```toml |
| 90 | schema_version = 1 |
| 91 | |
| 92 | [plugin] |
| 93 | name = "example" |
| 94 | version = "0.1.0" |
| 95 | description = "Example instruction and MCP bundle" |
| 96 | author = "Example Author" |
| 97 | |
| 98 | [skills] |
| 99 | path = "skills" |
| 100 | |
| 101 | [commands] |
| 102 | path = "commands" |
| 103 | |
| 104 | [agents] |
| 105 | path = "agents" |
| 106 | |
| 107 | [hooks] |
| 108 | path = "hooks" |
| 109 | |
| 110 | [mcp_servers.local] |
| 111 | command = "node" |
| 112 | args = ["server.js"] |
| 113 | cwd = "mcp" |
| 114 | |
| 115 | [mcp_servers.remote] |
| 116 | url = "https://example.invalid/mcp" |
| 117 | |
| 118 | [capabilities] |
| 119 | network_hosts = ["example.invalid"] |
| 120 | |
| 121 | [when] |
| 122 | os = ["macos", "linux", "windows"] |
| 123 | binaries = ["node"] |
| 124 | ``` |
| 125 | |
| 126 | 旧版 TOML 的名称由 1–64 个小写 ASCII 字母、数字或位于中间的连字符组成。 |
| 127 | 没有 `schema_version` 的未加版本号清单仍可解析,但 `/plugin validate` 会给出迁移警告 |
| 128 | (`[plugin].version` 缺失时显示为 `0.0.0`)。出现未知的顶层表或字段就是解析错误 |
| 129 | (`deny_unknown_fields`),报告时给出字节偏移,但不回显清单里的值。 |
| 130 | |
| 131 | ### 校验(两种格式) |
| 132 | |
| 133 | 组件路径必须是相对路径、位于插件包内、真实存在,而且不能包含符号链接或 |
| 134 | Windows reparse point(包括 junction 和 mount point)。v1 schema 会拒绝未知的 |
| 135 | MCP 字段、含义有歧义的本地/远程传输组合、没有上限的列表或超时, |
| 136 | 以及相互重叠的工具过滤。 |
| 137 | |
| 138 | 远程 MCP URL 必须使用 HTTPS,只有显式的回环 HTTP 端点例外。URL 中不能含用户信息、 |
| 139 | 查询串或片段。字面量请求头一律拒绝:身份验证必须通过 `env_headers` 或 |
| 140 | `bearer_token_env_var` 指定一个来源环境变量。远程插件包必须在 |
| 141 | `capabilities.network_hosts` 中精确声明其端点用到的归一化主机集合; |
| 142 | 端点的协议、归一化主机、端口和路径都绑定到本次审查。重定向有限制, |
| 143 | 且必须保持完全相同的归一化 origin。经过审查的远程传输会使用一个显式禁用代理的 HTTP 客户端: |
| 144 | 插件包从不读取或使用环境中的 `HTTP_PROXY`、`HTTPS_PROXY` 或 `NO_PROXY`, |
| 145 | 因为代理凭据和代理可见的内容,都不在受审查的权限范围内。 |
| 146 | 用户自己写的 MCP 配置保留现有的显式代理支持。 |
| 147 | |
| 148 | 本地 stdio 环境项必须使用精确的 `${SOURCE_ENV}` 引用。审查界面会显示目标名和来源名, |
| 149 | 但从不读取或打印它们的值。插件子进程只继承 Codewhale 清理过密钥的基础环境, |
| 150 | 外加这些经过审查的映射;带凭据的代理变量,以及用户自己写的 MCP 配置所用的更宽泛的兼容环境, |
| 151 | 都不会从环境中继承。绝对路径参数和向上穿越父目录的路径会被拒绝; |
| 152 | 位于插件包内的入口点会在启动前冻结到暂存路径。 |
| 153 | |
| 154 | 审查时,每个 stdio 参数都会以 JSON 字符串无损展示。常见的携带凭据的参数标志 |
| 155 | 和已知的字面量 token 形态都不允许出现在 argv 中;凭据必须改用经过审查的环境变量映射。 |
| 156 | 插件贡献的 MCP OAuth 自 v0.9.1 起已禁用,到 v0.9.6 仍然禁用, |
| 157 | 发现、登录、刷新和 token 存储都包含在内。清单若在插件的某个 MCP 服务器上声明 OAuth |
| 158 | 字段,校验就会失败。 |
| 159 | |
| 160 | ### 生效与未生效的组件面 |
| 161 | |
| 162 | Codewhale 0.9.10 会从内容寻址的运行时快照中激活声明式的 `[skills]`、 |
| 163 | `[mcp_servers.*]`、`[commands]`、`[agents]` 和 `[hooks]` 组件。 |
| 164 | Commands 使用 Markdown 命令文件,Agents 使用 Fleet TOML profile, |
| 165 | Hooks 使用 `HooksConfig` TOML 文件。一个组件可以指向单个文件, |
| 166 | 也可以指向存放同类文件的目录。普通的用户级/工作区级命令和 Agent profile |
| 167 | 优先于插件贡献;受信任的项目 hook 在插件 hook 之后运行。 |
| 168 | |
| 169 | 清单还可以额外登记下面这些未生效的组件面。这些声明照旧参与哈希、审查和展示, |
| 170 | 但不会激活,也不再因此禁用整个插件包: |
| 171 | |
| 172 | ```toml |
| 173 | [lsp] # TOML alias: [lsp_servers] |
| 174 | path = "lsp" |
| 175 | |
| 176 | [native] # TOML alias: [native_extension] |
| 177 | path = "native/index.mjs" |
| 178 | |
| 179 | [capabilities] |
| 180 | filesystem_roots = ["workspace"] |
| 181 | network_hosts = ["api.example.invalid"] |
| 182 | lifecycle_mutation = true |
| 183 | ``` |
| 184 | |
| 185 | (在 `plugin.json` 插件包里,同样的表放在 |
| 186 | `extensions["net.codewhale"]` 下。) |
| 187 | |
| 188 | 接受也好,拒绝也好,都刻意做得显眼,绝不静默: |
| 189 | |
| 190 | - 兼容性按组件判定:所有声明的组件面都有适配器时是 `full`(空插件包也算); |
| 191 | 受支持组件能与具名的未生效组件面并存、照常激活时是 `partial`;插件包只声明了 |
| 192 | Codewhale 暂时还无法激活的组件面时是 `unsupported`。同一套带版本号的激活策略(v3) |
| 193 | 驱动这些标签、运行时适配器和能力哈希。将来某个 Codewhale 版本开始执行 LSP |
| 194 | 或原生代码时,必须修改该策略;策略一变,能力哈希随之改变,就会强制重新审查。 |
| 195 | v1 和 v2 信任回执会以 `capabilities-changed` 失败关闭。 |
| 196 | - **实验性扩展宿主下的 `native`。** 开启 `[features] extension_host` 后,策略升级为 |
| 197 | v4,`native` 成为已生效的适配器:每个条目是一个 `.mjs`、`.js` 或 `.mts` ES 模块文件, |
| 198 | 由 TypeScript 扩展宿主导入。指向目录或其他任何文件时,`/plugin validate` 和审查界面 |
| 199 | 都会报错,并阻止激活。它的工具始终使用 `Required` 审批;Full Access(完全访问)、 |
| 200 | Bypass,或针对该已审查构建的精确会话授权,都可以满足这一要求而不再弹出审批。 |
| 201 | 切换该开关会使每个插件都需要重新审查。详见 |
| 202 | [设计文档](../design/TS_EXTENSION_HOST.md#as-built-phase-1-2026-09-25)。 |
| 203 | [扩展作者指南](../EXTENSIONS.md)包含经过测试的类型化示例、诊断流程, |
| 204 | 以及 Node 可擦除 TypeScript 语法的限制。 |
| 205 | - **已识别但未生效**的声明(`lsp`、`native`、非空的 |
| 206 | `capabilities.filesystem_roots`,或 `capabilities.lifecycle_mutation = true`) |
| 207 | 会像其他组件一样解析、校验(位于包内、存在、无链接)。它会计入清单, |
| 208 | 参与能力回执的哈希计算,在审查界面和 `/plugin show` 里显示为未生效,并且永不执行 |
| 209 | (对 `native` 而言,仅限于扩展宿主开关处于关闭状态时)。 |
| 210 | 经过审查、受信任且适用的混合插件包仍可启用:受支持的声明式组件照常生效, |
| 211 | 未生效的组件面仍旧标为未生效。 |
| 212 | - **全部不受支持**的插件包可以审查、可以信任,但 `/plugin enable` 会失败关闭, |
| 213 | 并列出未生效的组件面。没有任何组件能被诚实地激活。 |
| 214 | - **无法识别**的段或字段属于校验失败,而不是清点条目:未知的顶层 TOML 表、 |
| 215 | 未知的 MCP 服务器字段、未知的 `plugin.json` 根键,以及 |
| 216 | `extensions["net.codewhale"]` 里的未知键,统统直接拒绝。 |
| 217 | 唯一“忽略而不报错”的情况是 Agent Plugins 格式中其他厂商的 `extensions` |
| 218 | 命名空间,标准要求客户端跳过它。 |
| 219 | - `capabilities.network_hosts` 不属于未来才会生效的组件面:它今天就已强制执行, |
| 220 | 且必须与插件包远程 MCP 端点的归一化主机集合完全一致 |
| 221 | (有远程 MCP 端点就必须声明它,没有远程端点就不能声明)。 |
| 222 | |
| 223 | 环境检查或健康检查通过,永远不等于信任。 |
| 224 | |
| 225 | ## 审查、信任与启用 |
| 226 | |
| 227 | 使用会话内的命令界面: |
| 228 | |
| 229 | ```text |
| 230 | /plugin list |
| 231 | /plugin validate example |
| 232 | /plugin show example |
| 233 | /plugin enable example |
| 234 | ``` |
| 235 | |
| 236 | 第一次 `enable` 会打开审查界面,显示来源、组件清单、申请的权限、脱敏后的 MCP 端点、 |
| 237 | 完整的内容哈希和能力哈希,以及未生效的声明。它还会打印一条确认命令(需逐字执行): |
| 238 | |
| 239 | ```text |
| 240 | /plugin trust example <full-content-sha256>.<full-capability-sha256> |
| 241 | ``` |
| 242 | |
| 243 | 审查完插件包之后,再执行这条完整的命令。确认 token 用的是两个完整的 SHA-256 回执, |
| 244 | 不是显示用的前缀。能力回执是 v3 摘要:它照旧哈希完整清单, |
| 245 | 同时还绑定本次构建的激活策略(哪些适配器可执行、哪些只清点)。建立信任时,会先把审查过的 |
| 246 | 整棵树复制到 Codewhale 自有、内容寻址的运行时快照里,并记录匹配的回执;它不激活任何东西。 |
| 247 | 然后再次运行 `/plugin enable example`。信任与启用是两件事: |
| 248 | |
| 249 | - `/plugin disable example` 停止贡献,但保留信任。 |
| 250 | - `/plugin revoke example` 撤销信任,但保留启用位;插件包在重新审查之前一直不生效。 |
| 251 | - `/plugin reload` 在磁盘文件发生变化后重建当前工作区的注册表。 |
| 252 | |
| 253 | (`/plugin install`、`update` 和 `uninstall` 负责把文件本身放好、替换和删除, |
| 254 | 最后总会落到同一套审查上——见 [PLUGINS.md](./PLUGINS.md)。 |
| 255 | `/plugin suggest` 会对已安装的插件包,以及本地添加的市场目录排序;发送匹配的任务时, |
| 256 | 可以用 toast 提示弹出同样的下一步,但不安装任何东西。模型的请求里不会写入任何插件推广内容; |
| 257 | 完整的推荐策略见 [PLUGINS.md](./PLUGINS.md#codewhale-如何推荐插件)。) |
| 258 | |
| 259 | 信任、启用、停用、撤销和重新加载都会立即重建当前工作区的 Skills、MCP、Commands、 |
| 260 | Agent profiles 和 Hooks。每次持久化的状态变更,都会在稳定的跨进程锁下, |
| 261 | 推进各个插件包自己的代数(generation)。代数一变,就会取消正在进行的 MCP 工作, |
| 262 | 移除缓存中的目录条目,终止空闲的插件 stdio 子进程, |
| 263 | 并拒绝那些已持久化入队、携带旧权限回执的 Skills。 |
| 264 | |
| 265 | 审查界面区分远程 MCP 端点和本地 stdio MCP 服务器。本地 stdio 服务器是一个子进程, |
| 266 | 以 Codewhale 用户的宿主文件系统和网络权限运行;插件信任不是操作系统沙箱。 |
| 267 | 因此审查界面会显示命令、参数个数、工作目录、环境变量名,以及这条宿主权限警告, |
| 268 | 但不打印环境变量值或请求头值。服务器启动后,MCP 工具审批仍然照常生效。 |
| 269 | |
| 270 | 信任回执存放在 `~/.codewhale/plugins/state.json`。写入是原子的、仅属主可读写, |
| 271 | 记录完整内容哈希、能力哈希、已审查的能力清单、代数和审查时间, |
| 272 | 并保留最近 32 次审查作为有界的审计记录。状态文件格式错误或不受支持时不会被覆盖: |
| 273 | 在修复或移走该文件之前,所有插件包都失败关闭。 |
| 274 | |
| 275 | 内容哈希覆盖清单、整棵插件包树和可执行形态,按确定的路径顺序计算, |
| 276 | 包括本地 MCP 入口点和随附资源。暂存有大小上限:它会拒绝符号链接和不受支持的文件类型 |
| 277 | (外加所有 Windows reparse point 和硬链接文件),用原子方式替换目标目录; |
| 278 | 在 Windows 上,它通过经过校验的对象句柄施加仅属主可用的运行时权限或 ACL。 |
| 279 | 能力哈希覆盖归一化后的组件与权限清单。源文件或暂存内容被改动、能力发生变化, |
| 280 | 或者运行时的根被不安全地替换,都会确定性地使回执失效;已经启用的插件包会变得不生效, |
| 281 | 直到重新审查。`/plugin update` 依赖的正是这套失效机制:字节被替换后与回执不再匹配, |
| 282 | 就会强制重新审查。 |
| 283 | |
| 284 | ## 运行时行为 |
| 285 | |
| 286 | 生效的插件包必须已启用、当前哈希已受信任、适用于本机,并且没有校验错误。 |
| 287 | 经过审查的混合插件包可以生效,但只有审查过的 v3 激活掩码里受支持的组件可以使用。 |
| 288 | 不受支持的组件仍然列在清单里、参与哈希和审查,但不生效。 |
| 289 | |
| 290 | - Skills 只以 `<plugin>:<skill>` 的形式暴露。面向模型的目录和 `load_skill` |
| 291 | 使用一份绑定到已审查暂存树的内存快照,而不是在执行时去读可变的源路径。 |
| 292 | `load_skill` 在放出内容之前会立即重新校验来源、暂存、回执、工作区和代数。 |
| 293 | 一旦发现漂移,就失败关闭。排队的消息会持久化同样的来源信息, |
| 294 | 并在派发时重复这次检查。`/skills inspect` 会指出它来自哪个已审查的插件包, |
| 295 | 但不暴露其可变的源路径。 |
| 296 | - MCP 服务器名暴露为 |
| 297 | `plugin-<plugin-name-byte-length>-<plugin>-<server>`, |
| 298 | 这样任一部分里的连字符都不会造成权限冲突。停用或未受信任的插件包 |
| 299 | 会在无头 MCP 适配器处再次被拒绝。权限检查发生在这些时机:连接之前、 |
| 300 | 每次惰性 stdio 启动的前一刻、传输层构建之后,以及每个工具/资源/提示操作之前。 |
| 301 | 操作进行期间还会监视持久化的代数/启用/信任状态,因此停用、撤销 |
| 302 | 或其他跨进程状态变更会取消该操作,并终止插件的 stdio 子进程。 |
| 303 | 完整的源树和暂存树哈希会在派发和目录边界处重新校验; |
| 304 | 对已经跑起来的 MCP 调用,运行时不会持续重新哈希这些树。所以源或暂存树的漂移 |
| 305 | 要到下一个边界才会失败,届时丢弃过期的连接或目录条目, |
| 306 | 但不宣称能中断正在执行的调用。每次失败都会附带提示:重新加载、审查、信任, |
| 307 | 然后再次启用插件包。 |
| 308 | - Commands 在普通用户级/工作区级命令和已保存工作流之后加载, |
| 309 | 因此已有定义保持优先,冲突也看得见。命令面板会立即隐藏已撤销的命令; |
| 310 | 派发时会先重新核对完整回执,再展开命令体;遇到过期输入,会给出可见的拒绝提示。 |
| 311 | - Agent profiles 加入 Fleet 名册时,排在显式配置、个人 profile 和 workspace profile |
| 312 | 之后,但在内置项之前。名册冲突时,那条可见的遮蔽记录照旧保留。每次启动 Agent |
| 313 | 都会依据当前注册表重新构建,并在使用所选插件 profile 的提示词或路由之前,重新核对它的权限。 |
| 314 | - Hooks 在全局 hook 之后、受信任的项目 hook 之前合并。前台 Hooks 会在启动进程之前 |
| 315 | 立刻重新核对权限;后台 Hooks 在入队前检查,出队时再检查一次, |
| 316 | 这样已入队但被撤销的 Hook 也不会稍后启动。 |
| 317 | - 普通启动、resume、fork、exec 和 serve 都会先构建一份不可变的工作区级注册表, |
| 318 | 再构建各自依赖插件的目录。 |
| 319 | - 宪章(Constitution)、仓库指令、权限规则、沙箱策略和 MCP 工具审批的优先级, |
| 320 | 始终高于插件指令。 |
| 321 | |
| 322 | `/plugin list`、`show`、`suggest` 和 `validate` 不发起网络请求、不启动进程、 |
| 323 | 不读取凭据、不写配置。审查界面把结构化 argv 渲染为无损的 JSON 字符串, |
| 324 | 并展示环境变量的来源,而不显示其值。携带凭据的 argv 在清单校验阶段就被拒绝; |
| 325 | 由插件产生的错误会屏蔽 URL 查询、身份验证、argv 和环境变量内容。 |
| 326 | `[tools].plugin_dir` 下的旧版可执行工具仍是独立的一套系统,列在 `/plugin tools` 下。 |
| 327 | |
| 328 | ## 截至 v0.9.10 的明确非目标 |
| 329 | |
| 330 | 联邦式市场目录(`/plugin marketplace add|list|show|remove|install`) |
| 331 | 会解析本地 Kimi、Claude、Codex 和 Codewhale 格式的目录文档,见下面的市场小节 |
| 332 | (`/plugin install` 只拉取一个经过审查的来源,`/plugin suggest` 只对已安装的插件包排序)。 |
| 333 | 此外,以下这些同样明确不做:环境兼容性发现、自动信任、插件贡献的 MCP OAuth、 |
| 334 | LSP 适配器和 MCP 订阅适配器;除实验性的 `extension_host` 开关之外,没有原生扩展运行时; |
| 335 | 不导入外部的可执行插件运行时;也不把旧版 `plugin.toml` 自动迁移为磁盘上的 `plugin.json`。显式的离线 |
| 336 | [OpenCode/DSH 转换器](./PLUGIN_AUTHORING.md#转换现有插件)支持选定的可移植 Skills、 |
| 337 | 静态的 Streamable HTTP MCP 声明,以及用 `--stdio-root` 明确选中的已打包 Node |
| 338 | `.mjs`、`.js` 或 `.cjs` MCP 服务器。转换时会把本地源码和依赖一并复制, |
| 339 | 让它们走完同样的原生安装、能力审查、哈希绑定信任和启用流程;转换本身不执行代码, |
| 340 | 也不调用包管理器。它不会迁移任意插件包,也不会复现其他客户端的运行时或策略。 |
| 341 | 上面提到的其他能力属于后续工作,而不是已隐含支持。 |
| 342 | |
| 343 | ## 市场目录(#5311) |
| 344 | |
| 345 | `/plugin marketplace` 按真实发布的 schema 读取本地目录文档 |
| 346 | (Kimi、Claude、Codex、Codewhale 原生;Codex 通过其策略标记), |
| 347 | 并为每个候选项渲染一份诚实的安装计划: |
| 348 | |
| 349 | ```text |
| 350 | /plugin marketplace add <name> <path> # parse a local catalog file (no network) |
| 351 | /plugin marketplace list # catalogs + candidates + diagnostics |
| 352 | /plugin marketplace show <name> # one catalog in detail |
| 353 | /plugin marketplace remove <name> # forget a catalog (plugins unaffected) |
| 354 | /plugin marketplace install <catalog> <candidate> |
| 355 | ``` |
| 356 | |
| 357 | - `add` 从不拉取任何东西:它读取一个本地 JSON 文件(≤4 MiB,只接受普通文件, |
| 358 | 拒绝符号链接),并把解析结果存放在插件状态文件旁边。 |
| 359 | - 目录层级和来源标记(`official`、`curated` 等)**仅用于显示**—— |
| 360 | 它们从不授予信任、启用或安装。 |
| 361 | - 外部策略会被显式忽略:Codex 的 `INSTALLED_BY_DEFAULT` 条目会列出来, |
| 362 | 但带 `NO_AUTO_INSTALL` 警告,在操作者运行安装命令之前不会安装任何东西。 |
| 363 | - Codewhale 无法拉取的来源(npm 包、`command:` 来源、非 tarball URL) |
| 364 | 会标注为 `not installable` 并给出原因。 |
| 365 | - `install` 走与 `/plugin install` 相同的审查安装流程:插件包落盘时是停用且未受信任的, |
| 366 | 在激活之前要先进入哈希绑定的信任审查。 |
| 367 |