基于 Claude Code 源码(
/Users/zhaoweiguo/6ai/opensources/Claude-Code/src)的实现分析,非官方文档。
两种安装方式的区别
/plugin install(slash command) | claude plugin install(CLI) | |
|---|---|---|
| 运行环境 | REPL 内 | 终端 |
| 界面 | 交互式 Ink UI(React 组件) | 文本输出 |
| 入口 | src/commands/plugin/plugin.tsx | src/main.tsx(Commander.js) |
| 适合场景 | 手动操作 | 脚本/自动化 |
两者底层共用同一套 installPluginOp() 逻辑。
/plugin slash command 别名:plugins、marketplace,支持子命令:install / uninstall / enable / disable / manage / marketplace。
三层架构模型
Intent Layer → settings.json(声明哪些插件要启用)
State Layer → known_marketplaces.json(marketplace 注册表)
Materialization → ~/.claude/plugins/cache/(实际插件代码)
核心设计思路:Settings-First——先写 settings 声明意图,再异步物化缓存;启动时 reconcile 未物化的插件。
完整调用链
pluginInstallHandler() # src/cli/handlers/plugins.ts
└─ installPlugin(plugin, scope) # src/services/plugins/pluginCliCommands.ts
└─ installPluginOp(plugin, scope) # src/services/plugins/pluginOperations.ts
└─ installResolvedPlugin() # src/utils/plugins/pluginInstallationHelpers.ts
执行步骤详解
第 1 步:解析插件标识符
const { name, marketplace } = parsePluginIdentifier(plugin)
// "my-plugin" → { name: "my-plugin", marketplace: undefined }
// "my-plugin@my-market" → { name: "my-plugin", marketplace: "my-market" }第 2 步:在 marketplace 中搜索插件
- 指定了 marketplace → 只搜那一个(
getPluginById) - 没指定 → 遍历所有已配置的 marketplace(
loadKnownMarketplacesConfig+getMarketplace,内存 memoized)
第 3 步:策略检查 + 依赖解析
// 企业策略黑名单检查
if (isPluginBlockedByPolicy(pluginId)) return { ok: false, reason: 'blocked-by-policy' }
// 计算传递依赖闭包(递归)
const resolution = await resolveDependencyClosure(pluginId, ...)
// resolution.closure = ["my-plugin@market", "dep-a@market", "dep-b@market"]
// 对每个依赖也做策略检查
for (const id of resolution.closure) { ... }第 4 步:写入 settings(声明意图,原子操作)
updateSettingsForSource(settingSource, {
enabledPlugins: {
...existing,
"my-plugin@my-market": true,
"dep-a@my-market": true, // 依赖也一起写入
}
})写入路径:
userscope →~/.claude/settings.jsonprojectscope →.claude/settings.jsonlocalscope →.claude/local-settings.json
第 5 步:物化缓存(对闭包中每个插件)
① cachePlugin(source)
→ 根据 source 类型下载/复制到 ~/.claude/plugins/cache/(临时路径)
② calculatePluginVersion()
→ git SHA / npm version / 内容 hash
③ rename 到版本化路径
→ ~/.claude/plugins/cache/{marketplace}/{plugin}/{version}/
④ addInstalledPlugin()
→ 写入 installed_plugins_v2.json,记录 version/installedAt/installPath/gitCommitSha
第 6 步:清理内存缓存
clearAllCaches() // 让下次加载能看到新安装的插件Marketplace 来源类型
| 类型 | 说明 |
|---|---|
| URL | 直接下载 marketplace.json |
| GitHub | SSH/HTTPS git clone(自动探测 SSH 是否可用) |
| Git | 显式 git URL + 可选 ref/sparse-checkout |
| File | 本地路径 |
| Settings | 内联定义 |
| NPM | 规划中,未实现 |
安装 Scope
local > project > user > managed(企业强制)
关键设计要点
- 依赖闭包原子写入:主插件 + 所有传递依赖在一次
updateSettingsForSource调用中写入,避免部分安装状态 - 版本化缓存路径:
{marketplace}/{plugin}/{version}/,支持多版本共存 - ZIP 缓存:可选,节省磁盘空间(
CLAUDE_CODE_PLUGIN_ZIP_CACHE环境变量控制) - 幂等性:重复安装同一插件是 no-op
- 稀疏 checkout:大 monorepo 只 clone 需要的路径
关键文件
| 文件 | 职责 |
|---|---|
src/commands/plugin/plugin.tsx | /plugin slash command 入口 |
src/cli/handlers/plugins.ts | CLI 命令入口 |
src/services/plugins/pluginCliCommands.ts | CLI 包装层 |
src/services/plugins/pluginOperations.ts | 核心操作 installPluginOp |
src/utils/plugins/pluginInstallationHelpers.ts | installResolvedPlugin + cacheAndRegisterPlugin |
src/utils/plugins/marketplaceManager.ts | marketplace 搜索与缓存 |
src/utils/settings/settings.ts | settings.json 读写 |
src/utils/plugins/installedPluginsManager.ts | installed_plugins_v2.json 管理 |
总结
Claude Code 的 plugin install 采用”声明式意图 + 异步物化 + 启动时 reconcile”模式,与 K8s desired state 思路一致。安装操作分两阶段:先原子写入 settings(不可失败),再逐个物化缓存(可重试)。依赖解析在写入前完成,确保整个闭包一次性启用。
/plugin marketplace 命令
子命令列表
/plugin marketplace add <target> # 添加 marketplace
/plugin marketplace remove <name> # 移除 marketplace(别名 rm)
/plugin marketplace update <name> # 更新 marketplace
/plugin marketplace list # 列出所有 marketplace
/plugin marketplace # 打开交互式菜单
marketplace add 执行流程
以 /plugin marketplace add Lum1104/Understand-Anything 为例:
1. 解析输入(parseMarketplaceInput.ts)
支持多种格式:
| 输入格式 | 解析结果 |
|---|---|
Lum1104/Understand-Anything | { source: 'github', repo: 'Lum1104/Understand-Anything' } |
Lum1104/Understand-Anything#main | { source: 'github', repo: '...', ref: 'main' } |
git@github.com:owner/repo.git | { source: 'git', url: '...' } |
https://example.com/marketplace.json | { source: 'url', url: '...' } |
./local/path | { source: 'file'/'directory', path: '...' } |
2. 策略检查:验证企业 allowlist/blocklist
3. 克隆仓库(loadAndCacheMarketplace)
- 自动探测 SSH 是否可用(
isGitHubSshLikelyConfigured(),2s 超时) - 优先 SSH:
git@github.com:Lum1104/Understand-Anything.git - 降级 HTTPS:
https://github.com/Lum1104/Understand-Anything.git - 浅克隆:
--depth 1 --recurse-submodules --shallow-submodules
4. 读取 marketplace 定义
- 默认路径:
.claude-plugin/marketplace.json(可通过source.path覆盖) - 校验 schema,提取 marketplace 名称
5. 写入注册表(~/.claude/plugins/known_marketplaces.json)
{
"Understand-Anything": {
"source": { "source": "github", "repo": "Lum1104/Understand-Anything" },
"installLocation": "~/.claude/plugins/marketplaces/Understand-Anything",
"lastUpdated": "2026-05-26T03:27:00.000Z"
}
}marketplace remove 执行流程
- 检查是否为 seed-managed(企业强制,不可删除)
- 从
known_marketplaces.json移除 - 删除缓存目录
- 清理
settings.json中该 marketplace 的enabledPlugins条目 - 标记相关插件版本为 orphaned
marketplace update 执行流程
- GitHub/Git 源:在已有目录执行
git pull origin HEAD,失败则重新克隆 - URL 源:重新下载 marketplace.json
- 更新
lastUpdated时间戳
完整使用示例
# 添加第三方 marketplace
/plugin marketplace add Lum1104/Understand-Anything
# 安装该 marketplace 中的插件
/plugin install understand-anything
# 等价于指定 marketplace
/plugin install understand-anything@Understand-Anything相关链接
- plugins — 官方插件创建文档
- extend-claude-code — 扩展 Claude Code 概览