Clipping 微信公众号

Plugins从入门到精通(中)

by 朱昆鹏mm 原文 ↗
Created: 2026-06-14

公众号名称:朱昆鹏AI手记

作者名称:朱昆鹏mm

发布时间:2026-05-25 15:21

一.前言

《Plugins 从入门到精通》中篇来了,咱们继续

  • 上篇:讲解Plugins基础概念、目录结构和基本使用
  • 中篇(当前阅读):讲解Plugins 的 manifest 完整字段、Marketplace 机制和高级配置
  • 下篇:从源码角度来补充理解Plugins 的加载、缓存与运行机制

上篇我们讲了 Plugin 的”骨架”——目录怎么放、 plugin.json 长啥样、Marketplace 是什么 中篇我们要往里塞”血肉”——每一个字段到底怎么用,怎么写一个完整可用的插件


二.plugin.json 完整字段详解

上篇我们只列出了几个常用字段,那只是”皮”,真正发挥威力靠的是后面这些”内功”

根据源码 src/utils/plugins/schemas.ts 里的 PluginManifestSchemaplugin.json 一共支持 元数据 + 9 大类配置

1.元数据字段

字段类型必填说明
namestring插件名,kebab-case,不允许空格
versionstringsemver 版本(1.2.3)
descriptionstring简介
authorobject{ name, email?, url?}
homepagestring必须是合法 URL
repositorystring源码仓库地址
licensestringSPDX 标识(MIT / Apache-2.0)
keywordsarray关键字数组,用于市场检索
dependenciesarray依赖的其他插件(apt 风格)

这一部分和 NPM 的 package.json 几乎一一对应,写起来不会陌生

2.commands —— 自定义斜杠命令

最常用的扩展点 默认情况下,插件目录下的 commands/ 子目录里的 .md 文件会被自动识别为命令

方式一:默认目录(什么都不用配)

my-plugin/
└── commands/
├── deploy.md       →/my-plugin:deploy
└── format.md       →/my-plugin:format

方式二:在 manifest 中显式声明额外路径

{
"name":"my-plugin",
"commands":"./extra/extra-cmd.md"
}

支持三种格式:

  1. 单个路径"./extra-cmd.md"
  2. 数组["./cmd-a.md","./cmd-b.md"]
  3. 对象映射(推荐,可以加丰富元信息): json "commands":{"about":{"source":"./README.md","description":"查看插件介绍","argumentHint":"[版本号]","model":"haiku","allowedTools":["Read","Bash"]}}

对象映射的好处是,每个命令可以单独指定默认模型参数提示允许工具

命名规则:插件名 + ”:” + 命令名 → /:比如插件 dev-tools 里的 deploy.md 会变成 /dev-tools:deploy

3.agents —— 自定义 AI 代理

代理(Agent)是 Claude Code 里”子 AI”的概念 每个 agent 是一个 .md 文件,定义专门干一件事的小助手

my-plugin/
└── agents/
└── code-reviewer.md

也可以在 manifest 显式声明:

{
"agents":["./agents/special-agent.md"]
}

加载后,AI 在对话中可以通过 Task tool 调用 agent 委托子任务

4.skills —— 插件附带的 Skills

Plugin 可以打包 Skills,命名格式 :

my-plugin/
└── skills/
├── code-review/
│   └── SKILL.md       →/my-plugin:code-review
└── deploy-check/
└── SKILL.md       →/my-plugin:deploy-check

也可以在 manifest 指定额外的 skills 目录:

{
"skills":["./extra-skills"]
}

Skills 的详细写法可以看《Skills 从入门到精通》三部曲

5.hooks —— 生命周期钩子

这是 Plugin 最强大的能力之一 hook 可以让你在 Claude 执行某个操作的前后自动跑你的脚本

默认目录hooks/hooks.json

{
"description":"代码提交前自动跑 lint",
"hooks":{
"PreToolUse":[
{
"matcher":"Bash",
"hooks":[
{
"type":"command",
"command":"${CLAUDE_PLUGIN_ROOT}/scripts/lint.sh"
}
]
}
]
}
}

根据源码 src/utils/plugins/loadPluginHooks.ts,目前支持的 hook 事件多达 29 种

事件触发时机
PreToolUse工具执行前
PostToolUse工具执行后
PostToolUseFailure工具执行失败后
PermissionDenied权限被拒绝
PermissionRequest权限请求时
Notification通知触发
UserPromptSubmit用户提交提问
SessionStart会话开始
SessionEnd会话结束
Stop会话停止
StopFailure停止失败
SubagentStart子代理启动
SubagentStop子代理停止
PreCompact上下文压缩前
PostCompact上下文压缩后
Setup初始化
TeammateIdle队友空闲
TaskCreated任务创建
TaskCompleted任务完成
Elicitation信息征询
ConfigChange配置变更
WorktreeCreateWorktree 创建
WorktreeRemoveWorktree 移除
InstructionsLoaded指令加载
CwdChanged工作目录变更
FileChanged文件变更

