上一篇我们从静态目录和配置文件入手,梳理了 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
  }
}

官方文档明确指出,extraKnownMarketplacesenabledPlugins 是两个独立层次。


三、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 究竟如何组织和运行”。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