跳到正文
FunCoding

搜索

搜索文档、智能体、博客、Skill 和 MCP

插件加载参考

追踪 Claude Code 从哪里加载每个插件、哪个设置文件决定是否加载、为什么更新没变化:加载阶段、插件来源、启用优先级、磁盘位置、版本与自动更新、命名冲突。

当插件没加载、加载了你没想到的副本、或没拿到更新,而你想看清是哪个来源、设置范围或磁盘文件做出了这个决定时,用本页。它给出 Claude Code 在会话启动时以及每次运行 /reload-plugins 时应用的规则。安装、启用、禁用和更新的步骤见「安装和管理插件」;有具体错误消息见「插件排障」。

检查插件到了哪个阶段

一个 enabledPlugins 条目要经过几个阶段才成为你能用的插件:设置声明它,Claude Code 把它取到磁盘,运行中的会话加载它。插件的行为与设置文件所暗示的不符时,先看它到了哪个阶段:

  • 已声明(在设置里):enabledPlugins 说哪些插件该开,extraKnownMarketplaces 说哪些市场应当存在;运行 claude plugin marketplace add 时,Claude Code 既写到磁盘,也写入你用户设置里的 extraKnownMarketplaces
  • 已获取(在 ~/.claude/plugins/ 下的磁盘上):known_marketplaces.json 记录每个已获取的市场(source、installLocation、lastUpdated、autoUpdate),每个用户一份;installed_plugins.json 记录每次安装的 scope、installPath 和 version;cache/ 存放插件文件
  • 已加载(在运行的会话里):Claude Code 在启动时或上次 /reload-plugins 时加载的插件集合。对设置或磁盘的更改要等你运行 /reload-plugins 或开始新会话才会到达这一层

插件在会话启动时从 installed_plugins.json 和缓存加载,不使用网络;会话开始后 Claude Code 在后台检查已声明的市场:设置声明了但 known_marketplaces.json 没有的市场会被克隆,然后重新加载插件并下载还没缓存的已启用插件;来源在设置里改变了的已声明市场会从新来源重新获取,并显示 Plugins changed. Run /reload-plugins to activate.。两条路径都没取到、又没有可用缓存目录的已启用插件,会在 /plugin 的 Errors 标签页显示 Plugin "<name>" not cached at <path>。

插件从哪里来

每个插件有形如 <name>@<origin> 的 id,也就是你在设置文件和 claude plugin list --json 里看到的。@ 之后的部分告诉你 Claude Code 在哪里找到它:

id 结尾如何到达如何开关
@<marketplace>从你添加的市场安装设置文件里 enabledPlugins 下的 "<name>@<marketplace>": true 或 false
@inline用 --plugin-dir 或 --plugin-url 启动、设置了 CLAUDE_CODE_PLUGIN_DIRS、或 Agent SDK 应用传入 plugins 选项;只对该会话加载对该会话开启,除非清单设置了 defaultEnabled: false 或设置文件把它设为 false
@skills-dir你把带 .claude-plugin/plugin.json 的插件目录存放在 ~/.claude/skills/ 或项目的 .claude/skills/ 下清单的 defaultEnabled,除非设置文件把 "<name>@skills-dir" 设为 true 或 false
@synced你或你的组织为你的 claude.ai 账号打开了它,Claude Code 下载了它开启,除非清单设置了 defaultEnabled: false 或设置文件设了 "<name>@synced": false;组织标记为必需的插件除外

对市场插件,<name> 是 marketplace.json 里的条目名;对 @inline 和 @skills-dir 则是插件清单里的 name。这些来源名是保留的,任何市场都不能叫 inline、skills-dir 或 synced。

条目名与清单名:市场插件有两个可能不同的名字。marketplace.json 里的条目名是安装和启用的键,也是你写进 enabledPlugins、缓存目录的命名依据,以及 claude plugin list 显示的;清单里的 name 是插件组件的命名空间,也是命名冲突比较的对象。

通过仓库共享插件

