avatar


7.Plugin

引子

经过上文的讨论,现在我们有了:持久注入的CLAUDE.md、按需加载的Skill(技能)、隔离执行的Sub-Agent(子智能体)、确定性控制的Hook(钩子)、扩展工具边界的MCP(Model Context Protocol,模型上下文协议)服务器。
这些定制工具越攒越多,却散落在各个项目的.claude/目录和settings.json里,共享给同事靠手动拷贝,既没有版本,也没法批量更新。

那么,攒下的定制件,怎样打包、分发、更新?

这就是Plugin(插件)一个把定制件打包分发的容器,所解决的问题。

原理

理解插件只需六件事。

  • 打包侧三件
    • 它到底是什么
    • 目录该怎么摆
    • 组件之间靠什么不打架
  • 分发侧三件
    • 市场是什么
    • 装完从哪运行
    • 用户何时拿到更新

打包侧

插件是什么

插件不引入任何新能力。它是一个分发容器:把已有的Skills、Agents、Hook、MCP配置打包成一个可安装、可版本化的单元,再经Marketplace(插件市场)分发给团队或社区。

为什么需要这层容器?一套团队工作流往往同时包含几类组件:几个Skill、一两个Sub-Agent、几条Hook、一份MCP配置。独立形态下它们分处不同位置、安装方式各不相同,接收方要逐一理清每个组件放哪、怎么生效。插件的做法是:把它们收进同一个目录,用一份清单描述,整体安装、整体卸载。

目录该怎么摆

一个插件就是一个遵循固定布局的目录。
包括plugin.json清单在内,各部分都是可选的,有什么放什么。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
my-plugin/
├── .claude-plugin/
│ └── plugin.json # 清单文件
├── skills/ # Skill,每个是<name>/SKILL.md
├── commands/ # 旧式自定义命令
├── agents/ # Sub-Agent定义
├── hooks/
│ └── hooks.json # Hook配置
├── monitors/
│ └── monitors.json # 后台监视器配置
├── bin/ # 加入Bash工具PATH的可执行文件
├── settings.json # 插件启用时应用的默认设置
├── .mcp.json # MCP服务器配置
└── .lsp.json # LSP服务器配置

注意:只有plugin.json放在.claude-plugin/子目录里;skills/agents/hooks/等组件目录以及.mcp.json必须放在插件根目录,不能放进.claude-plugin/内,放错位置的组件不会生效。

组件之间靠什么不打架

plugin.json中的name不只是展示名,还决定命名空间。

这个我们在《3.Skill》讨论的,插件里的Skill以/plugin-name:skill的形式调用。
比如插件quality-review里名为review的Skill,调用名是/quality-review:review
这让多个插件、以及插件与本地配置之间的同名组件互不冲突。

分发侧

市场是什么

插件解决打包,市场解决"去哪找、怎么装"。
一个市场本质上是一份插件索引:仓库或目录的.claude-plugin/marketplace.json文件,列出若干插件条目及其来源。

装完从哪运行

插件安装后被复制到本机缓存目录运行,而不是在原仓库位置运行。
这带来一个路径陷阱:插件内部写的、指向插件目录之外的相对路径(比如../shared)在运行时不可达。
规则很简单,凡是引用插件自带的文件(Hook脚本、MCP服务器可执行文件等),一律用${CLAUDE_PLUGIN_ROOT}变量,它在运行时展开为插件的实际根目录。

用户何时拿到更新

ClaudeCode把版本号当缓存键:/plugin update(或自动更新触发)时算出插件当前版本,与已安装的一致就跳过。所以"何时更新"取决于这个版本号怎么来、何时变。

版本号按顺序解析,取第一个设了的:

  1. plugin.json里的version
  2. 市场条目里的versionmarketplace.jsonplugins数组中描述该插件的那一项,见后文「市场配置」)
  3. 插件git来源的commit SHA(githuburl等git托管来源)

