Book 第三十八章:插件系统为什么要把 Marketplace 和运行时分层
第六部分:迁移与附录

第三十八章:插件系统为什么要把 Marketplace 和运行时分层

拆 marketplace 声明层、物化层、安装链路、热更新和组织治理。

1. 为什么这章必须单独拆

前面我们已经拆过 MCP 和 Skill。

但 Claude Code 的 plugin 线,并不是 MCP 的一个轻薄包装。

从源码看,这里至少同时存在几层东西:

  • marketplace 声明层
  • marketplace 物化状态层
  • 插件安装与缓存层
  • 插件加载与命令/技能注入层
  • 插件 hook 热更新层
  • 组织策略治理层

这说明 plugin system 不是“装个包”,而是一整套扩展供应链。

相关源码锚点:

  • src/utils/plugins/marketplaceManager.ts
  • src/utils/plugins/reconciler.ts
  • src/utils/plugins/pluginLoader.ts
  • src/utils/plugins/pluginPolicy.ts
  • src/utils/plugins/loadPluginHooks.ts
  • src/services/plugins/PluginInstallationManager.ts

2. 先说结论

我对这一块的判断是:

Claude Code 的插件系统,重点不是“如何运行插件”,而是“如何把插件生态受控地引进 runtime”。

最关键的结论有五个:

  1. Marketplace declaration 和 materialized state 是分开的。
  2. 插件安装、缓存、加载、激活是几层不同职责。
  3. 插件不只加命令和技能,还会热插 hooks。
  4. 后台 reconcile 和前台 AppState 是桥接关系,不是一个层。
  5. 组织级策略可以在 plugin 入口直接拦截。

3. 总体结构图

flowchart TD
    A["settings / add-dir / 官方 fallback"] --> B["marketplaceManager<br/>声明层"]
    B --> C["known_marketplaces.json<br/>物化状态"]
    C --> D["reconciler<br/>install / update"]
    D --> E["PluginInstallationManager"]
    E --> F["pluginLoader"]
    F --> G["commands / skills / hooks 注入"]
    G --> H["AppState.plugins"]
    I["policySettings"] --> F
    I --> G

4. Marketplace:为什么要分 intent layer 和 materialized layer

源码锚点:

  • src/utils/plugins/marketplaceManager.ts

这一层是整套设计里最值钱的部分之一。

它明确把 marketplace 分成两种状态:

4.1 声明层

也就是“用户或配置想要什么”:

  • merged settings 里的 marketplace 声明
  • add-dir 形式的补充来源
  • 官方 marketplace 的隐式 fallback

4.2 物化层

也就是“本地现在实际认得哪些 marketplace”:

  • known_marketplaces.json
  • ~/.claude/plugins/marketplaces/
  • cache 状态

这样拆的好处特别直接:

  • 可以先表达意图,再后台 reconcile
  • 可以容忍网络、缓存、安装状态滞后
  • 不把配置文件直接当成安装结果

5. Reconciler:这是后台供应链,不是 UI 逻辑

源码锚点:

  • src/utils/plugins/reconciler.ts

diffMarketplaces() 会先把 declared 和 materialized 做 diff,分成:

  • missing
  • sourceChanged
  • upToDate

然后 reconcileMarketplaces() 再做真正的安装或更新。

这里很关键的一点是:

  • 它本身不改 AppState
  • 它是加法式、幂等式的后台 reconcile

这意味着作者故意把:

  • “后台把东西准备好”
  • “前台要不要刷新视图”

拆成两层。

6. pluginLoader.ts:运行时激活层

源码锚点:

  • src/utils/plugins/pluginLoader.ts

加载器这一层管的是:

  • marketplace-based plugin
  • session-only --plugin-dir
  • manifest 校验
  • 重名冲突
  • enable/disable 状态
  • 版本化缓存目录
  • legacy cache fallback
  • seed cache 探测

这里最值钱的设计点是:

作者没有把“插件目录里有个文件”直接等同于“runtime 能安全激活这个插件”。

中间插了完整的校验和缓存层。

7. Hooks 热插拔:插件不是只会加命令

源码锚点:

  • src/utils/plugins/loadPluginHooks.ts

这一层非常说明问题。

它会把插件 hook 配置转成 runtime matcher,然后:

  • 原子地 clear 再 register
  • 监听 policy settings 变化
  • 计算 plugin-affecting settings snapshot
  • 清 cache
  • 触发 fire-and-forget reload

这说明 Claude Code 的插件系统不是“启动时装好,之后不动”。

它允许一部分扩展面热更新。

而且作者专门修过 stop hook 在 clear 后静默丢失的问题,说明这条线已经是生产级运行时的一部分。

8. PluginInstallationManager:前后台桥接层

源码锚点:

  • src/services/plugins/PluginInstallationManager.ts

这层的职责很清楚:

  • 先计算 diff
  • 把 pending 状态写进 AppState.plugins.installationStatus
  • 跑 marketplace reconcile
  • 如果是新 marketplace,就 auto-refresh active plugins
  • 如果只是更新,则标 needsRefresh

这说明它不是“安装器”那么简单,而是:

把后台供应链结果翻译成 UI/runtime 可观察状态的桥。

9. Governance:组织策略怎么卡在插件入口

源码锚点:

  • src/utils/plugins/pluginPolicy.ts

pluginPolicy.ts 是个很小、但很值钱的叶子模块。

它只做一件事:

  • policySettings 读取组织级 plugin allow/deny 配置

这个设计很成熟,因为它避免了:

  • loader 自己去到处依赖 settings
  • 插件治理逻辑散落进各个激活点

也就是说,扩展治理被故意做成了明确的闸门。

10. 这套设计真正回答了什么问题

如果把这些层放在一起看,Claude Code 实际上回答了五个生态问题:

  1. 插件市场从哪里声明
  2. 本地怎么确认哪些市场已物化
  3. 插件怎么安装、缓存和升级
  4. 插件怎样在 runtime 中被激活或热更新
  5. 组织级策略怎么压住扩展入口

这比“插件机制”这个词本身要具体得多。

11. 对 C# 拆分最有用的建议

如果后面做 C# 版,这层至少应该拆成五个边界:

11.1 MarketplaceRegistry

负责:

  • marketplace intent
  • marketplace materialization
  • known state persistence

11.2 MarketplaceReconciler

负责:

  • diff
  • install / update
  • 幂等后台同步

11.3 PluginCatalogLoader

负责:

  • manifest 校验
  • cache/version 解析
  • enable/disable 决策

11.4 PluginRuntimeActivator

负责:

  • command / skill / hook 注入
  • refresh / hot reload

11.5 PluginGovernanceGuard

负责:

  • org allow/deny
  • provider / managed settings 约束

12. 一句话收口

Claude Code 的 plugin system 最值得学的地方,不是“支持插件”,而是它把 marketplace、安装、加载、热更新和组织治理拆成了一条受控供应链。