Harness Marketplace 剖析系列 - 之 Claude Code:Marketplace 如何发现、安装与落盘
上一篇我们从静态目录和配置文件入手,梳理了 Claude Code 的扩展体系:
Marketplace
↓
Plugin
├── Skill
├── Command
├── Agent
├── Hook
├── MCP Server
└── LSP Server
↓
Claude Code Harness
其中:
marketplace.json
→ 描述 Marketplace 中有哪些 Plugin
plugin.json
→ 描述一个 Plugin 自身包含哪些能力
但仅仅知道这些目录还不够。
当我们执行:
/plugin marketplace add anthropics/claude-code
/plugin install commit-commands@claude-code-plugins
Claude Code 背后到底做了什么?
例如:
Marketplace 注册信息写到了哪里?
Marketplace 仓库是直接使用还是复制到本地?
Plugin 会不会继续引用 Marketplace 原始目录?
不同安装作用域究竟改变了什么?
更新时会不会覆盖当前版本?
卸载后缓存是否立即删除?
有没有真正意义上的版本回滚?
这一篇,我们沿着下面这条链路继续追踪:
添加 Marketplace
↓
记录 Marketplace 声明
↓
拉取并缓存 Marketplace
↓
读取 marketplace.json
↓
选择 Plugin
↓
下载并复制 Plugin
↓
写入版本化 Plugin Cache
↓
写入 enabledPlugins
↓
Harness 重新加载
一、先区分三个容易混淆的动作
在 Claude Code 中,下面三个动作不是一回事:
添加 Marketplace
安装 Plugin
启用 Plugin
它们分别对应能力供应链中的不同阶段。
1. 添加 Marketplace
/plugin marketplace add ...
它解决的是:
Claude Code 去哪里发现 Plugin?
添加 Marketplace 后,只是注册了一个插件目录,并没有自动安装其中的所有 Plugin。
官方文档明确将 Marketplace 使用过程分为两步:
第一步:添加 Marketplace
→ 注册 Catalog,可以浏览 Plugin
第二步:安装具体 Plugin
→ 下载并启用选中的能力包
因此,Marketplace 更接近“软件源”,而不是软件本身。
2. 安装 Plugin
/plugin install plugin-name@marketplace-name
它解决的是:
从 Marketplace 指定的 Source 中获取某个 Plugin,并把它安装到本机。
Plugin 安装时,Claude Code 不会简单地长期引用远程仓库或者 Marketplace 中的原始目录,而是会把 Plugin 复制进本机的版本化缓存。
3. 启用 Plugin
安装并不只是下载文件,还会在某个配置作用域中声明:
plugin-name@marketplace-name = enabled
这决定了 Claude Code 启动时是否将这个 Plugin 纳入当前能力集合。
因此:
Marketplace 注册
→ 决定从哪里找
Plugin Cache
→ 决定代码放在哪里
enabledPlugins
→ 决定是否加载
这是理解 Claude Code 本地结构最重要的三个概念。
二、Marketplace 的发现来源
Claude Code 当前可以从多种来源发现 Marketplace。
Marketplace Source
├── 官方内置 Marketplace
├── GitHub Repository
├── 普通 Git Repository
├── 本地目录
├── 本地 marketplace.json
├── 远程 marketplace.json URL
├── settings.json 内联 Marketplace
└── Container Seed Directory
1. 官方 Anthropic Marketplace
官方 Marketplace 名称是:
claude-plugins-official
当前版本的 Claude Code 通常会自动提供该 Marketplace,用户可以直接通过 /plugin 的 Discover 页面浏览,或者使用:
/plugin install github@claude-plugins-official
不过官方文档也保留了手动添加方式:
/plugin marketplace add anthropics/claude-plugins-official
当本地没有注册官方 Marketplace,或者本地状态异常时,可以通过该命令重新添加。
这说明“内置 Marketplace”并不等同于:
Marketplace 内容永远打包在 Claude Code 二进制内部
更准确地说,它是:
Claude Code 默认认识或自动注册的官方 Marketplace Source
其实际 Catalog 和 Plugin 内容仍然可以通过本地缓存和远程仓库更新。
2. GitHub 仓库
最常用的第三方 Marketplace 来源是 GitHub:
/plugin marketplace add owner/repository
例如:
/plugin marketplace add anthropics/claude-code
Claude Code 会在这个仓库中查找:
.claude-plugin/marketplace.json
然后将其解析为 Marketplace Catalog。
还可以固定到特定 Branch 或 Tag:
claude plugin marketplace add acme-corp/claude-plugins@v2.0
这里的 @v2.0 表示 Marketplace 跟随该 Ref,而不是默认分支。
3. 普通 Git 仓库
GitLab、Bitbucket、自建 Git Server 同样可以使用:
claude plugin marketplace add \
https://gitlab.example.com/team/plugins.git
也可以使用 SSH:
claude plugin marketplace add \
git@gitlab.com:company/plugins.git
如果需要固定 Ref:
claude plugin marketplace add \
https://gitlab.com/company/plugins.git#v1.0.0
Claude Code 使用当前机器已有的 Git 凭据体系,包括 Credential Helper、SSH Key 和 ssh-agent。
4. 本地目录
开发 Marketplace 时,可以直接添加本地目录:
/plugin marketplace add ./my-marketplace
目录中需要存在:
my-marketplace/
└── .claude-plugin/
└── marketplace.json
也可以直接指向某一个 marketplace.json:
/plugin marketplace add ./config/marketplace.json
这种方式适合:
Marketplace 本地开发
Plugin 联调
企业内部原型
CI 测试
Claude Code 对本地相对路径的解析还有一个细节:路径会相对于 Git 仓库的主 Checkout 解析,而不是当前 Worktree。多个 Worktree 因此会共享同一个 Marketplace 位置。
5. 远程 marketplace.json
Claude Code 还支持直接添加一个远程 JSON:
/plugin marketplace add https://example.com/marketplace.json
这种模式不要求 Marketplace 本身是 Git 仓库。
它适合:
静态文件托管
对象存储
企业内部配置服务
CDN 分发
但是这种方式缺少完整 Git 仓库所提供的相对目录、历史记录和原生更新能力。
如果 Marketplace 中的 Plugin Source 使用相对路径,远程单文件模式就容易出现路径无法解析的问题。官方文档也明确提示,URL Marketplace 相比 Git Marketplace 存在额外限制。
6. settings.json 中声明 Marketplace
团队可以通过配置文件预声明 Marketplace:
{
"extraKnownMarketplaces": {
"team-tools": {
"source": {
"source": "github",
"repo": "company/claude-plugins"
}
}
}
}
这意味着:
团队成员进入项目
↓
Claude Code 读取 .claude/settings.json
↓
发现项目声明的 Marketplace
↓
提示用户安装或信任
extraKnownMarketplaces 支持:
github
git
directory
settings
其中 settings 类型甚至允许直接在 settings.json 中内联一小组 Plugin Entry,而不必单独建立 Marketplace 仓库。
不过,声明 Marketplace 并不会自动启用所有 Plugin。
仍需要:
{
"enabledPlugins": {
"formatter@team-tools": true
}
}
官方文档明确指出,extraKnownMarketplaces 和 enabledPlugins 是两个独立层次。
三、Marketplace 注册信息保存在哪里
无论 Marketplace 最初来自用户命令、项目配置还是托管配置,Claude Code 都需要维护一份运行时 Marketplace Registry。
官方公开的核心文件是:
~/.claude/plugins/known_marketplaces.json
官方文档明确说明:
Marketplace 状态按用户保存一次,而不是每个项目保存一份。
这意味着,即便 Marketplace 是通过项目级配置声明的,它的实际拉取状态和本地安装位置仍由用户目录中的 Marketplace Registry 统一管理。
可以将其理解为:
项目配置
.claude/settings.json
↓ 声明期望状态
用户 Marketplace Registry
~/.claude/plugins/known_marketplaces.json
↓ 记录本机实际状态
1. Registry 的作用
known_marketplaces.json 至少需要承担以下职责:
Marketplace 名称
Marketplace 来源类型
原始 Source
本地安装位置
是否固定 Ref
是否自动更新
最后获取状态
官方提供的命令:
claude plugin marketplace list --json
输出中会包含:
name
source
installLocation
repo / url / path
ref
其中 installLocation 就是当前 Marketplace 在本地的缓存路径。
因此,查看真实 Marketplace 注册和落盘位置时,优先使用:
claude plugin marketplace list --json
而不是直接猜测内部目录。
2. 配置作用域与 Registry 的关系
添加 Marketplace 时可以指定:
claude plugin marketplace add <source> --scope user
claude plugin marketplace add <source> --scope project
claude plugin marketplace add <source> --scope local
三个 Scope 分别表示:
user
→ Marketplace 声明写入用户设置
project
→ Marketplace 声明写入 .claude/settings.json
local
→ Marketplace 声明写入 .claude/settings.local.json
但 Marketplace 的共享运行状态和缓存并不会因此分别复制三份。
官方明确说明:
Marketplace State
→ 每个用户一份
Marketplace Declaration
→ 可以来自多个 Settings Scope
所以可以建立下面的模型:
~/.claude/settings.json
.claude/settings.json
.claude/settings.local.json
managed-settings.json
↓
合并 Marketplace 声明
↓
~/.claude/plugins/known_marketplaces.json
↓
统一 Marketplace 本地缓存
四、Marketplace 仓库如何缓存
Marketplace 被添加后,Claude Code 会把 Marketplace 内容放入:
~/.claude/plugins/marketplaces/
官方容器 Seed 目录直接公开了 Marketplace 的标准目录形态:
$CLAUDE_CODE_PLUGIN_SEED_DIR/
├── known_marketplaces.json
├── marketplaces/
│ └── <marketplace-name>/
└── cache/
└── <marketplace>/
└── <plugin>/
└── <version>/
Seed 目录完整镜像了默认的:
~/.claude/plugins/
目录结构,因此可以推导出 Marketplace 本地缓存结构:
~/.claude/plugins/
├── known_marketplaces.json
├── marketplaces/
│ ├── claude-plugins-official/
│ ├── company-tools/
│ └── local-dev-marketplace/
└── cache/
这一结构由 Anthropic 官方文档直接公开,而不是纯粹根据本地文件猜测。
1. Git Marketplace
对于 GitHub 或普通 Git Source,Marketplace 缓存本质上是本地 Checkout:
~/.claude/plugins/marketplaces/company-tools/
├── .git/
├── .claude-plugin/
│ └── marketplace.json
├── plugins/
└── README.md
更新 Marketplace 时:
/plugin marketplace update company-tools
Claude Code 会尝试从原始 Git Source 获取最新内容。
如果 Marketplace 固定到了 Branch 或 Tag:
acme-corp/plugins@v2.0
更新操作会获取该 Ref 的最新 Commit,而不是切换到默认分支。
2. Sparse Checkout
对于大型 Monorepo,可以使用:
claude plugin marketplace add acme-corp/monorepo \
--sparse .claude-plugin plugins
Claude Code 会通过 Git Sparse Checkout,只获取 Marketplace Catalog 和 Plugin 所需目录。
这说明 Marketplace 缓存并不要求一定完整克隆整个仓库。
3. 本地 Marketplace
本地 Marketplace 与远程 Git Marketplace 的语义不同。
从开发体验看,本地 Source 更像:
Marketplace Registry
→ 指向本地开发目录
但当其中的 Plugin 被正式安装时,Plugin 仍然会被复制到版本化 Plugin Cache,而不是直接长期原地运行。官方明确指出,Marketplace Plugin 为了安全和可验证性会复制到本地缓存。
所以:
本地 Marketplace
→ Catalog 可以来自本地开发目录
安装后的 Plugin
→ 仍运行于 ~/.claude/plugins/cache
这也是为什么修改本地 Plugin 后,通常需要重新安装或更新,不能默认认为 Claude Code 会直接热读原目录。
开发时需要直接原地加载,可以使用:
claude --plugin-dir ./my-plugin
但这属于临时 Sideload,不属于 Marketplace 安装路径。
五、Plugin 安装后保存在哪里
Plugin 的正式安装目录位于:
~/.claude/plugins/cache/
官方给出的标准层次是:
~/.claude/plugins/cache/
└── <marketplace-name>/
└── <plugin-name>/
└── <version>/
├── .claude-plugin/
├── skills/
├── commands/
├── agents/
├── hooks/
├── .mcp.json
└── ...
例如:
~/.claude/plugins/cache/
└── claude-code-plugins/
└── commit-commands/
└── 1.2.0/
├── .claude-plugin/
│ └── plugin.json
├── skills/
└── commands/
官方文档明确说明:
Plugin Source 获取完成
↓
复制到本地版本化 Plugin Cache
↓
每个安装版本使用独立目录
1. 为什么不能直接从 Marketplace 目录执行
Claude Code 选择复制到 Cache,而不是直接执行 Marketplace 原始目录,主要有几个原因。
原因一:版本隔离
Plugin 1.0.0
Plugin 1.1.0
不同版本拥有不同物理目录,更新时不会直接覆盖正在使用的版本。
原因二:运行稳定性
一个正在运行的 Claude Code Session 可能已经加载旧版本。
如果更新操作直接覆盖旧文件,会导致:
Skill 已读取一半
脚本突然被替换
MCP 启动文件发生变化
Subagent 定义前后不一致
版本化缓存可以避免这种问题。
原因三:文件边界
安装后的 Plugin 不能任意依赖 Plugin 目录之外的文件。
官方明确说明:
Plugin 被复制到 Cache 后,引用 Plugin 外部相对文件的路径将失效。
因此,Plugin 中的所有运行依赖都应该:
包含在 Plugin 自身目录
或者使用专门的持久化数据目录。
2. ${CLAUDE_PLUGIN_ROOT}
因为 Plugin 安装目录是动态 Cache 路径,Plugin 作者不能硬编码:
~/.claude/plugins/cache/market/plugin/1.0/scripts/run.sh
Claude Code 提供:
${CLAUDE_PLUGIN_ROOT}
例如:
{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh"
}
]
}
]
}
}
${CLAUDE_PLUGIN_ROOT} 会在运行时指向当前实际安装版本目录。
3. ${CLAUDE_PLUGIN_DATA}
Plugin 代码会随升级替换,但某些数据需要长期保留,例如:
索引文件
用户配置
缓存数据
登录状态
运行历史
本地数据库
这些内容不应该写进 ${CLAUDE_PLUGIN_ROOT}。
因为:
Plugin Root
→ 属于版本化代码
→ 更新后可能被替换或清理
Plugin Data
→ 属于持久化状态
→ 应跨版本保留
Claude Code 因此提供 ${CLAUDE_PLUGIN_DATA},用于保存应当在 Plugin 更新后继续存在的数据。官方也明确建议依赖或状态使用该目录,而不是写进 Plugin 安装目录。
六、Plugin 安装状态如何记录
除了 Cache,Claude Code 还需要记录:
安装了什么 Plugin
来自哪个 Marketplace
当前解析到哪个版本
Cache Path 是什么
是否处于启用状态
Claude Code 的更新日志公开提到内部状态文件:
installed_plugins.json
并曾修复该文件中残留条目指向已删除 Cache 目录的问题。
这说明本地至少存在两类 Plugin 状态:
安装状态 Registry
→ installed_plugins.json
启用状态
→ settings.json 中的 enabledPlugins
不过需要注意:
installed_plugins.json属于 Claude Code 内部状态文件,官方当前没有将其完整 Schema 作为稳定公共接口发布。
因此可以观察它,但不建议:
手动编辑
由第三方程序长期依赖字段
将其当作正式插件管理 API
更稳定的查询方式是:
claude plugin list --json
claude plugin details plugin-name@marketplace
官方命令能够返回 Plugin 版本、来源 Marketplace 和启用状态。
七、安装作用域究竟写入哪里
Claude Code Plugin 有四种主要作用域:
| Scope | 配置文件 | 作用 |
|---|---|---|
user |
~/.claude/settings.json |
当前用户所有项目 |
project |
.claude/settings.json |
项目团队共享 |
local |
.claude/settings.local.json |
当前用户、当前项目 |
managed |
Managed Settings | 企业管理员统一下发 |
官方 Plugins Reference 明确给出了这组对应关系。
1. User Scope
默认安装:
claude plugin install formatter@team-tools
等价于:
claude plugin install formatter@team-tools --scope user
会在:
~/.claude/settings.json
中加入类似:
{
"enabledPlugins": {
"formatter@team-tools": true
}
}
这个 Plugin 对当前用户所有项目生效。
2. Project Scope
claude plugin install formatter@team-tools --scope project
会将启用声明写入:
project/.claude/settings.json
示意:
{
"enabledPlugins": {
"formatter@team-tools": true
}
}
由于 .claude/settings.json 通常进入 Git,团队其他成员拉取项目后也能看到项目期望启用该 Plugin。
但这里有一个重要区别:
项目配置声明 Plugin 应启用
≠
Plugin 文件已经提交进 Git
其他开发者仍需要在自己机器上安装 Plugin Cache。
官方文档说明,项目只声明了外部 Plugin 时,如果成员本地尚未安装,Claude Code 会报告 Plugin 未安装并提示安装命令。
因此 Project Scope 的真实模型是:
Git 中共享:
enabledPlugins 声明
每个用户本地:
Marketplace Cache
Plugin Cache
实际安装状态
3. Local Scope
claude plugin install formatter@team-tools --scope local
会写入:
project/.claude/settings.local.json
该文件一般被 Git 忽略,因此:
只对当前开发者有效
只在当前项目生效
不会影响团队其他成员
适合:
Plugin 测试
个人工具
尚未通过团队评审的能力
需要本地 Secret 的集成
4. Managed Scope
企业管理员可以通过 Managed Settings 声明 Marketplace 和 Plugin。
例如:
{
"extraKnownMarketplaces": {
"company-tools": {
"source": {
"source": "github",
"repo": "company/approved-plugins"
}
}
},
"enabledPlugins": {
"security-review@company-tools": true
}
}
Managed Scope 是只读的,普通用户无法卸载或修改。
八、作用域并不会产生多份 Plugin 文件
需要特别强调:
User、Project、Local Scope 主要控制的是配置声明,不是把同一个 Plugin 分别复制到三个项目目录。
Plugin 实体仍然统一存在:
~/.claude/plugins/cache/
不同 Scope 决定的是:
哪个 Settings 文件声明该 Plugin 启用
可以理解为:
统一 Plugin Cache
↓
多个 Scope 引用同一个 Plugin 版本
↓
Harness 合并 enabledPlugins
因此:
Project Scope
≠
project/.claude/plugins/
Claude Code 默认不会把完整 Plugin 安装进项目仓库。
九、Plugin 更新如何实现
Plugin 更新分为两层:
Marketplace Update
Plugin Update
二者不能混为一谈。
1. Marketplace Update
/plugin marketplace update company-tools
或者:
claude plugin marketplace update company-tools
这一步主要更新:
marketplace.json
Plugin Source
Plugin Version Metadata
Renames
新增或移除的 Plugin
它相当于更新“软件源索引”。
如果省略 Marketplace 名称:
claude plugin marketplace update
则更新所有可变 Marketplace。
2. Plugin Update
claude plugin update formatter@company-tools
这一步才会:
解析最新 Plugin Version
↓
下载新的 Plugin Source
↓
复制到新的版本化 Cache 目录
↓
更新安装状态 Registry
官方的版本解析优先级是:
1. plugin.json 中的 version
2. marketplace.json Plugin Entry 中的 version
3. Plugin Source 的 Git Commit SHA
这说明即使 Plugin 没有显式版本号,Claude Code 也可以使用 Commit SHA 作为版本标识和 Cache 目录依据。
3. 相同版本不会重复更新
如果 Marketplace 更新后解析出的 Version 与当前已安装 Version 相同:
/plugin update
自动更新
都会跳过该 Plugin。
因此,如果 Plugin 内容发生了变化,但:
plugin.json version 没有修改
Claude Code 可能不会认为它是一个新版本。
这对 Plugin 发布者非常重要:
只修改代码、不升级
version,可能导致用户收不到更新。
4. 自动更新
Claude Code 可以在启动后后台检查 Marketplace 和 Plugin 更新。
流程大致是:
Claude Code 启动
↓
使用当前已安装版本构建 Session
↓
随机延迟最多约 10 分钟
↓
后台更新 Marketplace
↓
解析 Plugin 新版本
↓
下载到新 Cache 目录
↓
通知用户 /reload-plugins
当前正在运行的 Session 不会突然切换到新版本,而是继续使用启动时加载的版本。
默认策略是:
Anthropic 官方 Marketplace
→ 默认开启自动更新
第三方 Marketplace
→ 默认关闭自动更新
本地开发 Marketplace
→ 默认关闭自动更新
十、为什么更新后旧版本不会立即删除
Claude Code 的版本化 Cache 不会在更新完成后立即删除旧版本。
官方 Plugins Reference 说明:
旧版本目录
↓
标记为 Orphaned
↓
保留 7 天
↓
自动清理
这个七天宽限期主要解决并发 Session 问题。
例如:
Session A
→ 已加载 Plugin 1.0
用户执行更新
→ 安装 Plugin 1.1
Session B
→ 加载 Plugin 1.1
Session A
→ 仍然需要读取 1.0 的脚本和资源
如果 1.0 立即被删除,Session A 就可能在运行中报错。
因此 Claude Code 采用:
Copy-on-update
+
Delayed garbage collection
而不是直接覆盖安装目录。
十一、Plugin 如何禁用
禁用 Plugin:
/plugin disable plugin-name@marketplace-name
或者:
claude plugin disable plugin-name@marketplace-name \
--scope local
禁用的核心行为是:
保留 Plugin Cache
保留 Plugin 安装记录
修改 enabledPlugins 或添加覆盖声明
停止 Harness 加载其能力
也就是说:
disable
≠
uninstall
禁用后可以重新启用:
/plugin enable plugin-name@marketplace-name
项目 Plugin 的本地禁用
假设项目共享配置中写了:
{
"enabledPlugins": {
"formatter@company-tools": true
}
}
某个开发者不想使用它,可以选择:
只为自己禁用
Claude Code 会在:
.claude/settings.local.json
中写入本地覆盖,而不是修改项目共享的 .claude/settings.json。
较新版本在卸载项目 Plugin 时会询问:
只对我禁用
还是为所有协作者卸载
选择“只对我禁用”会写本地覆盖;选择“为所有人卸载”才会修改共享配置。
这是一种典型的配置分层设计:
Project Settings
→ 团队期望状态
Local Settings
→ 当前用户覆盖状态
十二、Plugin 如何卸载
卸载命令:
/plugin uninstall plugin-name@marketplace-name
或者:
claude plugin uninstall formatter@company-tools \
--scope project
卸载主要会做三件事:
1. 从指定 Scope 的 enabledPlugins 中移除
2. 更新 Plugin 安装状态
3. 当没有任何 Scope 继续引用时,安排清理 Cache
官方 CLI 还支持:
claude plugin uninstall plugin@marketplace --keep-data
用于保留 ${CLAUDE_PLUGIN_DATA}。
默认情况下,当最后一个安装 Scope 被移除时,Plugin 的持久化数据目录也可能被删除。
因此:
卸载 Plugin 代码
和
删除 Plugin 业务数据
是两个可以分开控制的动作。
1. 依赖清理
如果 Plugin 自动安装了依赖,卸载主 Plugin 后,依赖不一定立即删除。
可以执行:
claude plugin prune
或者:
claude plugin uninstall plugin@marketplace --prune
清理不再被其他 Plugin 依赖的自动安装项。
2. 移除 Marketplace 会发生什么
/plugin marketplace remove company-tools
如果这是该 Marketplace 在所有可编辑 Scope 中的最后一条声明,Claude Code 会同时卸载从该 Marketplace 安装的 Plugin。
但如果同一个 Marketplace 仍然被另一个 Scope 声明:
用户 Scope 已添加
项目 Scope 也已添加
只移除其中一个 Scope 时,共享 Marketplace 状态、Cache 和 Plugin 安装信息会继续保留。
因此:
Marketplace remove
→ 先移除当前声明
只有最后一个声明消失
→ 才真正清理 Marketplace 和相关 Plugin
十三、Claude Code 是否支持回滚
这是一个容易产生误解的问题。
从存储结构看,Claude Code 会:
保留旧 Plugin 版本目录 7 天
因此本地文件系统中可能同时存在:
plugin/
├── 1.0.0/
└── 1.1.0/
但这并不等同于 Claude Code 已经提供了完整的:
/plugin rollback plugin@marketplace 1.0.0
当前公开 CLI Reference 提供的是:
install
update
enable
disable
uninstall
没有公开一个正式的通用 Rollback 命令。
所以更准确的结论是:
Claude Code 的缓存机制具备“保留旧版本以支持运行中 Session”的能力,但公开插件管理接口目前不等同于完整版本回滚系统。
可以怎样实现受控降级
如果确实需要回退,比较稳妥的方法是:
方法一:固定 Marketplace Ref
claude plugin marketplace add \
company/plugins@v1.0 \
--scope project
然后重新安装或更新 Plugin。
方法二:修改 Plugin Version
让 Marketplace 指向旧版 Plugin Source,并使用明确的旧版本号或 Commit SHA。
方法三:建立 Release Channel
company-tools-stable
company-tools-beta
分别维护稳定和测试版本。
方法四:保留旧 Marketplace Tag
v1.0
v1.1
v2.0
通过切换 Ref 实现可审计的降级。
不建议直接手工修改:
installed_plugins.json
或者把 Cache 指针强行改到旧目录,因为这属于内部实现,可能造成状态不一致。
十四、/reload-plugins 在整个流程中的位置
安装、启用、禁用或更新 Plugin 后,当前 Session 不一定立即自动重建全部能力。
可以执行:
/reload-plugins
Claude Code 会重新扫描所有激活的 Plugin,并显示重新加载的:
Plugin 数量
Skill 数量
Agent 数量
Hook 数量
MCP Server 数量
LSP Server 数量
完整链路是:
磁盘状态发生变化
↓
Plugin Cache 更新
↓
enabledPlugins 更新
↓
/reload-plugins
↓
重新构建 Runtime Capability Registry
需要注意,重新加载 Plugin 可能导致下一次模型请求增加上下文 Token,尤其是 Plugin 新增了 MCP Tool 时,还可能使 Prompt Cache 失效。
因此 /reload-plugins 不只是文件刷新,而是一次运行时能力重建。
十五、容器和 CI 环境中的预置落盘
Claude Code 还支持为容器、CI 和离线环境预置 Marketplace 和 Plugin。
使用:
CLAUDE_CODE_PLUGIN_SEED_DIR
Seed 目录结构必须镜像:
~/.claude/plugins/
例如:
/opt/claude-seed/
├── known_marketplaces.json
├── marketplaces/
│ └── company-tools/
└── cache/
└── company-tools/
└── security-review/
└── 1.0.0/
运行时:
export CLAUDE_CODE_PLUGIN_SEED_DIR=/opt/claude-seed
Claude Code 会:
读取 Seed 中的 Marketplace
使用 Seed 中已有 Plugin Cache
不重新 Clone
不修改 Seed
Seed Marketplace 是只读的:
/plugin marketplace update
/plugin marketplace remove
对它们不会生效。
而且 Seed 中的同名 Marketplace 会优先于用户本地配置。
这个机制非常适合:
企业统一开发镜像
Air-gapped 环境
固定供应链版本
CI Runner
Dev Container
十六、完整的本地目录模型
综合公开文档,可以将 Claude Code Marketplace 与 Plugin 的本地结构还原为:
~/.claude/
├── settings.json
│ └── 用户级 extraKnownMarketplaces / enabledPlugins
│
├── plugins/
│ ├── known_marketplaces.json
│ │ └── Marketplace 注册与本地位置
│ │
│ ├── installed_plugins.json
│ │ └── 内部 Plugin 安装状态
│ │
│ ├── marketplaces/
│ │ ├── claude-plugins-official/
│ │ │ ├── .claude-plugin/
│ │ │ │ └── marketplace.json
│ │ │ └── ...
│ │ │
│ │ └── company-tools/
│ │ ├── .git/
│ │ ├── .claude-plugin/
│ │ │ └── marketplace.json
│ │ └── plugins/
│ │
│ └── cache/
│ ├── claude-plugins-official/
│ │ └── github/
│ │ └── <version>/
│ │
│ └── company-tools/
│ └── formatter/
│ ├── 1.0.0/
│ └── 1.1.0/
│
└── ...
project/
├── .claude/
│ ├── settings.json
│ │ └── 项目级 Marketplace 和 Plugin 声明
│ │
│ └── settings.local.json
│ └── 当前用户在本项目中的覆盖
│
└── ...
需要再次强调:
known_marketplaces.json
installed_plugins.json
cache/
marketplaces/
属于 Claude Code 的运行状态和内部存储层。
而:
settings.json
settings.local.json
managed-settings.json
属于用户和管理员可以依赖的公开配置层。
十七、整个发现、安装与落盘流程
现在可以把完整过程串起来。
第一步:添加 Marketplace
/plugin marketplace add company/plugins
Claude Code:
解析 Source
↓
检查 strictKnownMarketplaces
↓
Clone 或读取 Marketplace
↓
查找 marketplace.json
↓
校验 Marketplace
↓
写入 Settings Scope
↓
写入 known_marketplaces.json
↓
缓存到 marketplaces/<name>/
第二步:浏览 Plugin
/plugin
↓
Discover
Claude Code:
遍历已注册 Marketplace
↓
读取 marketplace.json
↓
合并 Plugin Catalog
↓
展示 Plugin 信息和组件清单
安装前,当前版本的 UI 会展示 Plugin 将要增加的 Skill、Agent、Hook、MCP 和 LSP 等组件。
第三步:安装 Plugin
/plugin install formatter@company-tools
Claude Code:
定位 Marketplace Entry
↓
解析 Plugin Source
↓
解析版本
↓
下载或复制 Plugin
↓
校验 plugin.json 和组件
↓
复制到 cache/<marketplace>/<plugin>/<version>/
↓
更新 Plugin 安装 Registry
↓
写入对应 Scope 的 enabledPlugins
第四步:加载 Plugin
/reload-plugins
Claude Code:
读取 enabledPlugins
↓
找到版本化 Cache
↓
扫描 Plugin Components
↓
注册 Skill / Command / Agent
↓
加载 Hook / MCP / LSP
↓
重建当前 Session 的能力集合
第五步:更新 Plugin
/plugin marketplace update
/plugin update formatter@company-tools
Claude Code:
更新 Catalog
↓
解析新版本
↓
复制到新的版本目录
↓
更新 Registry
↓
保留旧版本 7 天
↓
提示 reload
第六步:禁用或卸载
/plugin disable
→ 保留文件,只停止加载
/plugin uninstall
→ 移除 Scope 引用,安排清理
/plugin marketplace remove
→ 移除 Marketplace;最后一个 Scope 消失时卸载其 Plugin
十八、从落盘结构看 Claude Code 的设计思想
通过这套结构,可以看出 Claude Code Plugin 系统的几个重要设计。
1. 声明与实体分离
Settings
→ 声明应该启用什么
Cache
→ 保存实际 Plugin 文件
项目仓库只需要提交声明,不需要提交第三方 Plugin 实体。
2. Marketplace 与 Plugin 分离缓存
marketplaces/
→ 保存 Catalog 和 Source Checkout
cache/
→ 保存真正执行的 Plugin 副本
Marketplace 仓库不是 Plugin 的最终运行目录。
3. 版本化、不可变式安装
Plugin 1.0
Plugin 1.1
不会直接互相覆盖,而是保存到不同目录。
这更接近:
Maven 本地仓库
npm 内容寻址缓存
Nix Store
而不是传统的:
把新文件覆盖进 plugins/current/
4. 延迟垃圾回收
旧版本保留七天,保证已有 Session 可以继续运行。
这是一种典型的:
Runtime Safety
+
Eventual Cleanup
设计。
5. 多作用域共享单一物理缓存
User、Project 和 Local Scope 不重复保存 Plugin 实体。
它们只是提供不同层级的启用声明。
6. 回滚能力弱于版本存储能力
Claude Code 具备版本化 Cache,却没有公开完整的通用 Rollback 命令。
因此:
底层可以保留多个版本
上层管理能力仍偏向 latest/update
企业需要稳定发布时,应借助 Git Tag、SHA 和独立 Release Channel,而不是依赖手工 Cache 回退。
十九、当前仍值得继续验证的问题
经过这一篇,我们已经可以确认主要目录和流程,但仍有一些内部细节值得通过本地实验继续观察。
1. known_marketplaces.json 的完整字段
包括:
不同 Source 类型如何序列化
installLocation 是否直接保存
autoUpdate 状态放在哪里
Scope 声明如何关联
最后更新时间是否记录
2. installed_plugins.json 的实际 Schema
重点确认:
Plugin Key
Version
Cache Path
Marketplace
Install Scope
Installed At
Last Used
Orphaned 标记
3. Disable 的真实配置写法
例如:
enabledPlugins 中写 false
还是单独维护 disabledPlugins
Local Scope 如何覆盖 Project Scope
4. 多 Scope 不同版本
例如:
User Scope 使用 Plugin 1.0
Project Scope 要求 Plugin 1.1
Claude Code 是否允许同时存在,最终选择哪个版本?
5. Plugin Data 的真实目录
${CLAUDE_PLUGIN_DATA} 的具体路径和多 Scope 行为需要进一步确认。
6. Cache 垃圾回收触发时机
启动时扫描
定时清理
安装或更新时顺带清理
官方只公开了七天宽限期,没有完整公开垃圾回收实现细节。
总结
Claude Code 的 Marketplace 与 Plugin 安装并不是一个简单的“下载到 plugins 目录”。
它实际上分成了四个相互独立的存储层:
第一层:Settings Declaration
~/.claude/settings.json
.claude/settings.json
.claude/settings.local.json
作用:
声明 Marketplace 和 Plugin 的期望状态
第二层:Marketplace Registry
~/.claude/plugins/known_marketplaces.json
作用:
记录本机认识哪些 Marketplace
第三层:Marketplace Cache
~/.claude/plugins/marketplaces/<name>/
作用:
保存 Marketplace Catalog 和 Git Checkout
第四层:Versioned Plugin Cache
~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/
作用:
保存 Harness 实际加载和执行的 Plugin
完整链路是:
Marketplace Source
↓
Settings 声明
↓
known_marketplaces.json
↓
marketplaces/<name>/
↓
marketplace.json
↓
Plugin Source
↓
cache/<marketplace>/<plugin>/<version>/
↓
enabledPlugins
↓
Claude Code Harness
其中:
User / Project / Local
→ 控制配置作用域
Marketplace Cache
→ 控制 Catalog 来源
Plugin Cache
→ 控制实际运行文件
/reload-plugins
→ 控制当前 Session 是否重新加载
从设计上看,Claude Code 采用的是:
声明式配置
+
中心化用户缓存
+
Plugin 版本隔离
+
延迟清理
+
多作用域覆盖
而不是把 Plugin 直接复制到每个项目目录。
下一篇可以继续进入:
Harness Marketplace 剖析系列 - 之 Claude Code:一个真实 Plugin 与 Skill 的完整拆解
重点选择一个官方 Plugin,逐个分析:
marketplace.json 中的 Plugin Entry
Plugin 本地目录
plugin.json
skills/SKILL.md
commands/
agents/
hooks/
MCP / LSP
组件之间如何相互引用
Harness 最终暴露出哪些能力
这样就能从“Plugin 如何落盘”继续进入“落盘后的 Plugin 究竟如何组织和运行”。
更多推荐


所有评论(0)