由此有两种发布策略:

  • version(写在plugin.json
    锁定版本,用户只有在我们手动改了这个字段后才更新。"发了新代码却忘了改版本号"是"更新不生效"最常见的原因。适合有稳定发布节奏的插件。
  • 两处都不设version
    回落到commit SHA,每次提交即新版本,用户总能拿到最新提交。适合开发中、快速迭代的插件。

注意:解析顺序里plugin.json排在市场条目前面,所以两处都写了version时以plugin.json为准、市场条目的被忽略——别两处都写,徒增困惑。

选型:打包成插件还是留在.claude/

  • 独立形态与项目代码同仓、改起来直接,也适合个人试验。
  • 插件形态有命名空间、有版本、能一键安装。

那么,我们怎么选择呢?只服务当前项目的配置,放在.claude/里随代码提交就够了。只有需要团队共享、跨项目重用或社区分发时,才值得打包成插件。

插件形态与独立.claude/形态一一对应,同一份组件只是换个位置摆放。各组件自身的机制、字段与协议本章一概不重复,见各归属章。

组件 独立形态 插件形态 机制详见
Skill .claude/skills/<name>/SKILL.md,调用名/<skill> skills/<name>/SKILL.md,调用名/<plugin>:<skill> 《3.Skill》
Sub-Agent .claude/agents/*.md agents/*.mdhooks/mcpServers/permissionMode三字段不支持,写了会被忽略;需要这些能力时,改用独立.claude/agents/形态 《4.SubAgent》
Hook settings.jsonhooks字段 hooks/hooks.json,脚本路径用${CLAUDE_PLUGIN_ROOT}引用 《5.Hook》
MCP服务器 .mcp.json 插件根的.mcp.json,命令路径用${CLAUDE_PLUGIN_ROOT}引用 《6.MCP》

示例

需求

我们为团队维护一个代码质量插件quality-review,并通过团队市场分发,让队友在项目里自动获得它。

代码质量插件

示例代码(目录结构):

1
2
3
4
5
6
quality-review/
├── .claude-plugin/
│ └── plugin.json
└── skills/
└── review/
└── SKILL.md

示例代码(.claude-plugin/plugin.json):

1
2
3
4
5
{
"name": "quality-review",
"description": "代码质量审查",
"version": "1.0.0"
}

示例代码(skills/review/SKILL.md):

1
2
3
4
5
---
description: 对指定文件或目录做代码审查
---

对"$ARGUMENTS"指向的文件或目录做代码审查,按严重、警告、建议三级输出结论。

--plugin-dir本地调试,改完文件重新启动即可测试,省去反复安装卸载的循环。示例代码:

1
claude --plugin-dir ./quality-review

会话里以命名空间全名调用:

1
/quality-review:review src/

市场配置

团队市场是一个GitHub仓库a-corp/claude-pluginsquality-review以相对路径放在仓库内,另一个插件deploy-tool引用外部仓库。

示例代码(.claude-plugin/marketplace.json):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"name": "team-plugins",
"owner": {"name": "Platform Team"},
"plugins": [
{
"name": "quality-review",
"source": "./plugins/quality-review",
"description": "代码质量审查"
},
{
"name": "deploy-tool",
"source": {
"source": "github",
"repo": "acme-corp/deploy-plugin",
"ref": "v2.0"
}
}
]
}

团队成员添加市场并安装:

1
2
/plugin marketplace add a-corp/claude-plugins
/plugin install quality-review@team-plugins

注意:install@后面写的是市场清单里的nameteam-plugins),不是仓库地址。

团队自动安装

要让团队成员在某个项目里自动获得指定插件,不必人人手动执行安装命令:在项目的.claude/settings.json里声明extraKnownMarketplaces(市场从哪来)与enabledPlugins(启用哪些插件)即可,settings的层级与优先级见《1.Start》

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"extraKnownMarketplaces": {
"team-plugins": {
"source": {
"source": "github",
"repo": "a-corp/claude-plugins"
}
}
},
"enabledPlugins": {
"quality-review@team-plugins": true
}
}

这份文件随项目代码提交,队友在该项目里使用ClaudeCode时即可获得同一套插件,插件的变更也随代码评审流程可追溯。

实践

plugin.json字段

plugin.json是插件的清单。它本身是可选的,只有需要声明元数据时才必须提供。

字段 必需 说明
name 插件标识,也是组件的命名空间前缀
description 插件管理器中展示的描述,建议提供
version 版本号;省略时以git commit SHA作为版本,见前文「用户何时拿到更新」
author 作者信息,对象形式{name, email}email可省略
homepage 文档或主页URL
repository 仓库URL
license SPDX许可证标识,如MIT、Apache-2.0

会话内命令(/plugin)

插件在会话内用/plugin命令族管理。不带参数的/plugin打开交互管理器,含Discover、Installed、Marketplaces、Errors四个标签页。

命令 作用
/plugin install <name>@<marketplace> 安装插件,交互式选择作用范围
/plugin uninstall <name>@<marketplace> 卸载插件
/plugin enable <name>@<marketplace> 启用插件
/plugin disable <name>@<marketplace> 禁用插件
/plugin list [--enabled\|--disabled] 列出已安装插件
/plugin details <name>@<marketplace> 查看插件详情
/plugin validate [path] 校验plugin.jsonmarketplace.json语法
/plugin marketplace add <source> 添加市场
/plugin marketplace list 列出已配置的市场
/plugin marketplace remove <name> 移除市场
/plugin marketplace update [name] 更新指定市场或全部市场
/reload-plugins 重新加载活动插件,无需重启会话

终端命令(claude plugin)

脚本或自动化场景下可用claude plugin前缀的终端命令,安装时以--scope显式指定作用范围:

命令 作用
claude plugin init <name> 创建插件骨架目录(默认位于~/.claude/skills/下)
claude plugin install <name>@<marketplace> --scope <user\|project\|local> 在指定作用范围安装插件
claude plugin marketplace add <source> [--scope] [--sparse] 添加市场
claude plugin validate . 校验当前目录

Marketplace

marketplace.json字段

字段 必需 说明
name 市场标识,kebab-case,安装时@<marketplace>引用的就是它
owner 维护者信息,对象形式{name, email}email可省略
plugins 插件条目数组
description 市场描述
version 市场清单自身的版本
metadata.pluginRoot 相对路径的基准目录,如"./plugins"
renames {"旧名": "新名"}映射,用于插件重命名或移除,见后文「重命名与迁移」

插件条目与来源

plugins数组中每个条目的字段:

字段 说明
name 插件标识,必需
source 插件来源,必需;字符串形式的相对路径,或对象形式的远程来源
displayName UI显示名,缺省时回退用name
version 该条目声明的插件版本
strict 默认trueplugin.json是权威,市场条目仅作补充;设为false时市场条目全权控制,与plugin.json冲突会导致加载失败
relevance 推荐信号,需管理员设置允许才生效
defaultEnabled 安装后是否默认启用,默认true

source支持五种来源类型:

类型 写法 可选锁定
相对路径 "./plugins/quality-review"
GitHub {"source": "github", "repo": "owner/repo"} refsha
git URL {"source": "url", "url": "https://gitlab.com/team/plugin.git"} refsha
git子目录 {"source": "git-subdir", "url": "owner/repo", "path": "tools/plugin"} refsha
npm {"source": "npm", "package": "@org/plugin"} versionregistry

注意:通过远程URL添加的市场,清单文件能下载,但相对路径source指向的插件目录并不在本机,这类市场里的条目必须改用GitHub或git URL来源。

重命名与迁移

市场维护者要重命名或下架插件时,在marketplace.json里声明renames映射(键是插件旧名):值为新名表示重命名,值为null表示该插件已下架。
已安装用户的配置会自动迁移,把对旧名的引用改写或清理掉。

注意:如果插件的远程源本身换了位置,用户仍需手动重新执行一次/plugin install

插件环境变量

插件相关的环境变量如下。其中私有仓库插件的自动更新,依赖GITHUB_TOKEN/GITLAB_TOKEN/BITBUCKET_TOKEN完成认证。

环境变量 用途
CLAUDE_CODE_PLUGIN_CACHE_DIR 自定义插件缓存目录
CLAUDE_CODE_PLUGIN_SEED_DIR 容器构建时预装插件的目录
CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS 插件git操作超时,毫秒,默认120000
CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE git拉取失败时保留已有缓存,适合离线环境
GITHUB_TOKEN / GITLAB_TOKEN / BITBUCKET_TOKEN 私有仓库插件自动更新时的认证
文章作者: Kaka Wan Yifan
文章链接: https://kakawanyifan.com/12807X
版权声明: 本博客所有文章版权为文章作者所有,未经书面许可,任何机构和个人不得以任何形式转载、摘编或复制。

留言板