要通过仓库共享插件,把它列在 .claude/settings.json 的 enabledPlugins 下,或放在 .claude/skills/ 下;Claude Code 不扫描项目的 .claude/plugins/ 目录。云端会话不会添加仓库在 extraKnownMarketplaces 里列出的市场,因为这需要云端会话从不显示的工作区信任对话框。项目范围的 skills 目录插件只从会话主工作目录的 .claude/skills/ 加载,且只在你接受该文件夹的工作区信任对话框之后;它不会向上搜索到仓库根。因为项目范围插件的内容来自仓库而不是你,它只在通过与 .claude/settings.json 里的项目 allow 规则相同的信任检查后加载:它声明的 MCP 服务器要经过与项目 .mcp.json 相同的逐服务器批准;作为 MCP bundle(.mcpb 或 .dxt 文件)声明的、或来自插件目录之外文件的 MCP 服务器被跳过(要内联声明,或放在插件目录内的 .mcp.json 里);后台监视器不加载。个人范围的插件没有这些限制。

从 claude.ai 同步的插件

你为 claude.ai 账号打开的插件也会在 Claude Code 里与你从市场安装的插件一起加载,包括你的组织为成员打开的插件。每个这样的插件以 <name>@synced 加载。在终端会话里,同步插件的 skills、agents、hooks、MCP 服务器和 LSP 服务器都会加载,信任度与你安装的市场插件相同。同步插件在 Cowork 会话和你用 claude.ai 账号登录的终端会话里加载:Cowork 在会话启动时把它们下载到会话自己的环境;终端会话每次启动 Claude Code 时在后台同步一次,下载新增和更新的插件并移除你或组织关闭的(需要 Claude Code v2.1.273 或更高版本)。后台同步可能在会话启动之后才完成,交互会话里它添加、更新或移除同步插件时你会看到 Plugins changed. Run /reload-plugins to activate.;会话运行时在 claude.ai 上启用的插件在下次启动 Claude Code 时下载。

在终端里,只有你用 claude.ai 账号登录的会话才同步插件。即使你用 /login 登录,在这些会话里 Claude Code 既不下载也不加载同步插件:凭据来自 ANTHROPIC_AUTH_TOKEN、CLAUDE_CODE_OAUTH_TOKEN 或 apiKeyHelper 脚本的会话;不从 Anthropic 获取功能开关的会话(如设置了 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC);bare 模式或用 --safe-mode 启动的会话;用不含 user 的 --setting-sources 列表启动的会话。

控制哪些同步插件加载:可以逐个关闭(组织要求的除外)——shell 里 claude plugin disable <name>@synced 或会话里 /plugin 的 Installed 标签页,都会在你用户级 enabledPlugins 里保存 "<name>@synced": false;也可以关闭机器上所有同步插件——在用户设置里把 syncClaudeAiPlugins 设为 false,或由组织在托管设置里设置,Claude Code 停止下载,并在下次启动时把已同步的插件移走;组织在 claude.ai 上标记为必需的插件即使你之前禁用了也会加载,claude plugin disable 会拒绝它。

插件在哪里被启用

enabledPlugins 条目可以在六个来源中设置。下表从最低优先级到最高:

来源设置位置触及
--add-dir你用 --add-dir 传入的目录里的 .claude/settings.json 或 .claude/settings.local.json仅本会话;只有 true 值有效,且被其他每个来源覆盖
user~/.claude/settings.json你,在每个项目里
project.claude/settings.json所有克隆该仓库的人
local.claude/settings.local.json你,仅在这个仓库里
flag启动时传入的 --settings 值仅本会话
managed托管设置策略覆盖的每个用户;true 强制启用、false 阻止,其他来源都不能覆盖

这些来源逐键合并:对每个插件 id,生效的值来自提到该 id 的最高优先级来源;没提到该 id 的来源保留较低优先级来源的值。

