基于 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.tsxsrc/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,   // 依赖也一起写入
  }
})

写入路径:

  • user scope → ~/.claude/settings.json
  • project scope → .claude/settings.json
  • local scope → .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
GitHubSSH/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.tsCLI 命令入口
src/services/plugins/pluginCliCommands.tsCLI 包装层
src/services/plugins/pluginOperations.ts核心操作 installPluginOp
src/utils/plugins/pluginInstallationHelpers.tsinstallResolvedPlugin + cacheAndRegisterPlugin
src/utils/plugins/marketplaceManager.tsmarketplace 搜索与缓存
src/utils/settings/settings.tssettings.json 读写
src/utils/plugins/installedPluginsManager.tsinstalled_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 执行流程

  1. 检查是否为 seed-managed(企业强制,不可删除)
  2. 从 known_marketplaces.json 移除
  3. 删除缓存目录
  4. 清理 settings.json 中该 marketplace 的 enabledPlugins 条目
  5. 标记相关插件版本为 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

相关链接