news 2026/9/10 20:18:00

用 Codewhale plugin-creator 技能搭建本地插件 Bundle:清单、Skill 与信任流程实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用 Codewhale plugin-creator 技能搭建本地插件 Bundle:清单、Skill 与信任流程实战

用 Codewhale plugin-creator 技能搭建本地插件 Bundle:清单、Skill 与信任流程实战

【免费下载链接】CodewhaleOpen-source coding agent for your terminal, built in Rust and on a journey of continuous community improvement. Issues and PRs welcome.项目地址: https://gitcode.com/GitHub_Trending/de/Codewhale

本篇技术指南围绕 Codewhale 内置的plugin-creator技能(crates/tui/assets/skills/plugin-creator/SKILL.md)展开,讲解如何在终端中从零搭建一个本地 Codewhale 插件 bundle:包括plugin.toml版本化清单的字段语义、Skills 与 MCP 服务器的命名空间与声明约束、/plugin命令族的校验-审查-信任-启用全流程,以及为什么 bundle 默认处于 untrusted/disabled 状态。读完本文,你将能够独立创建、校验、审查并启用一个安全的本地插件 bundle,并理解 Codewhale 插件加载器"有界装载、显式信任"的底层机制。

插件加载器的边界:v0.9.1 的"有界装载"模型

Codewhale v0.9.1 的插件加载器是**刻意有界(deliberately bounded)**的:一个被信任且启用的 bundle,只能通过既有引擎向 Codewhale 添加两类声明式组件:

  • 声明式 Skills:以SKILL.md形式挂载的、可被 Agent 调用的技能文档;
  • MCP 服务器:通过既有 MCP 引擎接入的 stdio 或远程服务。

其他组件类型(命令、子代理、钩子、LSP、原生扩展、文件系统根、生命周期变更)在当前构建中仅作清单登记(inventory-only),不会被执行。这一边界同时存在于命令面和源码策略中:在 crates/tui/src/plugins/activation.rs 中,PluginActivationPolicy::current()(激活策略版本 v3)把SkillsMcpStdioMcpRemote(以及声明式的CommandsAgentsHooks)列为受支持适配器,而LspNativeFilesystemRootsLifecycleMutation明确列为 inactive;激活策略还通过capability_hash把"这份策略本身"绑定进信任凭证,未来任何一次适配器策略变更都会让旧的信任凭证以CapabilitiesChanged方式失败关闭(fail closed)。

从源码结构看,这意味着插件系统的安全模型是"最小可执行面 + 显式审查":你能装进去的东西不多,但每一样都会被严格校验、逐项审查后才可能生效。

第一步:选择 Bundle 归属位置与命名

plugin-creator技能的工作流,首先选择一个 Codewhale 拥有的位置存放 bundle,二选一:

  • 用户级 bundle~/.codewhale/plugins/<plugin-name>/,对所有工作区生效;
  • 工作区级 bundle<workspace>/.codewhale/plugins/<plugin-name>/,仅对当前工作区生效。

随后将 bundle 名称规范化为小写连字符形式(lowercase hyphen-case)。这不是风格建议,而是硬性校验规则:在 crates/tui/src/plugins/manifest.rs 的validate_plugin_name中,名称必须为 1~64 个字符,只能由小写 ASCII 字母、数字和内部连字符组成,且首尾字符不能是连字符;plugin.json(Agent Plugins v1.0.0 格式)清单则额外允许内部点号但禁止--..

从源码看,PluginManifest支持plugin.toml(Codewhale 原生/遗留格式)与plugin.json+ 兄弟文件mcp.json(Agent Plugins 标准格式,以及 Kimi 兼容格式)三种编码,解析后统一为同一个PluginManifest结构。plugin-creator技能采用最直接的plugin.toml方式。

第二步:编写版本化清单 plugin.toml

在 bundle 根目录创建plugin.toml。技能给出了最小可运行骨架:

schema_version = 1 [plugin] name = "my-plugin" version = "0.1.0" description = "What this bundle provides" [skills] path = "skills"

结合 crates/tui/src/plugins/manifest.rs 中PluginManifest/PluginMeta的结构体定义,我们可以把这份清单的字段语义完整展开:

字段位置含义与约束
schema_version顶层当前支持的最高版本为1CURRENT_SCHEMA_VERSION);声明超过上限会报错。缺省会被视为遗留清单/plugin validate会提示补写schema_version = 1
[plugin].name插件元信息bundle 名称,规则同上(小写连字符)
[plugin].version插件元信息必须是合法SemVer(如0.1.0),Version::parse校验失败即报错;遗留清单缺失版本时显示0.0.0并告警
[plugin].description插件元信息可选,最长 1024 字符,不含控制字符与双向排版字符
[plugin].author插件元信息可选,最长 256 字符
[plugin].display_name插件元信息可选;当发布用name因标准名规则被 slug 化时,保留人类可读名
[plugin].homepage/repository/license/keywords插件元信息可选,分别有长度上限(homepage/repository 2048、license 128、keyword 128 且去重)
[skills].path组件路径指向 Skill 目录,相对 bundle 根;也可用paths数组把同一种组件拆到多个目录
[commands]/[agents]/[hooks]/[lsp]/[native]组件路径声明式组件位置,结构与[skills]相同(path/paths
[mcp_servers.<name>]MCP 服务器见下文专节
[capabilities]能力声明filesystem_rootsnetwork_hostslifecycle_mutation,仅登记不执行
[when]宿主条件os(支持windows/linux/macos/freebsd/openbsd/netbsd/android/ios)与binaries(裸可执行名,禁止路径分隔符与 Windows 绝对路径)

仓库自带了一个真实样例 crates/tui/assets/plugins/rust-toolkit/plugin.toml,展示了author[when]的用法:

[plugin] name = "rust-toolkit" description = "Rust development toolkit with cargo check integration" version = "0.1.0" author = "Codewhale Team" [skills] path = "skills" [when] os = ["windows", "linux", "macos"] binaries = ["cargo"]

注意:组件路径必须是相对路径,禁止绝对路径、禁止..逃逸、禁止穿越符号链接(resolve_contained_path会逐级做symlink_metadata检查并canonicalize后确认仍位于 bundle 根内)。清单本身也必须是普通文件而非符号链接,大小上限 1 MiB。

第三步:挂载 Skill 并理解命名空间

把每个 Skill 放到skills/<skill-name>/SKILL.md。Codewhale 会将其暴露为my-plugin:<skill-name>这种带命名空间的限定名称,绝不会作为不带前缀的裸命令出现。这一点同样有源码支撑:在 crates/tui/src/commands/groups/skills/skills.rs 中,/skills inspect会输出技能的source与插件来源(plugin provenance),让用户一眼看出某个 Skill 究竟来自哪个 bundle,而非全局命令空间。

这样的设计带来两个实际收益:一是避免不同 bundle 之间的技能名冲突;二是让信任边界清晰——你启用的是"某个插件带来的技能",审查对象始终指向明确的来源。

第四步:声明 MCP 服务器(仅当确实需要)

只有 bundle 确实需要既有 MCP 引擎时才添加[mcp_servers.<name>]。Codewhale 对 MCP 声明的校验异常严格(全部实现在 crates/tui/src/plugins/manifest.rs 的validate_mcp_servers中),并且把 stdio 与远程两类服务器区分管理,因为它们在审查界面上的威胁模型不同。

stdio MCP(本地子进程)

[mcp_servers.my-tool] command = "bin/my-tool" # 必须是裸可执行名,或 bundle 内的相对路径 args = ["--config", "config.json"] env = { "API_KEY" = "${MY_API_KEY}" } # 只允许精确的 ${SOURCE_ENV} 引用 cwd = "." enabled = true required = false

核心约束:

  • commandurl二选一,必须恰好声明其一;
  • stdio 服务器不得声明远程传输或鉴权字段(transportheadersenv_headersbearer_token_env_varscopesoauth等全部禁止);
  • args禁止绝对路径、禁止..逃逸出 bundle 根,且不得内嵌字面量凭据——源码会对token=api-key=secret等敏感键名及sk-ghp_AKIA等凭据形态做启发式拦截,并要求改为"经审查的环境映射";
  • env的值只允许精确的${SOURCE_ENV}引用exact_environment_placeholder会要求字符串严格形如${VAR}),不允许字面量秘密、不允许拼接表达式;
  • 其余限额:args≤ 64、env≤ 64、enabled_tools/disabled_tools各 ≤ 256,超限报错。