在用户设置里禁用却仍然加载:你在 ~/.claude/settings.json 里设为 false 却仍加载,说明更高优先级来源里的 true 在覆盖它;claude plugin list 和 /plugin 里该插件的行会显示 Disabled in ~/.claude/settings.json but still loads。要在你的机器上退出项目启用的插件,在优先级高于项目文件的 .claude/settings.local.json 里把该 id 设为 false。

在项目设置里启用但未安装:插件唯一的 true 在项目的 .claude/settings.json 里时,Claude Code 不会把它取到未安装它的机器上(除非它的市场条目是相对路径来源,或种子目录已有它)。具有外部来源的插件只有在这些来源之一把它设为 true 时才会被获取:你的用户设置、git 不跟踪的 .claude/settings.local.json、--settings 标志、托管设置。

在磁盘上找插件

Claude Code 把插件文件和状态记录放在一个插件根目录下,除非设置 CLAUDE_CODE_PLUGIN_CACHE_DIR,否则是 ~/.claude/plugins:

路径内容
cache/<marketplace>/<plugin>/<version>/市场插件每个已安装版本一个目录;${CLAUDE_PLUGIN_ROOT} 指向这个目录
data/<plugin-id>/插件的持久目录,暴露为 ${CLAUDE_PLUGIN_DATA};在插件组件首次使用时创建并跨更新保留
marketplaces/<name>/从 GitHub、其他 Git 主机或 URL 添加的市场的克隆或下载
synced/从你的 claude.ai 账号同步的插件
.trash/claude.ai 同步移除的插件(如你在 claude.ai 上关闭了它或停止同步)
installed_plugins.json 和 known_marketplaces.jsonClaude Code 已安装什么、已获取哪些市场的记录
flagged-plugins.json因其市场下架而被 Claude Code 卸载的插件,显示在 /plugin 的 Flagged 部分

因为 ${CLAUDE_PLUGIN_ROOT} 指向版本目录,插件的根路径随每个版本变化,所以把插件的持久文件放在 ${CLAUDE_PLUGIN_DATA} 里。

原地加载与复制:--plugin-dir 和 skills 目录插件原地加载,从不复制(--plugin-url 压缩包或 --plugin-dir 的 .zip 先解压到会话临时目录);从本地目录添加的市场里的相对路径插件原地加载,你对源目录的编辑在下次会话启动或 /reload-plugins 时生效;command 来源插件的链接模式会通过缓存条目里的链接原地加载命令打印的目录;其余市场插件在安装时被复制到 cache/<marketplace>/<plugin>/<version>/ 并加载那份副本,插件目录之外的文件不会被复制,所以复制插件里的脚本读取其上层的路径时会失败。

逃出插件目录的路径:无论原地加载还是从缓存副本加载,Claude Code 都不允许插件声明自身目录之外的组件,会拒绝解析到插件根之外的组件路径(无论在 plugin.json 还是市场条目里):按字面指向插件外的路径(如 ../shared-utils);通向插件外的符号链接(同一市场内插件之间的链接除外);在 macOS 和 Linux 上,任何含反斜杠的路径(即使仍在插件内;所以组件路径要用正斜杠,如 ./commands/deploy)。被拒绝的路径显示为 path escapes plugin directory 错误,插件在没有该组件的情况下加载。

旧版本清理:更新或卸载插件时,Claude Code 在前一个版本目录里写入 .orphaned_at 标记,14 天后在后台清理中移除该目录,这样已经加载旧版本的会话继续运行。清扫只在 installed_plugins.json 至少记录一次安装时运行。

Node.js 包依赖

