Claude Code 插件装了不加载:依赖、提示与相关性三层各卡在哪
「插件装了没反应」这句话没法直接回答。Claude Code 官方文档把这件事拆在三个不同页面上,三种现象长得很像,处置动作却完全不重叠:你自己装的插件功能不生效,跟平台组在 marketplace.json 里配了推荐但同事看不见,是两条链路。
先做分流:动手之前跑一条命令,把「装了但被禁用」和「压根没被推荐出来」分开。
claude plugin list --json
官方文档在《Constrain plugin dependency versions》一页写明,有问题的插件在这个 JSON 输出里会带 errors 字段列出问题,干净加载的插件则省略该字段。成本极低,却能把下面三层里的第一层直接摘出来。
第一层:依赖没满足,插件被 Claude Code 主动禁用
现象:插件明明装过,claude plugin list 里也能看到,但它的 skill、agent、hook 一个都不生效。
判定动作:跑上面那条命令看目标插件有没有 errors 字段。文档特意提醒,依赖问题在 claude plugin list 和 /plugin 中呈现为描述性的错误消息,而不是文档表格里那些字面错误码——别拿着 dependency-unsatisfied 这个词去搜输出,搜不到不代表没问题。文档同时写明,出现依赖错误时 Claude Code 会把受影响的插件禁用,直到你解决为止。
文档列出的常见错误有四个,含义和处置各不相同:
| 错误 | 含义 | 处置 |
|---|---|---|
dependency-unsatisfied | 依赖没装,或装了但被禁用 | 跑错误消息里给出的 claude plugin install;依赖所在的 marketplace 还没配就先 claude plugin marketplace add,Claude Code 会自动解析;依赖被禁用的就启用它 |
range-conflict | 多个插件对同一依赖的版本要求无法合并 | 错误消息会点名原因:没有版本满足全部范围、某个范围不是合法 semver、或范围复杂到无法求交。对应地卸载或更新冲突的一方、修正非法 version 字符串、简化过长的 || 链,或请上游放宽约束 |
dependency-version-unsatisfied | 已装依赖的版本落在本插件声明的范围之外 | claude plugin install <dependency>@<marketplace>,按当前所有约束重新解析 |
no-matching-tag | 依赖仓库上没有满足范围的 {name}--v* 标签 | 确认上游按约定打了标签,或放宽范围 |
处置时几个容易踩空的前提,都写在同一页里:
- 启用会连带启用依赖,但需要 Claude Code v2.1.143 或更高。更早的版本只启用你点名的那一个,然后在下一次加载时抛
dependency-unsatisfied。现象若是「我明明 enable 过了」,先看版本。 - 启用被拒绝还有三类固定原因:依赖没装、依赖被组织的插件策略阻止(会点名被拦的那个)、依赖在优先级更高的 scope 上被显式设成了
false(要么在那个 scope 启用,要么用--scope写到那里去)。 - 跨 marketplace 的依赖默认装不上。除非根 marketplace 的
marketplace.json把目标名字加进allowCrossMarketplaceDependenciesOn,否则安装以cross-marketplace错误失败。用户手动先装上那个依赖同样能满足约束。 - 预发布版本默认被排除。像
2.0.0-beta.1不会被匹配,除非范围用^2.0.0-0这类带预发布后缀的写法主动 opt in。上游只打了 beta 标签而你写的是普通范围,表现就是no-matching-tag。 - 非 git 源的依赖,版本约束根本不控制拉哪个版本。文档明确
npm、archive、command三类源不走标签解析,约束只在加载时检查,不满足就把依赖方插件以dependency-version-unsatisfied禁用。其中command源的依赖 Claude Code 从不自行安装;plugin.json里没写version的依赖满足不了任何约束。 - 本地文件夹形式的 marketplace 要按标签解析版本,需要 v2.1.196 或更高;更早版本不读它的标签,文件夹不是 git 仓库时也没标签可读,都退化成「按当前内容安装」。
上游打标签的约定是 {plugin-name}--v{version},插件目录下执行 claude plugin tag --push;文档写明它会先校验插件内容、检查 plugin.json 与 marketplace 条目版本是否一致、要求工作区干净。
处置后怎么验证:重跑 claude plugin list --json,确认 errors 字段消失。文档还提到,自动更新若因找不到满足所有范围的标签而跳过某个依赖,会把这次跳过列在 /plugin 的 Errors 标签页里并点名约束方,值得顺手看一眼。
什么情况说明不是这个原因:如果这个插件根本没有 errors 字段,依赖层就是干净的,再折腾 dependencies 也没用。先排掉两个纯结构问题:其一,commands/、agents/、skills/、hooks/ 这些目录不能放进 .claude-plugin/,只有 plugin.json 在里面(文档还补了一句:插件根永远不是 ~/.claude/,放在 ~/.claude/.mcp.json 的文件不会被读)。其二,插件里的 skill 一律带命名空间,是 /plugin-name:skill-name 而不是裸的 /skill-name。
还有个坑人的伪证据:文档写明 /reload-plugins 之后摘要里的 skills 计数只统计 commands/ 目录,所以哪怕 skill 已经重载,它也可能报 0 skills。别把这个 0 当成「没加载」的证据。 agents 那侧则相反——项目和用户的 .claude/agents/ 定义会覆盖同名的插件 agent,从 .claude/ 迁移后原文件不删,插件版本就一直不生效。
第二层:你的 CLI 发了 hint,用户那边没弹安装提示
现象:你按《Recommend your plugin from your CLI》在自己的 CLI 里实现了 <claude-code-hint /> 标记,格式也照文档写了,但用户那边从没见过安装提示。
怎么确认:文档给的是一串顺序检查,按它逐条对:
- 环境变量是否被设。Claude Code 为它通过 Bash 和 PowerShell 工具运行的每条命令、以及 hook 命令设置
CLAUDECODE=1;从 v2.1.172 起在同样这些子进程里还设CLAUDE_CODE_CHILD_SESSION=1。只有 Bash 和 PowerShell 工具的输出会触发安装提示;hook 命令里的 hint 标记会被剥掉并忽略。Windows 侧走 PowerShell 不会掉链子,这两个工具的输出是同等对待的。 - 标记是否独占一行。这是文档明说会被强制的两条之一:嵌在某行中间(比如塞进一条日志语句里)的标记直接被忽略,行首行尾的空白则允许。
- 目标是否在官方 Anthropic marketplace。这是强制的第二条:
value必须指向 Anthropic 控制的 marketplace(例如claude-plugins-official),指向别的 marketplace 的 hint 会被静默丢弃。文档还专门写明,站内提交表单加的是 community marketplace,而 hint 协议不检查 community。 - 属性是否合法。三个必需属性:
v(唯一支持值是1)、type(唯一支持值是plugin)、value(name@marketplace形式)。值可加双引号也可不加,不加引号时不能含空白,且不支持转义序列。 - 是否被提示频率挡掉。文档写了三档:同一插件只提示一次(提示过就记下,不管用户当时选了什么);每个会话最多一次,全机所有 CLI 合计;关闭了遥测的会话从不显示 hint 提示——包括设了
DISABLE_TELEMETRY或CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC的会话,以及在 Amazon Bedrock、Google Cloud 的 Agent Platform 这类第三方 provider 上因自动遥测退出而适用的会话。
处置:文档给了带环境变量门控的示例,Shell 版原样如下:
if [ -n "$CLAUDECODE" ]; then
printf '%s\n' '<claude-code-hint v="1" type="plugin" value="example-cli@claude-plugins-official" />' >&2
fi
同一页也给了 Node.js、Python、Go 三种写法,逻辑一致。门控选哪个变量文档给了取舍:CLAUDECODE 覆盖所有版本因而触达最广,但它在 tmux 会话、Claude Code 启动的 stdio MCP server 子进程、以及 IDE 扩展的集成终端里也会被设,而那里可能是真人在手敲你的 CLI;CLAUDE_CODE_CHILD_SESSION 只在 Claude Code 自己 spawn 的子进程里设(工具调用、hook 命令、状态行命令),代价是需要 v2.1.172 或更高。反直觉的一点:tmux server 这种长生命周期进程会把变量继承下来,之后从它启动的 shell 里仍会看到裸标记。
验证:文档说 hint 行总是在输出到达模型之前被移除,即使版本或 type 无法识别也一样。反过来说,「我在会话里没看到这个标记」并不能证明它没被发出来,验证只能靠提示本身是否出现,以及上面五条逐一排除。
什么情况说明不是这一层:插件根本不在 claude-plugins-official 里,那整条协议对你不成立,写得再对也不会弹——文档写明官方 marketplace 由 Anthropic 自行决定收录,站内提交表单加进去的是 community marketplace,而 hint 协议不检查 community;文档给的路径是:如果你有对接的 Anthropic 合作方联系人,通过对方协调官方 marketplace 上架。
第三层:marketplace 配了 relevance,但成员看不到建议
现象:平台组按《Recommend plugins for your org》给插件条目加了 relevance 块,成员那边没有任何建议出现。
判定动作,按依赖强度从硬到软:
- 客户端版本。
relevance需要 Claude Code v2.1.152 或更高,更早的客户端直接忽略这个字段。 - 管理员是否 allowlist 过这个 marketplace。光在
marketplace.json里声明relevance不够,必须由管理员在 managed settings 的pluginSuggestionMarketplaces里加上该 marketplace 名字,官方 Anthropic marketplace 也不例外。 - 非官方 marketplace 还要在同一份 managed settings 里声明来源:作为
extraKnownMarketplaces中该名字的条目,或作为strictKnownMarketplaces的条目。文档强调,如果机器上以这个名字注册的 marketplace 来自另一个来源,allowlist 里的名字会被忽略。 - 是否被 spinner-tips 设置关掉了。spinner tip 和会话开始时的一行通知都属于 spinner-tips 体系,
spinnerTipsEnabled设成false、或配了带excludeDefault的spinnerTipsOverride时两者都被禁用。而/pluginDiscover 标签页的置顶不受 tip 设置影响——这正好可以当判定动作:tip 看不到但 Discover 里置顶了,说明匹配成功,只是被 tip 开关挡住了。 - 信号本身是否匹配得上。
relevance.signals下文档列了五个字段:cwd、cli、hosts、filesRead、manifestDeps,至少要有一个才可能被建议。踩坑最多的是cli:文档写明 Claude Code 每次 shell 工具调用只记录一个命令名——跳过前导环境变量赋值和sudo之后的第一个 token,而且复合命令只贡献前导命令,所以cd infra && terraform plan记下的是cd而不是terraform,且是精确匹配。这条在每个平台都适用,Windows 上走 PowerShell 或 Git Bash 的记录方式相同。
Windows 侧要单独盯 manifestDeps。 文档写明这个信号的路径不做分隔符归一化,Windows 路径就是反斜杠;file 是对清单文件路径(通常是绝对路径)的正则,必须尾锚定,因为起始锚定的模式永远匹配不上绝对路径。官方写法是 JSON 转义形式的 [/\\\\]package\\.json$,用 [/\\\\] 同时吃两种斜杠,用 \\. 让点号变字面量;另外 file 大小写不敏感、pattern 大小写敏感。而 cwd 和 filesRead 是正斜杠归一化且大小写不敏感的,别混着记。
处置后怎么验证:发布前跑 claude plugin validate ./my-marketplace。它会把 relevance 与 relevance.signals 下的未知键报为警告,标记 relevance 值不是对象的情况,并拒绝 hosts 里带 scheme、端口或路径的条目(hosts 只接受裸的小写主机名)。注意这三条里只有 hosts 那条是拒绝,未知键只是警告——发布前扫一眼输出,别看到「通过」就以为字段名全拼对了。至于有没有办法把警告直接升级成错误,官方文档没有说明这一点,以 claude plugin validate --help 的实际输出为准。
什么情况说明不是这一层:allowlist 配了、版本够、信号也确实该命中,却只是「偶尔才看见」,那多半不是配置问题,而是文档写明的展示频率在起作用:同一插件的建议在 spinner tip 和会话开始通知合计最多每三个会话出现一次,插件一旦装上两者都不再出现;会话开始通知显示过两次后就不再出现;Discover 标签页对一个插件只置顶一次。这两个展示位还各有版本门槛——会话开始通知需要 v2.1.153 或更高,Discover 置顶需要 v2.1.154 或更高。看不到,不等于没配对。
最后一句边界:文档明确 Claude Code 从不自动安装插件,永远由用户确认,第二层和第三层做的都只是「建议」。真要全组织铺开,文档指的是把插件加进 managed settings 的 enabledPlugins。
本文依据 Claude Code 官方文档(code.claude.com/docs)于 2026-08-17 的公开内容整理。
该产品闭源,本文只复述官方文档写明的机制,不推断其内部实现;
我们没有对文中涉及的功能做过实测,因此不涉及界面外观、操作手感与运行速度的任何描述。
该产品迭代频繁,文中涉及的命令、配置项与默认值随版本变动,请以官方文档最新内容为准。
本文不涉及价格、额度与限流的具体数值,相关信息请以官方定价与用量说明页为准。
安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。