远程 MCP(HTTP/HTTPS)

[mcp_servers.remote-api] url = "https://api.example.com/mcp" transport = "sse" # 显式设置时只接受 sse env_headers = { "Authorization" = "${AUTH_TOKEN}" } bearer_token_env_var = "AUTH_TOKEN" enabled = true

核心约束:

  • URL 必须使用HTTPS,或仅当目标是localhost/回环地址时才允许明文 HTTP;
  • URL禁止内嵌用户信息(userinfo/password)、查询参数与 fragment;
  • 禁止字面量headers;鉴权一律走env_headers(环境变量名来源)或bearer_token_env_var
  • 远程服务器不得声明cwdargsenv等 stdio 专属字段;OAuth 字段当前被禁用,报错提示改用环境变量鉴权;
  • [capabilities].network_hosts必须精确等于所有远程 MCP 端点归一化后的主机集合——源码会取出每个 URL 的 host 做规范化(转小写、拒绝带端口/路径/凭据的主机串),与声明值逐一比对,不一致直接校验失败;
  • 清单中任何位置都不得出现凭据:无论是 URL 内嵌、字面量 header 还是参数值,一律以"经审查的环境变量引用"方式注入。

第五步:其他组件类型——只登记、不激活

如果 bundle 需要声明命令、代理(agents)、钩子(hooks)、LSP、原生扩展、文件系统根或生命周期变更,plugin-creator技能的原则是:仅在为未来工作做清单登记时声明它们。Codewhale 会把它们显示为 inactive(未激活),同时仍然激活同一 bundle 中受支持的 Skills 与 MCP——即"混合 bundle 部分激活"。

从 crates/tui/src/plugins/manifest.rs 的PluginInventory::compatibility()可以看出三种兼容性结论:

  • full:所有声明面都有适配器(或 bundle 为空)——可完整激活;
  • partial:支持适配器可激活,其余声明面保持 inactive——可部分激活;
  • unsupported:只声明了当前构建无法激活的面(如仅含 LSP/原生扩展)——该 bundle 无法被启用

这就是技能中"只声明那些不受支持表面的 bundle 不能被启用"的源码依据:can_activate_supported_components()在兼容性为unsupported时返回 false,/plugin enable会直接拒绝。

第六步:校验、审查与信任——先 validate,再 trust,后 enable

plugin-creator技能规定了一个"不执行 bundle 内容"的校验与审查流程(全部命令由 crates/tui/src/commands/groups/plugins/mod.rs 的/plugin分发器实现):

/plugin validate <plugin-name> # 校验清单与组件,报告 warning/error 诊断 /plugin show <plugin-name> # 查看 bundle 详情(组件、能力、兼容性、哈希) /plugin enable <plugin-name> # 打开内容/能力审查界面(未信任时) /plugin trust <plugin-name> <token> # 运行审查后给出的精确确认命令 /plugin enable <plugin-name> # 再次启用

