ZCode 的”插件生态”是三层结构:官方市场(Builtin + CDN 分片)、Personal Source(用户自加)、以及不入市场的系统内置(node-repl-host、bundled-skills)。三者可卸载性、可见性、分发方式完全不同。领域词汇的唯一裁决来源是根目录 CONTEXT.md。

领域词汇(CONTEXT.md)

概念定义
Official Marketplace官方唯一分发渠道,id = zcode-plugins-official,内容 = Builtin + CDN;是”分发渠道”而非”作者归属”
Builtin Plugin随应用包分发、启动时 seed 进官方市场的插件(官方插件子集)
CDN Plugin官方市场中经官方 CDN、以 sha256 校验 zip 分发、按需下载的插件
Personal Source用户自行添加的一切来源:claude-plugins-official、git/GitHub/URL/本地目录市场、inline 插件
Store Listing vs Plugin ManifestListing 是展示元数据(目录条目);Manifest 是包内 plugin.json 的功能定义
Restorable Builtin被卸载并入持久化抑制态的内置插件,重启不自动 reseed,可从 Public Segment 恢复
Orphaned Installed PluginPersonal Source 被删但安装目录/数据保留的插件,仍可用但不能更新

常量在 packages/shared/src/plugin-marketplaces.ts:ZCODE_OFFICIAL_PLUGIN_MARKETPLACE_ID、CLAUDE_OFFICIAL_PLUGIN_MARKETPLACE_ID、DEFAULT_ENABLED_OFFICIAL_PLUGIN_IDS(须与 bootstrap 定义机械对齐)、DEFAULT_PLUGIN_MARKETPLACES(官方 CDN source)。

插件来源(loader 候选)

apps/zcode-cli/packages/adapters/src/plugins/index.ts 的 resolveCandidates()(:238-277)按序收集:

  1. config.dirs → source:"inline",默认启用(本地/导入插件)
  2. request.officialPluginRoots → source:"official"(本次 seed/兜底的 Builtin 根)
  3. scanOfficialCache() → 官方 cache 目录(优先读 bundled 分片指向的 cachePath)
  4. listInstalledPluginRecords() → 已安装记录(source:"cache")
  • 权威 id:id = ${manifest.name}@${candidate.marketplace}。
  • 内置插件被卸载时只在 user config 写 suppressedBuiltins 标记,发现层据 id 过滤。
  • Manifest 查找顺序:.zcode-plugin/plugin.json → .claude-plugin/plugin.json → .codex-plugin/plugin.json(兼容 Claude Code / Codex;README 只写了前两者,代码实际还兼容 Codex)。

Plugin Manifest(plugin.json)

规范见 apps/zcode-cli/packages/plugin-creator-plugin/skills/plugin-creator/references/plugin-json-spec.md。最小形态:

{
  "name": "my-plugin",
  "version": "0.1.0",
  "description": "The implemented workflow",
  "author": { "name": "Your team" },
  "skills": "./skills"
}

组件字段:skills / commands(目录路径)、hooks、mcpServers、agents、userConfig。变量:${CLAUDE_PLUGIN_ROOT} / ${ZCODE_PLUGIN_ROOT}、${ZCODE_PROJECT_DIR}、${ZCODE_PLUGIN_DATA}、${user_config.<key>}。

Loader 校验:

  • name 匹配 /^[a-z0-9][a-z0-9._-]{0,127}$/,版本缺失兜底 0.0.0。
  • 组件路径必须 resolveInside(pluginRoot),越界报 plugin_component_path_invalid。
  • 仅诊断字段:UNSUPPORTED_COMPONENT_KEYS = [channels, lspServers, outputStyles, settings]。
  • 插件 skill 根 scope:官方 → system,其余 → user,source:"plugin"。

官方市场 = 两个分片合并

apps/zcode-cli/packages/adapters/src/plugins/official-marketplace.ts:

  • 三文件:bundled-marketplace.json、cdn-marketplace.json、合并产物 marketplace.json,位于 <storageRoot>/marketplaces/zcode-plugins-official/。
  • rebuildOfficialMarketplaceSync():合并两分片,同名时以可刷新的 CDN 条目为准,但不清除内置 cache。
  • loadBundledOfficialPluginRootsSync():从 bundled 分片读 cachePath,仅接受位于官方 cache 根下的严格后代路径(信任边界)。

内置插件 seed 机制

apps/zcode-cli/packages/bootstrap/src/app/bundled-plugins.ts:

  • seedBundledOfficialPlugins():从 filesystem 或 SEA 内嵌资源解析 seed 源,写入官方 cache 原子目录 <storageRoot>/cache/zcode-plugins-official/<name>/<version>/。
  • 原子替换:写唯一临时目录 → rename → 旧 target 移 backup;用 .zcode-plugin-seed.json marker 记录内容 hash 与版本;并发多进程用 seed lock + 15s 总预算。
  • 文件白名单 includedTopLevelPaths:.zcode-plugin、agents、commands、dist、docs、hooks、output-styles、package.json、scripts、skills、templates(runtimeTopLevelPaths 可增加如 node_modules)。
  • 失败降级:单插件缺 requiredSeedPaths 只降级该插件,回退可用旧 cache。
  • 官方定义清单 official-plugin-definitions.ts 的 OFFICIAL_PLUGIN_DEFINITIONS,含 name/version/rootCandidates/requiredSeedPaths/listing/defaultEnabled/hostMcpServerNames。