Claude Code 把插件复制进缓存时,也会在那里安装插件的 Node.js 包依赖,使插件的 hooks 和 MCP 服务器能加载它们。它在每次创建复制的版本目录时运行:安装插件时、更新到新版本时、会话启动时已启用插件还没缓存时(如在新机器上)。对从本地目录市场原地加载的相对路径插件,Claude Code 不会往源目录里安装依赖,需要你自己安装,或从 hook 里装到 ${CLAUDE_PLUGIN_DATA}。安装只在插件根目录同时含 package.json 和受支持的 lockfile 时运行,lockfile 决定命令:bun.lock 或 bun.lockb 对应 bun install --frozen-lockfile --ignore-scripts;npm-shrinkwrap.json 或 package-lock.json 对应 npm ci --ignore-scripts。含多个时按 bun.lock、bun.lockb、npm-shrinkwrap.json、package-lock.json 的顺序取第一个。Yarn 和 pnpm 的 lockfile,以及 Bun lockfile 旁的 bunfig.toml,会让安装被跳过:只有 yarn.lock 或 pnpm-lock.yaml 时换成 npm lockfile;想覆盖最多用户就包含一个 npm lockfile;通过 npm 来源分发的插件用 npm-shrinkwrap.json,因为 npm 会把 package-lock.json 排除在发布的包之外。

对这个依赖安装的限制:冻结解析(只装 lockfile 固定的内容,package.json 与 lockfile 不一致时失败而不是重新解析);无生命周期脚本(--ignore-scripts,所以在这些脚本里构建原生模块的依赖只下载不编译);60 秒超时(超时视为失败)。自动安装无法关闭。失败或被跳过的安装从不阻止插件:失败,或因 Yarn/pnpm lockfile 或 bunfig.toml 而跳过,会在 claude --debug 输出里显示警告;有 package.json 而无 lockfile 的插件被静默跳过;超时的安装可能在缓存副本里留下不完整的 node_modules。自动安装无法提供某个依赖时,从 hook 里把它装进持久数据目录(包括需要生命周期脚本构建的包、Python 依赖和用 Yarn 或 pnpm 锁定的插件)。

版本与更新

插件作者推送了新提交,而 claude plugin update 打印 <name> is already at the latest version (<version>).,说明 Claude Code 为该插件计算的版本没变,所以磁盘上什么都不变。Claude Code 为它安装的每个插件计算版本,并据此检测更新;版本也是插件缓存目录的名字。从本地目录市场原地加载的插件在每次会话启动时加载它当前的源文件,不管版本字符串写什么。

版本如何计算:对你按来源添加的市场,Claude Code 按插件市场条目的 source 类型选规则。对除 command 之外的每种来源类型:先取插件清单里的 version 字段;再取插件市场条目里的 version 字段;都没设置时按来源类型:

来源类型没设置 version 时的版本
github、url 或 git-subdir来源的提交 SHA,缩短到 12 个字符(git-subdir 的版本还带子目录路径的哈希)
archiveSHA-256 摘要缩短到 12 个字符:市场条目里的 sha256 固定值,或没有固定值时下载文件的摘要
Git 托管市场里的相对路径已安装目录的提交 SHA
本地目录,且插件目录和它的市场都不是 git 仓库unknown
npmunknown

Claude Code 不从包围安装路径的仓库取版本(如被 git 管理的 ~/.claude)。command 来源的版本总是从命令产出的内容派生:单独一个 12 字符的哈希,或清单设置了版本时为 <清单版本>-<哈希>。因为清单优先,固定了 "version": "1.0.0" 的清单会让每个用户停留在缓存副本上,直到作者改了这个字符串,无论推了多少提交;想让用户跟踪提交,就在清单和市场条目里都不写 version。

安装前何时刷新市场:name@marketplace 的 /plugin install 或 claude plugin install 会在查找之前刷新指定的市场;单独的 name 用 /plugin install 时只刷新开启了自动更新的市场,且只在查找未命中之后;单独的 name 用 claude plugin install 时什么都不刷新,只读缓存的目录。刷新失败时安装从缓存的目录继续,claude plugin install 报告 marketplace not refreshed。以下情形跳过刷新:市场是从本地 file 或 directory 来源添加的,或在设置里用 settings 来源内联定义;种子目录提供该市场;Claude Code 在 30 秒内刚刷新过;设置了 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC;托管设置阻止该市场(此时也拒绝安装)。

