本教程聚焦 Claude Code 的插件系统(Plugin System)——这是把零散的 Skill、Agent、Hook、MCP 服务器、LSP 服务器打包成一个可分发单元的官方机制。当你已经写好若干 SKILL.md,想把它们作为一个整体交给团队、通过 /plugin 一键安装、跟随 Git 仓库随版本演进时,插件就是答案。本教程适合已经掌握 Skill 基础、希望进入"团队级标准化能力分发"阶段的开发者。完成后你将能独立设计 plugin.json 清单、组织多组件目录、搭建私有 marketplace,并在 CI 中用 claude plugin validate --strict 把关发布质量。
displayName 需 v2.1.143、defaultEnabled 需 v2.1.154、monitors 需 v2.1.105)SKILL.md,理解 frontmatter 与渐进披露很多人把 Plugin 和 Skill 混为一谈,但它们处在不同抽象层级。
Skill 是"一段能力":一个目录 + 一个 SKILL.md,由模型按需加载。它是面向单个任务的最小复用单元。
Plugin 是"一个能力包":一个自包含目录,内部可以装下任意数量的 Skill、Agent、Hook、MCP/LSP 服务器、Monitor、Output Style、Theme。它是面向分发与版本管理的单元。
关键差异可以用一句话概括:Skill 让 Claude 多一项本事,Plugin 让一项本事的拥有者可控、可装、可卸、可升级、可分享。
| 维度 | Skill | Plugin |
|---|---|---|
| 定位 | 单点能力 | 能力集合 + 分发载体 |
| 必需文件 | SKILL.md |
可选 .claude-plugin/plugin.json |
| 可含组件 | 仅指令 + 脚本 | Skill/Agent/Hook/MCP/LSP/Monitor/Theme |
| 安装方式 | 放进目录即生效 | marketplace 安装 / @skills-dir 就地加载 |
| 版本管理 | 无原生版本 | 支持 semver 与 commit-SHA 两种策略 |
| 作用域 | 跟随目录位置 | user/project/local/managed 四级 |
理解这张表后,你应该建立一个判断准则:当能力需要"被多人以相同版本使用"时,就值得从 Skill 升级为 Plugin。
官方给出的完整布局如下:
enterprise-plugin/
├── .claude-plugin/ # 元数据目录(可选)
│ └── plugin.json # 插件清单
├── skills/ # 技能
│ ├── code-reviewer/
│ │ └── SKILL.md
│ └── pdf-processor/
│ ├── SKILL.md
│ └── scripts/
├── commands/ # 扁平 .md 形式的技能(旧式)
│ ├── status.md
│ └── logs.md
├── agents/ # 子 Agent 定义
├── output-styles/ # 输出风格
├── themes/ # 颜色主题(实验性)
├── monitors/ # 后台监控(实验性)
├── hooks/ # Hook 配置
│ └── hooks.json
├── bin/ # 加入 Bash PATH 的可执行文件
├── scripts/ # Hook 与工具脚本
├── settings.json # 插件默认设置
├── .mcp.json # MCP 服务器定义
├── .lsp.json # LSP 服务器配置
├── LICENSE
└── CHANGELOG.md
最易踩的坑:所有组件目录(commands/、agents/、skills/、hooks/ 等)必须位于插件根目录,而不是 .claude-plugin/ 内部。.claude-plugin/ 里只放 plugin.json。如果你把 skills/ 误塞进 .claude-plugin/skills/,插件能加载但组件全部"隐身"——这是新手最高频的错误。
另一个要点:插件根目录的 CLAUDE.md 不会被当作项目上下文加载。插件贡献上下文的唯一通道是 skill、agent、hook,而不是 CLAUDE.md。想注入指令,就把它写进一个 skill。
清单是可选的——省略时 Claude Code 会自动发现默认位置下的组件,并用目录名作为插件名。但凡你要做团队分发,都应当显式编写清单。下面给出完整 schema 再逐一拆解。
{
"name": "deployment-tools",
"displayName": "Deployment Tools",
"version": "1.2.0",
"description": "部署自动化工具集",
"author": { "name": "Dev Team", "email": "[email protected]" },
"homepage": "https://docs.example.com/plugin",
"repository": "https://github.com/author/plugin",
"license": "MIT",
"keywords": ["deployment", "ci-cd"],
"skills": "./custom/skills/",
"commands": ["./custom/commands/special.md"],
"agents": ["./custom/agents/reviewer.md"],
"hooks": "./config/hooks.json",
"mcpServers": "./mcp-config.json",
"lspServers": "./.lsp.json",
"outputStyles": "./styles/",
"experimental": {
"themes": "./themes/",
"monitors": "./monitors.json"
},
"userConfig": { },
"dependencies": [ ]
}
name 是唯一必填字段(前提是你写了清单),必须是 kebab-case、不含空格。它同时承担命名空间职责:插件 plugin-dev 提供的 agent agent-creator,在 UI 中显示为 plugin-dev:agent-creator。
几个值得注意的新字段:
displayName(v2.1.143+):人类可读名称,可含空格与任意大小写,仅用于 UI 展示,不参与查找。省略时回退到 name。version:semver 字符串。设了它就必须每次发版手动 bump,否则 /plugin update 会判定"已是最新"。这是显式版本策略;省略则改用 git commit-SHA 作为版本号,每次提交即一个新版本,适合快速迭代的内部插件。defaultEnabled(v2.1.154+):默认 true。设为 false 可让插件安装后默认关闭,用户需手动 claude plugin enable。适合那种会连接外部服务、需要用户明确知情的插件。清单中的路径字段决定了 Claude Code 去哪里找组件。这里的替换规则是新手第二高频踩坑点:
| 字段 | 行为 | 说明 |
|---|---|---|
commands |
替换默认 commands/ |
想保留默认并追加,须显式列出:["./commands/", "./extras/"] |
agents |
替换默认 agents/ |
同上 |
outputStyles |
替换 | 同上 |
experimental.themes |
替换 | 同上 |
experimental.monitors |
替换 | 同上 |
skills |
追加默认 skills/ |
默认目录始终扫描,清单路径是额外补充 |
hooks / mcpServers / lspServers |
各有独立合并规则 | 多来源会合并而非替换 |
一个反直觉的设计:当清单指定了 commands 字段,默认的 commands/ 目录不再被扫描。从 v2.1.140 起,这种"被忽略的默认文件夹"会在 /doctor、claude plugin list 和 /plugin 详情中给出提示。所以养成习惯:要么全用默认位置不放路径字段,要么放字段就把默认目录也写进数组里。
所有路径必须相对插件根目录且以 ./ 开头。绝对路径或 ../ 跨目录引用在安装后会失效——因为 marketplace 插件会被复制到本地缓存(~/.claude/plugins/cache),缓存外的文件根本不会被带过去。
Claude Code 会忽略它不认识的顶层字段,而非报错。这意味着你可以用同一个 plugin.json 同时充当 VS Code 扩展清单、npm package.json、或 MCPB/DXT bundle 清单——一份文件,多个生态共享。
claude plugin validate 会把未识别字段作为警告(不是错误)报告;如果某字段只差一两个字符(比如把 keywords 拼成 keyword),它还会智能提示你可能是想写哪个。加 --strict 可在 CI 中把警告升级为错误,用来在发布前拦住手滑。
安装插件时选择 scope,决定了它对谁可见:
| Scope | 写入的设置文件 | 适用场景 |
|---|---|---|
user |
~/.claude/settings.json |
个人插件,全项目可用(默认) |
project |
.claude/settings.json |
团队插件,随版本控制共享 |
local |
.claude/settings.local.json |
项目专属,被 gitignore |
managed |
受管设置文件 | 受管插件(只读,仅可更新) |
团队分发最常用的是 project——把 enabledPlugins 写进 .claude/settings.json 提交到仓库,任何 clone 仓库的同事都会获得相同的插件清单。命令示例:
# 默认装到 user scope
claude plugin install formatter@my-marketplace
# 装到 project scope,团队共享
claude plugin install formatter@my-marketplace --scope project
# 装到 local scope,仅本机本项目
claude plugin install formatter@my-marketplace --scope local
并非所有插件都要走 marketplace。任何在 skills 目录下、含 .claude-plugin/plugin.json 的文件夹,都会在下次会话自动加载为 @skills-dir 源的插件,无需 marketplace、无需安装步骤。
用脚手架命令一键生成:
# 最小骨架
claude plugin init my-helper
# 带上 skill 和 hook 文件夹
claude plugin init my-helper --with skills hooks
# 带上 MCP 配置
claude plugin init my-helper --with mcp
# 覆盖已存在的骨架
claude plugin init my-helper --force
--with 支持的值与对应脚手架产物:
| 值 | 生成内容 |
|---|---|
skills |
一个额外的命名空间 :example skill |
agents |
一个 agents/ 子 Agent 定义 |
hooks |
一个 hooks/hooks.json 含示例事件处理 |
mcp |
一个 .mcp.json 含 HTTP 与 stdio 示例 |
lsp |
一个 .lsp.json 语言服务器示例 |
output-style |
一个会自动生效的输出风格 |
channel |
一个基于 MCP 的 channel(含 server.ts、.mcp.json、package.json) |
@skills-dir 插件的加载位置分两种信任级别:
~/.claude/skills/):每个项目都加载,无额外限制。<repo>/.claude/skills/):随仓库分发,但内容来自仓库而非你本人,因此要经过与 .claude/settings.json 相同的工作区信任对话框;并且它声明的 MCP 服务器要走逐服务器审批,LSP 服务器要信任工作区后才启动,后台 monitor 不加载。注意一个易错点:项目级 @skills-dir 插件只从启动 Claude Code 时所在的 .claude/skills/ 加载,不会像普通 skill 那样向上递归到仓库根。从子目录启动会漏掉根目录的插件——要么从仓库根启动,要么改完目录后执行 /reload-plugins。
插件脚本里大量需要引用路径,Claude Code 提供三个变量,在 skill 内容、agent 内容、hook 命令、monitor 命令、MCP/LSP 配置中均可内联替换,同时也会作为环境变量导出给子进程:
${CLAUDE_PLUGIN_ROOT}:插件安装目录的绝对路径,用于引用随包分发的脚本、二进制、配置。插件更新时此路径会变,旧版本目录约保留 7 天后被清理——所以不要在这里写持久状态。${CLAUDE_PLUGIN_DATA}:持久化数据目录,路径为 ~/.claude/plugins/data/{id}/,跨插件版本存活。适合放 node_modules、Python venv、缓存、生成代码。首次引用即自动创建。${CLAUDE_PROJECT_DIR}:项目根,等价于 hook 中的同名变量。一个生产级的依赖安装模式——在 SessionStart hook 中比较随包 package.json 与持久目录中副本,差异时才重装:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "diff -q \"${CLAUDE_PLUGIN_ROOT}/package.json\" \"${CLAUDE_PLUGIN_DATA}/package.json\" >/dev/null 2>&1 || (cd \"${CLAUDE_PLUGIN_DATA}\" && cp \"${CLAUDE_PLUGIN_ROOT}/package.json\" . && npm install) || rm -f \"${CLAUDE_PLUGIN_DATA}/package.json\""
}
]
}
]
}
}
随后随包脚本就能跑在持久化的依赖上:
{
"mcpServers": {
"routines": {
"command": "node",
"args": ["${CLAUDE_PLUGIN_ROOT}/server.js"],
"env": { "NODE_PATH": "${CLAUDE_PLUGIN_DATA}/node_modules" }
}
}
}
这个"差异比对 + 重装 + 失败回退"的三段式是官方推荐的依赖管理模式,diff 在副本缺失或不同时都返回非零,覆盖了首次运行与依赖变更更新两种情况;npm install 失败则尾部 rm 删掉副本,下次会话重试。
要求用户手改 settings.json 是糟糕体验。userConfig 字段声明插件启用时主动提示用户填写的值:
{
"userConfig": {
"api_endpoint": {
"type": "string",
"title": "API endpoint",
"description": "团队 API 端点"
},
"api_token": {
"type": "string",
"title": "API token",
"description": "API 认证令牌",
"sensitive": true
}
}
}
支持的 type:string、number、boolean、directory、file。sensitive: true 会掩码输入并存入系统钥匙串(而非明文 settings.json);required: true 空值校验失败;default 提供默认值;multiple: true 让 string 接受数组;min/max 约束 number。
填好的值可在 MCP/LSP 配置、hook 命令、monitor 命令中用 ${user_config.KEY} 替换;非敏感值还能在 skill 和 agent 内容中替换;所有值会以 CLAUDE_PLUGIN_OPTION_ 前缀导出为环境变量。
需要注意钥匙串与 OAuth token 共享,总量约 2KB 上限——敏感值要尽量短。
下面把前面的知识串成一个完整可运行的例子。目标:封装团队的三项规范——提交信息校验、代码评审 checklist、敏感信息扫描——为一个可分发的插件。
claude plugin init team-standards --with skills hooks
cd ~/.claude/skills/team-standards
.claude-plugin/plugin.json{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "team-standards",
"displayName": "团队代码规范",
"version": "1.0.0",
"description": "提交规范、评审 checklist、敏感信息扫描三合一",
"author": { "name": "Platform Team" },
"license": "Apache-2.0",
"keywords": ["review", "security", "commit"],
"skills": ["./skills/"],
"commands": ["./commands/"],
"hooks": "./hooks/hooks.json",
"userConfig": {
"jira_prefix": {
"type": "string",
"title": "JIRA 前缀",
"description": "提交信息必须以此开头,如 PROJ-",
"default": "PROJ-"
}
}
}
skills/commit-guard/SKILL.md:
---
name: commit-guard
description: 校验 git 提交信息是否符合团队规范(前缀 ${user_config.jira_prefix} + 类型 + 简述)。在用户准备 commit 时使用。
---
# 提交信息守卫
1. 读取最近一条未提交的提交信息草稿
2. 检查是否以 ${user_config.jira_prefix} 开头
3. 检查类型词(feat/fix/docs/refactor/chore/test)
4. 不合规时给出改写建议并示例
skills/review-checklist/SKILL.md:
---
name: review-checklist
description: 用团队评审 checklist 审查改动,覆盖边界条件、错误处理、测试覆盖、性能、安全五维。在 /review 或代码评审场景使用。
---
# 团队评审 checklist
详见 reference.md 五维清单……
skills/secret-scan/SKILL.md:
---
name: secret-scan
description: 扫描工作区中可能的密钥泄露(AWS key、私钥、token)。调用 scripts/scan.sh 执行确定性扫描。
---
# 敏感信息扫描
执行 `${CLAUDE_PLUGIN_ROOT}/scripts/scan.sh`,对命中结果逐条确认是否误报。
hooks/hooks.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}\"/scripts/scan.sh"
}
]
}
]
}
}
scripts/scan.sh(记得 chmod +x):
#!/usr/bin/env bash
# 扫描新增文件中的疑似密钥
pattern='(AKIA[0-9A-Z]{16}|-----BEGIN (RSA |EC )?PRIVATE KEY-----|ghp_[a-zA-Z0-9]{36})'
if grep -rEn "$pattern" "${CLAUDE_PROJECT_DIR}" 2>/dev/null; then
echo "⚠️ 疑似密钥命中,已拦截写入" >&2
exit 2 # 退出码 2 阻断工具调用
fi
exit 0
claude plugin validate ./team-standards --strict
claude plugin details team-standards
claude --debug
validate --strict 会把警告升为错误,是发布前的质量门禁。details 会列出组件清单与预估 token 成本,分为"always-on"(每个会话恒定开销,来自 skill/agent 描述)与"on-invoke"(组件触发时的开销),帮你判断插件是否过重。
git init && git add -A && git commit -m "feat: 团队规范插件 1.0.0"
claude plugin tag --push # 创建 v1.0.0 发布 tag
@skills-dir 只适合个人开发调试,团队分发要走 marketplace。在团队 Git 仓库根放一个 marketplace.json,把上面的插件作为一项登记进去。团队成员添加该 marketplace 后,即可 /plugin 浏览安装。
关键在于版本策略的选择:
| 策略 | 做法 | 更新行为 | 适用 |
|---|---|---|---|
| 显式版本 | plugin.json 设 version |
必须 bump 才推送更新 | 稳定发布周期的已发布插件 |
| commit-SHA | 两个地方都不设 version | 每次提交即新版本 | 内部快速迭代插件 |
显式版本遵循 semver:破坏性改动升 MAJOR、新功能升 MINOR、修 bug 升 PATCH,并在 CHANGELOG.md 记录。关键陷阱:设了 version 就必须每次手动 bump,光推新提交没用——Claude Code 看到相同版本字符串会直接用缓存副本。
理解缓存机制能解释很多"为什么装了不生效":
~/.claude/plugins/cache,每个版本一个独立目录。卸载或更新后,旧目录被标记为孤儿,7 天后自动清理——宽限期让并发会话仍能跑旧版本。../shared-utils 之类的相对穿越在缓存里不工作。要让兄弟插件共享 skill,可用:ln -s ../../shared-plugin/skills/foo ./skills/foo(Windows 用 mklink /D)。
claude --debug 是第一工具,它会打印:加载了哪些插件、清单错误、skill/agent/hook 注册情况、MCP 服务器初始化。常见问题速查:
| 现象 | 原因 | 解决 |
|---|---|---|
| 插件不加载 | plugin.json 无效 |
claude plugin validate 查语法/Schema |
| skill 不出现 | 目录结构错 | 组件须在根目录而非 .claude-plugin/ 内 |
| hook 不触发 | 脚本不可执行 | chmod +x script.sh;检查 shebang |
| MCP 启动失败 | 缺 ${CLAUDE_PLUGIN_ROOT} |
所有插件路径都用该变量 |
| 路径错误 | 用了绝对路径 | 必须相对、以 ./ 开头 |
LSP Executable not found |
语言服务器没装 | 先 npm install -g 装二进制 |
hook 不触发时按四步排查:脚本可执行?shebang 正确?路径用了 ${CLAUDE_PLUGIN_ROOT}?手动跑能过?事件名大小写敏感(PostToolUse 而非 postToolUse),matcher 要匹配工具名(Write|Edit)。
flowchart TD
A["需求:团队级标准化能力"] --> B{能力数量与分发对象?}
B -->|单个能力、自用| C["写 SKILL.md 放 skills 目录"]
B -->|多个能力、团队共享| D["打包为 Plugin"]
D --> E["claude plugin init 脚手架"]
E --> F["编写 .claude-plugin/plugin.json 清单"]
F --> G["组织 skills/ agents/ hooks/ .mcp.json"]
G --> H["写 scripts 并 chmod +x"]
H --> I["用 userConfig 声明用户配置项"]
I --> J{分发方式?}
J -->|本地开发| K["@skills-dir 就地加载"]
J -->|团队分发| L["提交 Git + claude plugin tag"]
K --> M["claude plugin validate --strict"]
L --> M
M --> N["claude plugin details 查 token 成本"]
N --> O["claude --debug 验证加载"]
O --> P["/plugin 安装或 marketplace 发布"]
P --> Q["版本策略: 显式 semver / commit-SHA"]
Q --> R["团队 claude plugin install --scope project"]
R --> S["随 .claude/settings.json 共享"]
claude plugin details 输出的两类 token 成本值得在设计阶段就盯紧:
设计原则:描述要精炼到能精准触发即可,不必把整份 reference 塞进 SKILL.md 顶部——这正是渐进披露的价值,把详尽内容放进同目录的 reference.md,按需加载。
| 维度 | 评估 |
|---|---|
| 适用训练营类型 | 企业内训"AI 编程工程化"营、团队效能提升营、Claude Code 进阶营 |
| 学员基础 | 需先完成 Skill 基础(建议前置 4 课时 Skill 训练) |
| 建议时长 | 理论 2 课时 + 实战 4 课时(含打包、marketplace、调试) |
| 验收标准 | 学员独立产出一个含 ≥2 skill、1 hook、1 userConfig 的可分发插件,通过 validate --strict |
| 延伸方向 | 与 MCP 服务器开发营、Hook 事件总线营组合形成"插件生态工程师"完整路径 |
code.claude.com/docs/en/plugins——教程式用法与实战code.claude.com/docs/en/plugin-marketplaces——创建与管理 marketplacecode.claude.com/docs/en/skills——Skill 开发细节,与插件内 skill 行为一致.claude 目录体系实战,涵盖 skills/agents/hooks/plugins 协同本文由 51学通信 原创,站长「爱卫生」(微信:gprshome201101)。聚焦通信技术与 AI 工程化,每日更新硬核技术解读。
[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