插件生命周期

权威用例目录:docs/plugin-management-lifecycle-case-catalog.md(PLM-LC-001…020)与 docs/plugins/workspace-level-plugin-architecture.md。完整路径:

发现 → 查看详情 → 安装 → 配置 → 启停 → 使用 → 检查更新 → 升级
     → 持久化恢复 → 卸载 / 恢复内置
  • 添加市场 addMarketplace():支持 url|github|git|npm|file|directory|hostPattern|pathPattern|settings;先解析 manifest 不落盘 → 官方 id 守卫 → 原子目录激活 → 写 known_marketplaces.json。
  • 安装 installMarketplacePlugin():解析依赖闭包(禁跨市场依赖除非 allowCrossMarketplaceDependenciesOn,检测环),逐个复制/解压到 cache/{marketplace}/{plugin}/{version}/,原子提交,写 installed_plugins.json。
  • 启停/scope:resolveEnabled() = enabledPlugins[id] ?? defaultEnabled;Workspace/User 优先级 workspace ?? user ?? manifest default。
  • 更新 updateMarketplace():刷新目录并持久化 lastRefreshFailure。
  • 卸载 / 恢复内置 uninstallMarketplacePlugin():--keep-data 保留 data 目录;内置插件转 suppressedBuiltins。
  • 来源删除:只删市场记录,已安装插件转 Orphaned(ADR 0003)。

UI Plugin 与 MCP Apps

主文档 UI_PLUGIN.md(中文 48KB)/ UI_PLUGIN.en.md(英文 461 行)。

能力矩阵:交互式 tool results、会话侧面板、页面调 plugin server、与主会话协作、App 内模型调用、页面工具注册、页面状态与资源更新。当前仅本地桌面 workspace 支持;Web/移动/远端只保留普通 MCP tool records。

Manifest ui.surfaces:

{
  "mcpServers": { "app": { "type": "stdio", "command": "node",
    "args": ["${ZCODE_PLUGIN_ROOT}/dist/server.mjs"], "cwd": "${ZCODE_PROJECT_DIR}" } },
  "ui": { "surfaces": [ { "id": "editor", "title": {"en":"Editor","zh-CN":"编辑器"},
    "server": "app", "resourceUri": "ui://my-panel/editor.html", "availability": "session" } ] }
}
  • server 须注册 ui://... 资源并返回 text/html;profile=mcp-app;tool 用 _meta.ui.resourceUri + _meta.ui.surface 关联。
  • 官方 SDK 版本 pin:page SDK 2.0.0、MCP server SDK 1.29.0。
  • 数据/能力边界:HTML 资源 16 MiB,资源读取 8 MiB;初始 tool result structuredContent 64 KiB、page metadata 16 KiB、content 32 KiB;localStorage/IndexedDB 按 plugin/workspace/account 隔离。
  • 判定规则:提供 ui.surfaces 面板或 tool _meta.ui.resourceUri 页面的才是 UI Plugin;“仅 MCP tools”或”生成 Gen UI 的 skill”都不是。

MCP Apps 沙箱(Electron Main):分区 persist:plugin-sandbox-v2-<hash(appIdentity)>,guest 固定 contextIsolation/sandbox/webSecurity,CSP default-src none,最多 64 实例。详见 desktop。

两类插件的区分

类别标志例子
UI Plugin有 MCP server + HTML page + ui.surfacesvisualize-plugin
内置能力插件仅 Skill/Command/Agent/Hook/MCP 组合,无交互页browser-use-plugin、documents/pdf/presentations/spreadsheets、android/ios-simulator、image-search
创建器/指南提供元能力plugin-creator、skill-creator、zcode-guide

MCP servers(插件侧)

adapters/src/plugins/mcp.ts:

  • 来源合并:.mcp.json(插件根)+ manifest mcpServers,后者覆盖前者。
  • 支持 stdio / http / sse。
  • server 名命名空间 plugin:<pluginName>:<serverName>。
  • 官方鉴权 auth: {type:"zcode_official", provider:"jwt_token"}(仅 http/stdio,sse 禁用;与 oauth 不能共存)。
  • 环境模板:CLAUDE_PROJECT_DIR/ZCODE_PROJECT_DIR、ZCODE_PLUGIN_DATA、ZCODE_PLUGIN_ROOT;sensitive user_config 只允许展开到敏感 sink(env/header/clientSecret),不得进入 command/args/URL。
  • 身份注入:ZCODE_PLUGIN_ID_ENV_KEY 由 resolver 权威覆盖,防第三方伪造 official CUA 身份。

详见 mcp-integration。

已知偏差(本 wiki 分析)

上游 plugin-compat.md 说第三方 hook”只诊断、不注入运行时”,但当前 canRunPluginHooks() 无条件返回 true,所有插件来源的 hooks/hooks.json / manifest hooks 都会被解析并装入 PluginLoadOutcome.hooks(adapters/src/plugins/index.ts:371)。写 hook 信任边界时需明确这是当前实现风险或近期行为变化。NOTICE.md 也指出”插件 Hook 与工作区 Hook 使用不同准入路径”。

相关页面