返回 CodeWhale
PLUGINS.md
根目录 / docs / zh_hans / PLUGINS.md
1 # 安装插件
2
3 > 英文原文:[PLUGINS.md](../PLUGINS.md)。
4 > 最后与英文同步日期(last synced with English revision):2026-09-26。
5
6 想做一个插件包,先从[编写你的第一个 Codewhale 插件](./PLUGIN_AUTHORING.md)
7 和里面可运行的 Skills 示例入手。
8
9 本文是 `/plugin install` 这条入口链路的分步说明(v0.9.4,#5182)。
10 插件包的格式、发现、校验,以及信任/启用生命周期,仍以
11 [PLUGIN_BUNDLES.md](./PLUGIN_BUNDLES.md) 为准;插件包格式即 `plugin.json`、
12 兼容的 `kimi.plugin.json`、`.claude-plugin/plugin.json`,或旧版 `plugin.toml`。
13 本文讲的是文件最初怎么落盘。
14
15 `/plugin suggest <task>` 是一个本地、只读的配套命令:它会按名称、关键词、
16 描述、所含 skill 名、声明的主机,给已安装的插件包排序,也给你用
17 `/plugin marketplace add` 添加的市场目录排序。它还会说明匹配的原因,
18 并给出下一步:审查、启用,或从目录安装。但它自己从不安装、信任或启用插件包。
19
20 ## Codewhale 如何推荐插件
21
22 Codewhale 在插件上只帮忙,不推销。规则如下:
23
24 - **只有一处会主动提示。** 当你发送的任务匹配到某个已安装但闲置的插件,
25 或某个你还没有的目录候选项时,可以弹出一条安静的 toast,
26 例如 `/plugin trust supabase` 或
27 `/plugin marketplace install <catalog> supabase`。你打字时什么都不会出现,
28 插件推广内容也不会被塞进你的消息里。
29 - **只有一个开关。** 关掉 `contextual_tips` 之后,任何地方都不会再出现插件引导。
30 必须出现的通知和你自己执行的 `/plugin` 命令照常可用。
31 - **只有一份配额。** 插件推荐与其他提示共用每会话的引导配额。
32 在交互式 TUI 里,模型每个会话可以调用一次 `request_plugin_install`,
33 请你审查任务需要的某个插件;第二次调用会失败。
34 Exec、ACP 和 runtime-API 会话拿不到这个工具。
35 - **内置插件从不作为推荐出现。** Computer Use 这类内置插件,
36 只会出现在 `/plugin list` 和 Extensions 里。
37 - **只认具体词。** 泛化词(accessibility、browser、chrome、docs、screenshot、
38 web、wiki 等)永远不触发推荐。匹配器和市场的 `check-marketplace.mjs`
39 共用同一份停用词表。
40 - **只推荐本机跑得起来的。** 插件的 `when.os` 若排除了当前操作系统,就不会被推荐。
41 - **给出真正的下一步。** 模型请求的那一行会按插件的实际需要写成 Install、
42 Review trust 或 Enable。只有那个按钮可点,它打开的是 `/plugin show <name>`;
43 它从不安装、信任或启用。
44 - **关闭可以撤销。** 按 Esc 时,如果草稿非空,先清空草稿,然后才隐藏这一行,
45 而且只对当前会话生效。“Don't suggest again”是你显式做出的选择,
46 会被持久保存。`/plugin dismissals` 会列出这两种;
47 `/plugin dismissals reset [<name>]` 可以让被关闭的插件重新出现在推荐里。
48 - **新插件要靠自己找。** 想找新插件,就看这些文档、`/plugin marketplace list`、
49 Extensions,以及下面的浏览器指南。
50
51 Codewhale 不会凭空编造远程插件 URL;缺失的插件只会从你添加过的目录里推荐。
52 磁盘上的插件包有变化时,发送消息时和回合之间仍会弹出 `/plugin reload` 的 toast。
53
54 ## 浏览器:选一个
55
56 操控浏览器有好几种方式。区别在于用谁的浏览器,以及它能看见什么。
57
58 | 选项 | 用的是谁的浏览器 | 适合 |
59 | --- | --- | --- |
60 | `chrome-devtools` MCP(`/mcp recommendations`) | 它自己驱动的一个 Chrome,可以包含已登录的页面 | DevTools 级别的检查和性能分析 |
61 | Playwright MCP(`/mcp recommendations`) | 带 `--isolated` 的全新隔离 profile | 不带你身份的脚本化流程和测试 |
62 | Computer Use 的 `browser_*` 工具(内置,审查前关闭) | 它自己启动的浏览器,用独立的 profile | 更宽泛的桌面任务里的浏览器步骤 |
63 | Chromewhale(开发者预览版,`codewhale-hq/codewhale-plugin-marketplace`) | 你自己的、已经打开的 Chrome profile;以 unpacked 方式加载 | 读取或操作你当前正看的标签页,每次授权一个站点 |
64
65 这些都不会主动推荐给你。按任务需要自己添加。
66
67 ## 来源
68
69 `/plugin install <spec>` 接受三种来源:
70
71 ```text
72 /plugin install ./path/to/bundle # local directory (copied)
73 /plugin install github:owner/repo # GitHub archive of the default branch
74 /plugin install https://example.com/x.tar.gz # direct tarball URL
75 ```
76
77 v1 没有注册表索引,也不做 `git clone`,只拉 tarball。
78 安装器的大小上限和“不允许符号链接”这两条保证,正靠这一点守住。
79 下载由逐域名的网络策略把关:未知主机会返回一条“需要审批”的错误,并点出主机名
80 (先 `/network allow <host>`,再重试);被拒绝的主机直接中止,不碰磁盘。
81
82 拉下来的目录树里必须**有且只有一个**插件包根目录。所谓根目录,
83 就是放着 `plugin.json`、兼容的 `kimi.plugin.json`、`.claude-plugin/plugin.json`
84 或旧版 `plugin.toml` 清单的那个目录。Kimi 插件包使用 Codewhale 兼容的 skills、commands、agents 和 MCP 声明时
85 会被接受;不支持的 Kimi 运行时字段会失败关闭,而不是被静默忽略。
86 插件包落到用户插件根目录 `~/.codewhale/plugins/<name>/`,
87 其中的 `<name>` 来自清单里的插件名。
88
89 Claude 插件包的元数据放在 `.claude-plugin/plugin.json`,组件放在插件包根目录。
90 导入器支持 skills、commands、agents,以及内联声明或写在根目录 `.mcp.json` 里的
91 MCP 服务器(服务器映射可以是平铺的,也可以包在 `mcpServers` 下)。
92 Claude 的 `http` 传输映射为 Streamable HTTP。
93 `.claude-plugin/marketplace.json` 目录里的相对来源,会从市场仓库的根目录解析。
94 整个插件包仍要接受与原生插件相同的审查哈希和路径检查。
95
96 远程 MCP 请求头可以只写出凭据的名字,不把凭据本身写进去:authorization 值只要与
97 `Bearer ${ENV_NAME}` 完全一致,就会转成 `bearer_token_env_var`;请求头值只要与
98 `${ENV_NAME}` 完全一致,就会转成 `env_headers`。导入过程不读取任何凭据值。
99 字面量凭据和复合模板会被拒绝。
100
101 这是一个兼容子集:hooks、LSP 声明、自定义 MCP 文件路径和
102 `${CLAUDE_PLUGIN_ROOT}` 展开都会被拒绝,并给出原因;不会装出半个插件。
103 安装远程 MCP 声明不等于完成它的身份验证。
104 插件贡献的远程服务器仍保留现有的显式凭据要求;这个导入器不启用插件 OAuth。
105
106 ## 引导流程
107
108 安装从不激活任何东西。命令把文件放好,然后直接把你带进标准的能力审查:
109
110 ```text
111 /plugin install github:someone/neat-plugin
112 → Installed plugin 'neat-plugin' to ~/.codewhale/plugins/neat-plugin.
113 It is disabled and untrusted. Review its requested authority below…
114 <full inventory, permissions, MCP authority render>
115 /plugin trust neat-plugin <content-hash>.<capability-hash>
116
117 /plugin trust neat-plugin <paste the token> # records the hash-bound receipt
118 /plugin enable neat-plugin # activates for this workspace
119 ```
120
121 这里渲染的审查内容和确认 token 与 `/plugin trust <name>` 完全相同。
122 信任走的是严格的、绑定哈希的回执流程,不是一个仅供参考的标记。
123 插件包的内容或声明的能力一旦变化,回执就不再匹配,插件随之失效,直到你重新审查。
124
125 ## 更新与卸载
126
127 ```text
128 /plugin update <name> # re-download, byte-compare, atomic swap if changed
129 /plugin disable <name> # required before uninstall
130 /plugin uninstall <name> # deletes the bundle and prunes its state entry
131 ```
132
133 - `update` 会重新下载记录在案的来源。字节完全相同就什么都不做;
134 有变化的插件包会被原子替换,其信任回执自动失效(哈希不再匹配),
135 所以想让插件再次激活,必须重新审查。从本地路径安装的插件无法重新下载。
136 要替换已安装的副本,先停用再卸载,然后运行 `/plugin install <path>`
137 并审查新的插件包;原来源目录保持不动。参见
138 [本地编写循环](./PLUGIN_AUTHORING.md#4-修改并重新审查)。
139 - `uninstall` 拒绝卸载已启用的插件(先停用),删除插件包目录,
140 并移除它持久化的信任/启用记录。
141
142 ## 安全规则
143
144 - 每次安装都会带一个 `.installed-from` 来源标记。缺少这个标记的插件包,
145 安装器**拒绝覆盖或删除**——手工放到 `~/.codewhale/plugins/` 下的插件包,
146 永远不会被覆盖。
147 - tarball 有大小上限,而且会先解压到一个私有暂存目录。路径穿越(`..`、绝对路径)
148 和插件包里的符号链接/硬链接都会被拒绝;等所有检查都通过,
149 目标目录才会出现,这一步走的是原子重命名。
150 - 安装前会拿名称与内置插件包、工作区插件包比对,
151 防止优先级更高的插件包被这次安装悄悄遮蔽,也防止它反过来遮蔽这次安装。
152 - 新装的文件一律**停用且未受信任**;启用只能走上面那套显式的信任审查。
153
153 lines MARKDOWN