自动更新何时运行:在交互会话里,你发出第一条消息后,Claude Code 等待最多十分钟的随机延迟,然后刷新每个开启了自动更新的市场并更新从它们安装到磁盘上的插件;运行中的会话保持已加载的版本,你会看到 Plugin updated: <name> · Run /reload-plugins to apply,无论是否重新加载,新版本都会在下次启动时加载。市场是否自动更新按第一个被设置的来源:设置文件里其 extraKnownMarketplaces 条目的 autoUpdate;其 known_marketplaces.json 条目的 autoUpdate(/plugin Marketplaces 下的 Enable auto-update 开关写的);默认值:Anthropic 官方市场(如 claude-plugins-official)开、knowledge-work-plugins 和 first-party-plugins 关、从 claude.ai 添加的市场开、其他所有市场关。设置 DISABLE_UPDATES=1、DISABLE_AUTOUPDATER=1 或 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 会关闭整个过程并隐藏 Enable auto-update 开关,除非同时设置 FORCE_AUTOUPDATE_PLUGINS=1。市场条目声明了 headersHelper 的插件会被自动更新跳过。复制的插件在会话中途更新时,hook 命令、监视器、MCP 服务器和 LSP 服务器继续使用前一个版本的路径;运行 /reload-plugins 把 hooks、MCP 服务器和 LSP 服务器切到新路径,监视器需要重启会话。

command 来源何时重跑:command 来源的插件不等自动更新过程。命令打印的目录反映工具运行时的状态,所以 Claude Code 会在这些时候重新运行你接受过的命令:每次安装或更新该插件时;会话启动后不久,对每个已启用的 command 来源插件在后台运行一次(不依赖市场的自动更新设置或 DISABLE_AUTOUPDATER);启动或 /reload-plugins 时,已启用插件的已安装版本在插件缓存里缺失时。设置了 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC 时跳过两次后台运行(显式安装和更新仍运行命令)。命令的哈希输出变化时,Claude Code 把结果作为新版本安装并在运行中的交互会话里重新加载,切换与 /reload-plugins 相同的组件;如果原地重新加载会使会话的提示缓存失效,Claude Code 改为提示你运行 /reload-plugins(会警告缓存成本,加 --force 重新运行才应用)。

命名冲突

来自不同来源的已启用插件共享清单名时,按这个顺序(从最高到最低优先级)决定加载哪个:

  1. id 出现在托管设置 enabledPlugins 里(true 或 false)的插件;清单名与该 id 的名字部分匹配的 --plugin-dir 副本不会加载,你会看到 --plugin-dir copy of "<name>" ignored: plugin is locked by managed settings
  2. 已启用的 --plugin-dir、--plugin-url 或 CLAUDE_CODE_PLUGIN_DIRS 插件;它会替换同名的已安装市场插件(静默替换,claude plugin list 仍把市场行显示为已启用,因为那一行反映你的设置,只有用 --debug 启动时写在 ~/.claude/debug/ 下的日志记录了替换)或 skills 目录插件(/plugin 的 Errors 标签页出现 Not loaded 行)
  3. 已安装的市场插件;同名的 skills 目录插件会得到相同的 Not loaded 行,点名已安装的插件
  4. skills 目录插件;两个这样的插件之间,~/.claude/skills/ 下的副本加载,项目 .claude/skills/ 下的副本被丢弃,并有一行说明哪个路径遮蔽了它
  5. 从 claude.ai 同步的插件;当任何其他来源的已启用插件与其名字匹配时,Claude Code 加载那个插件,并把同步的副本报告为未加载;想用 claude.ai 的副本,就禁用你自己的副本

因为顺序比较的是清单名,名为 hello-plugin 的 --plugin-dir 插件,当该插件清单里也写着 "name": "hello-plugin" 时会替换 hello@example-marketplace。要让某个 --plugin-dir 插件不遮蔽任何东西,或在父进程替你传了该标志时把它关掉,在任何设置文件里把它的 id 设为 false。