是不是有点眼花?记不住没关系,常用的就 4 个

  • PreToolUse —— 工具执行前(最常用,比如拦截危险命令)
  • PostToolUse —— 工具执行后(最常用,比如自动格式化)
  • SessionStart —— 启动时(注入欢迎信息、环境检查)
  • Stop —— 结束时(清理、审计)

6.mcpServers —— MCP 服务器

MCP(Model Context Protocol)是让 AI 调用外部工具的协议 插件可以打包自己的 MCP 服务器

{
"mcpServers":{
"my-mcp":{
"command":"node",
"args":["${CLAUDE_PLUGIN_ROOT}/server/index.js"],
"env":{
"API_KEY":"${user_config.api_key}"
}
}
}
}

也支持以下几种来源:

格式说明
"./mcp.json"引用外部 JSON 配置文件
"./bundle.mcpb"引用 MCPB 打包文件
{"server-name":{...}}内联配置
[...]数组形式,混合多种来源

注意默认情况下 .mcp.json 文件也会被自动加载,不写 manifest 也行

7.lspServers —— LSP 语言服务器

LSP(Language Server Protocol)让 AI 像 IDE 一样能做代码补全和跳转

{
"lspServers":{
"my-language":{
"command":"my-lsp-server",
"args":["--stdio"],
"extensionToLanguage":{
".myext":"my-language"
},
"transport":"stdio"
}
}
}

支持 stdiosocket 两种通信方式

8.outputStyles —— 输出风格

可以定义 AI 输出的风格 比如让 AI 用”简洁版”或者”详细版”回答

my-plugin/
└── output-styles/
├── concise.md      # 简洁风格
└── verbose.md      # 详细风格

9.userConfig —— 用户配置

这是一个特别有用的字段 它允许插件作者声明”我需要用户提供哪些信息”,安装时会弹窗让用户填

{
"userConfig":{
"api_key":{
"type":"string",
"title":"API 密钥",
"description":"用于访问 XXX 服务的 API Key",
"required":true,
"sensitive":true
},
"timeout":{
"type":"number",
"title":"超时时间",
"description":"请求超时秒数",
"default":30,
"min":1,
"max":300
},
"enable_log":{
"type":"boolean",
"title":"启用日志",
"default":false
},
"workspace_dir":{
"type":"directory",
"title":"工作目录"
}
}
}