几个关键机制值得展开:

  • 审查令牌绑定完整哈希review_token()生成的确认令牌形如<content_hash>.<capability_hash>——content_hash是对整个 bundle(含所有文件字节与可执行位)的 SHA-256,capability_hash则把激活策略与能力清单一起哈希。用户必须逐字运行界面给出的精确确认命令,而不是拍脑袋输入任何文本;
  • trust 只登记、不激活:从 crates/tui/src/plugins/registry.rs 的trust()实现看,信任操作会先把 bundle 内容**暂存(stage)**为运行时快照,写入TrustReceipt(含两个哈希、被审查能力清单、审查时间),并记录进 review history;关键点:entry.enabled = false被强制置位——即使旧状态曾启用,重新审查后也绝不会隐式重新激活;
  • enable 需要完整前置条件enable()依次检查——已受信任、存在已验证的运行时快照(staged)、[when]条件适用于当前宿主、且至少有一个受支持的声明组件。任何一项不满足都会报错;
  • enable 立即重建目录:启用成功后会立即重建当前工作区的 Skill/MCP 目录(AppAction::PluginRegistryChanged),无需重启或手动刷新。

最后用以下命令做闭环验证:

/skills inspect # 检查 Skill 的插件来源(plugin provenance) /plugin list # 检查预期的信任与激活状态

若 bundle 内容在信任后被更新(/plugin update),其内容哈希必然变化,旧信任凭证不再匹配——必须重新走"审查 → trust → enable"流程,这正是"内容即身份"哈希设计的自愈机制。

安全基线:默认 untrusted、默认 disabled

每个用户级与工作区级 bundle 在创建之初都是未信任且未启用的。plugin-creator技能最后明确划定了 v0.9.1 的功能边界:

  • 不要添加 marketplace(市场)、下载器、更新器、兼容性扫描、可执行扩展运行时或自动信任流程;
  • 这些表面(surface)超出 v0.9.1 范围,不应出现在 bundle 设计中。

这一约束与整个插件信任模型一脉相承:能力边界刻意收窄,信任必须显式、逐次、绑定内容哈希,杜绝任何"装上即运行"或"自动放行"的路径。对需要更强的插件分发、更新或自动化的场景,应等待 Codewhale 后续版本对相应适配器与流程的正式支持,而不是绕过审查机制自行扩展。

小结

借助内置的plugin-creator技能,搭建 Codewhale 本地插件 bundle 的完整路径可以归纳为四步:定位置与命名 → 写版本化plugin.toml→ 挂载命名空间 Skills / 声明受约束的 MCP → 用/plugin命令族完成 validate → show → trust → enable 的显式审查闭环。整个过程由 crates/tui/src/plugins/manifest.rs 的清单校验、crates/tui/src/plugins/activation.rs 的激活策略、crates/tui/src/plugins/registry.rs 的信任状态机共同保障:内容以 SHA-256 绑定身份,能力以策略哈希防漂移,信任与激活彻底分离,最终让"可扩展性"与"可审计性"在同一个有界加载器内达成平衡。

【免费下载链接】CodewhaleOpen-source coding agent for your terminal, built in Rust and on a journey of continuous community improvement. Issues and PRs welcome.项目地址: https://gitcode.com/GitHub_Trending/de/Codewhale

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 20:17:27

假期作业三:极简技术栈实现情绪记账、自动备份与实时数据看板

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 20:16:54

固定污染源温室气体多组分监测标准技术要点解读

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 20:13:31

宠物寄养小程序开发:物联网与WebRTC技术实践

1. 项目背景与核心价值去年夏天帮朋友临时照看金毛犬时&#xff0c;发现传统宠物寄养存在三大痛点&#xff1a;主人无法实时查看宠物状态、寄养环境信息不透明、紧急情况沟通滞后。这款小程序正是为解决这些行业顽疾而生&#xff0c;通过数字化手段重构宠物寄养服务流程。市场上…

作者头像 李华
网站建设 2026/9/10 20:12:13

多无人机部署优化:基于BCD+GA的吞吐量与飞行时间平衡方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 20:11:35

交换机品牌怎么选?十大品牌深度对比与选型实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华