支持的类型有 5 种:

  • string —— 字符串(支持 multiple:true 开启数组)
  • number —— 数字(可指定 min / max
  • boolean —— 布尔值
  • directory —— 目录路径
  • file —— 文件路径

重点:sensitive 字段

如果一个配置标记了 "sensitive":true

  • 输入时自动遮罩显示
  • 存储到安全存储(macOS keychain / .credentials.json),不会进入 settings.json
  • 在 Skill / Agent 内容中不会展开(避免敏感信息进入模型上下文)

这一招让插件安全地接入 API Key变得非常优雅

怎么在插件里读取用户配置?

通过 ${user_config.KEY} 模板变量,可以在以下地方使用:

  • MCP 服务器的 command / args / env
  • LSP 服务器配置
  • Hook 命令
  • Skill / Agent 内容(但 sensitive 字段会被屏蔽)

10.channels —— IM 频道接入

这是一个比较新的字段,让插件可以注册自己为”消息频道” 比如 Telegram、Slack、飞书的 IM 接入

{
"channels":[
{
"server":"my-telegram-mcp",
"displayName":"Telegram",
"userConfig":{
"bot_token":{"type":"string","title":"Bot Token","sensitive":true},
"owner_id":{"type":"string","title":"Owner ID"}
}
}
]
}

server 必须指向 manifest 里 mcpServers 中已声明的某个 MCP 服务器

11.settings —— 注入设置

允许插件合并一些设置到 Claude Code 的设置体系中 但是出于安全考虑,目前只允许 agent 这一个白名单字段


三.模板变量

写插件经常会用到”动态路径”,比如指向插件自己的脚本 根据源码 src/utils/plugins/pluginOptionsStorage.ts,Plugin 提供了 3 类模板变量:

1.${CLAUDE_PLUGIN_ROOT}

插件的安装目录(版本化路径)

# 比如某个插件实际安装在
~/.claude/plugins/cache/my-market/my-plugin/1.2.0/
# 那么 ${CLAUDE_PLUGIN_ROOT} 就指向上面这个目录

⚠️ 注意:这个路径会在插件更新时变化(每次更新创建新的版本目录),所以不要把用户数据放到这里

2.${CLAUDE_PLUGIN_DATA}

插件的持久化数据目录

~/.claude/plugins/data//

特点:

  • 在插件更新时保持不变
  • 只在最后一次卸载时才删除
  • 用来存配置、缓存、用户数据

3.${user_config.KEY}

用户配置变量,对应 manifest 里 userConfig 声明的字段

"command":"${CLAUDE_PLUGIN_ROOT}/scripts/run.sh",
"env":{
"API_KEY":"${user_config.api_key}",
"DATA_DIR":"${CLAUDE_PLUGIN_DATA}"
}

4.${VAR} —— 一般环境变量

任何标准的环境变量都可以用 ${VAR} 引用 解析顺序是:plugin 变量优先 → user_config 变量 → 系统环境变量


四.Marketplace 详解

上篇我们简单提了 Marketplace,这里我们深入讲一下

1.官方 Marketplace 一览

根据源码 src/utils/plugins/schemas.ts 里的 ALLOWED_OFFICIAL_MARKETPLACE_NAMES,Anthropic 维护着 8 个官方市场

名称用途
claude-code-marketplaceClaude Code 通用市场
claude-code-pluginsClaude Code 插件市场
claude-plugins-official官方插件
anthropic-marketplaceAnthropic 综合市场
anthropic-pluginsAnthropic 插件
agent-skillsAgent 技能市场
life-sciences生命科学领域
knowledge-work-plugins知识工作市场

这些名字是保留字,只有来自 github.com/anthropics/ 的仓库才能使用,防止第三方仿冒

2.marketplace.json 完整结构

{
"name":"my-marketplace",
"owner":{
"name":"团队名称",
"email":"contact@example.com",
"url":"https://example.com"
},
"metadata":{
"description":"我们团队的内部插件市场",
"version":"1.0.0",
"pluginRoot":"./plugins"
},
"plugins":[
{
"name":"java-best-practices",
"source":"./plugins/java-best-practices",
"description":"Java 开发最佳实践",
"category":"language",
"tags":["java","backend","best-practices"]
},
{
"name":"jira-mcp",
"source":{
"source":"npm",
"package":"@my-org/jira-mcp",
"version":"^1.0.0"
},
"category":"integration"
},
{
"name":"shared-tools",
"source":{
"source":"github",
"repo":"my-org/shared-tools",
"ref":"v2.1.0"
}
}
],
"allowCrossMarketplaceDependenciesOn":["other-market"],
"forceRemoveDeletedPlugins":true
}

3.插件来源 (PluginSource) 6 种类型

根据源码 PluginSourceSchema,每个插件可以来自 6 个地方:

Source配置适用
相对路径"./plugins/foo"同仓库内的插件
github{ source:'github', repo:'owner/repo',ref?, sha?}GitHub 整仓
git{ source:'git', url:'...',ref?, sha?}任意 Git 仓库
git-subdir{ source:'git-subdir', url, path,ref?, sha?}Monorepo 子目录
npm{ source:'npm',package, version?, registry?}NPM 包
pip{ source:'pip',package, version?, registry?}Python 包

亮点: git-subdir

如果你的插件放在一个大 monorepo 的子目录里,用 git-subdir 可以只克隆子目录,省带宽 底层用的是 git sparse-checkout,对超大仓库(比如几个 GB 的)非常友好

4.7 种 Marketplace 来源

上篇也提过,市场本身也支持 7 种来源类型 这里把 7 种全列出来对比:

//1.GitHub仓库(最常用)
{"source":"github","repo":"owner/repo"}
//2.任意Git URL
{"source":"git","url":"https://gitlab.com/x/y.git"}
//3.直接给 JSON URL
{"source":"url","url":"https://x.com/m.json"}
//4. NPM 包(市场分发)
{"source":"npm","package":"@org/marketplace"}
//5.本地文件
{"source":"file","path":"/path/to/marketplace.json"}
//6.本地目录
{"source":"directory","path":"/path/to/dir/"}
//7. settings.json 内联(最骚的)
{
"source":"settings",
"name":"my-inline",
"plugins":[
{"name":"x","source":{...}}
]
}

第 7 种 settings 来源特别有意思——你可以直接在 settings.json 里写一个虚拟市场,不用单独建一个 marketplace.json 文件,特别适合临时尝试

5.插件依赖 dependencies

Plugin 之间可以声明依赖关系,类似 apt 包管理

{
"name":"advanced-deployer",
"dependencies":[
"git-helper",
"docker-tools@official-market"
]
}

依赖规则(根据 dependencyResolver.ts):

  • 裸名(不带 @xxx)会默认从声明插件所在的市场解析
  • @market 的需要跨市场授权
  • 默认禁止跨市场依赖(防止信任泄漏)
  • 想跨市场,需要在根市场 marketplace.json 里写: json "allowCrossMarketplaceDependenciesOn":["other-market"]

依赖采用 apt 风格:仅保证”依赖项存在并启用”,不是模块导入

6.自动更新

根据 pluginAutoupdate.ts,Plugin 系统支持后台自动更新:

  • 默认:官方市场开启自动更新(除了 knowledge-work-plugins
  • 非官方市场默认不自动更新
  • 启动时检查并下载新版本,但需要重启 Claude Code 才生效
  • 用户可以手动开关: bash /plugin marketplace update # 手动更新所有 /plugin marketplace update # 更新指定市场

五.三方插件库推荐

讲完原理,来推荐几个实战中比较有口碑的 Plugin 仓库(注:随着时间推移地址可能变化)

1.官方插件市场

# 添加官方市场
/plugin marketplace add anthropics/claude-plugins-official

里面是 Anthropic 官方维护的一批通用插件,安全有保障,首推

2.Agent Skills

/plugin marketplace add anthropics/agent-skills

更偏向通用 Agent 能力的市场,里面打包了一堆”AI 助理”性质的插件

3.Knowledge Work Plugins

/plugin marketplace add anthropics/knowledge-work-plugins

针对知识工作者(写作、研究、咨询、PM 等)的专项插件市场

4.各社区/团队的插件库

  • Superpowers —— 社区里比较火的一套”超能力”插件
  • gstack —— 一套基于 Plugin 的开发工作流(在本项目代码里可以看到很多 gstack 命令)
  • superclaude / sc: —— Multi-Agent 编排插件包

5.怎么挑插件?

我自己挑插件的几个原则:

  1. 看作者 —— Anthropic 官方 > 知名开源团队 > 个人项目
  2. 看更新频率 —— 三个月以内有提交比较稳妥
  3. 看 issue —— 看看坑多不多,能不能修
  4. 看 manifest 干不干净 —— 有完整的 description、author、homepage 的更靠谱
  5. 看权限范围 —— 含 hooks 的插件优先看 hook 脚本内容,别盲装

六.开发一个完整插件的流程

最后用一个端到端的示例串起本篇所有知识点

假设我们要做一个 git-helper 插件:

  • 提供 /git-helper:status 斜杠命令
  • 在每次会话开始时打印仓库状态
  • 接入一个 git-mcp 服务器
  • 安装时让用户配置一个工作区路径

第一步:建目录

mkdir -p git-helper/{.claude-plugin,commands,hooks,scripts}

第二步:写 plugin.json

{
"name":"git-helper",
"version":"1.0.0",
"description":"智能 Git 助手插件",
"author":{
"name":"你",
"email":"you@example.com"
},
"license":"MIT",
"keywords":["git","vcs","helper"],
"userConfig":{
"workspace":{
"type":"directory",
"title":"工作区路径",
"description":"默认查询的仓库根目录",
"required":true
}
},
"mcpServers":{
"git-mcp":{
"command":"node",
"args":["${CLAUDE_PLUGIN_ROOT}/scripts/git-mcp.js"],
"env":{
"WORKSPACE":"${user_config.workspace}",
"DATA_DIR":"${CLAUDE_PLUGIN_DATA}"
}
}
}
}

第三步:写命令 commands/status.md

---
description:查看 git 仓库状态
allowed-tools:Bash
---
帮我执行`git status`并解释当前仓库的状态

第四步:写 hook hooks/hooks.json

{
"description":"会话开始时打印仓库状态",
"hooks":{
"SessionStart":[
{
"matcher":"*",
"hooks":[
{
"type":"command",
"command":"git -C ${user_config.workspace} status --short"
}
]
}
]
}
}

第五步:验证

/plugin validate ./git-helper

如果 manifest 合法,会输出 ✅

第六步:本地测试

# 启动时加上 --plugin-dir 参数加载本地插件
claude --plugin-dir ./git-helper

测试无误后,把目录推到 GitHub,写一个 marketplace.json 就能让别人安装了


七.结尾

读完本篇,我建议你按这个顺序练手:

  1. 从官方市场装一个真实插件(比如 claude-plugins-official 里随便挑一个),观察它的目录结构
  2. 写一个最简化的 git-helper(按上面流程做)
  3. 试着加一个 PreToolUse hook,拦截一下 Bash 命令
  4. ${user_config.xxx} 接入一个真实的 API Key

下篇我会从源码角度带大家走一遍 Plugin 的”一生”:

  • Plugin 怎么被启动加载? loadAllPlugins 干了啥?
  • Marketplace 是怎么从 GitHub 克隆到本地缓存的?
  • 版本化缓存 ( cache////) 怎么工作?
  • Hooks 怎么从 plugin 注册到全局事件系统?
  • MCP / LSP 服务器怎么被启动?

我们明天再会吧~

往期推荐

Plugins 从入门到精通(上)


内容效果不满意?点此反馈

输入关键词开始搜索