做Claude Code开发有一段时间了,我最大的感受是:单机版的使用很爽,但要真把能力沉淀下来、让团队里的任何人都能用上,还得靠插件化。前几篇教程里我一直在讲怎么调教agent、怎么写skill,但那些都停留在“自己项目里能用”的层面。这一篇直接进入分享环节——把你自己调教好的agent、沉淀出来的技能包,打成一个Claude Code插件,让同事、让社区里的人一条命令就能装进自己的工程。
这篇教程面向的读者有两类:一类是已经上手Claude Code、写过几个自定义指令的人,另一类是刚意识到“配置与能力应该复用”的团队技术负责人。不管哪一类,读完这一篇,你都能交付一个结构完整、可安装、可迭代的插件包。
1. 为什么要用插件分享agent和skills
1.1 复制粘贴式分享的痛点
先说说我走过的弯路。早期共享agent配置,最“原始”的做法是把markdown文件发到群里,或者塞进git仓库的根目录,让同事自己复制。听起来没毛病,但实际使用中全是坑。
第一,文件到底放哪儿没有统一约定。有人放在.claude/agents/下,有人直接丢进项目根目录,还有人把内容贴在会话里让Claude“记一下”。结果就是同一个团队里,大家的agent行为完全不一致,配置文件散落各处,根本没法维护。
第二,依赖关系是隐式的。一个功能完善的agent往往要引用若干skill,而skill里还可能带脚本和参考文档。你复制走agent文件,却忘了复制配套的skill目录,运行的时候频繁报错,排查半天才发现是依赖缺失。
第三,版本混乱。你改进了一个agent提示词,重新发了一版文档,但同事手里还是旧版。尤其是当大家分属不同项目时,同步成本极高,最终又回到“各写各的”状态。
1.2 插件化解决的核心问题
插件机制解决的就是这三件事:结构标准化、依赖打包、版本可追踪。
结构标准化意味着插件自带一套被约定的目录骨架。任何一个符合规范的插件,安装之后agent该出现在哪里、skill的配置入口在哪里、附带脚本与文档在哪,都是确定的。使用者不需要记忆,也不需要阅读冗长的README。
依赖打包则更直接。Claude Code插件把所有agent、skills、参考文件、脚本放在同一个插件目录里,由插件清单统一声明。安装一个插件,等于把整套能力原子化地装进去,不存在“少了某个skill”的问题——因为清单里没有声明的文件,本来就不会被加载。
版本可追踪意味着每次分发的是一个带版本号的插件包。团队内部可以通过更新插件来同步能力,不用再靠口口相传。这也是我后来极力向团队推行插件化的根本原因。
注意力放在“结构”和“打包”上,而不是单个markdown文件写了什么——这才是分享agent和skills的正确姿势。
2. 插件的基本结构:目录与两类核心资产
2.1 一个标准插件的目录骨架
我开工一个插件时,会用下面这个骨架起步,原则是“先搭目录,再填内容”:
my-plugin/ ├── .claude-plugin/ │ └── plugin.json ├── agents/ │ ├── code-reviewer.md │ └── log-analyzer.md ├── skills/ │ ├── dependency-scan/ │ │ ├── SKILL.md │ │ ├── scripts/ │ │ │ └── scan.py │ │ └── references/ │ │ └── deps-format.md │ └── convention-check/ │ ├── SKILL.md │ └── scripts/ │ └── check.sh └── README.md这个骨架有三层含义。.claude-plugin/plugin.json是插件的身份入口,Claude Code扫描插件时首先读它。agents/目录放agent定义文件,也就是“角色说明书”。skills/目录下面是一个个技能包,每个技能包有自己的子目录,里面是技能定义文件和配套资源。
这么组织对维护者非常友好:你不需要翻遍整个项目才能找到“插件的入口在哪里”“哪些技能是有效的”,看目录结构就能明白。
2.2 agent与skills的本质区别
很多人分不清agent和skill,其实两者的定位非常清晰。
agent做的事情是“定义角色与边界”,它告诉大模型:在什么场景下、以什么身份、用什么风格、按什么流程来工作。举例说,一个“日志分析专家”agent,它的核心资产是一大段高质量指令,告诉Claude“收到日志先分级、先提取关键行、不臆测根因”。它不需要附带任何可执行脚本。
skill做的事情则是“把某类操作变成可复用的工具包”,它除了包含给大模型的指令文本之外,还常常附带脚本、模板、参考文档。比如“依赖安全扫描”这个skill,里面有扫描脚本、输出格式模板、查阅文档。大模型遇到未被定义过的问题时,可以从skill里检索知识与工具。
两者在插件里是一对搭档:agent负责“像专家一样思考”,skill负责“像工具一样做事”。一个agent可以引用多个skill,而一个skill也可以被多个agent复用。
2.3 插件清单文件plugin.json的编写
插件清单是整个插件的“总纲”,职责是声明元信息和加载路径。我一个最小示例通常长这样:
{ "name": "project-assistant", "version": "0.1.0", "description": "项目开发助手,内置代码评审与日志分析能力", "agents": [ "agents/code-reviewer.md", "agents/log-analyzer.md" ], "skills": [ "skills/dependency-scan/SKILL.md", "skills/convention-check/SKILL.md" ] }这里有一点值得强调:路径要写“从插件根目录出发的相对路径”,不要写绝对路径,也不要写在插件之外的文件。踩过坑的人都知道,路径写错后插件加载静默失败,排错非常痛苦。
version字段建议遵循语义化版本,每次有破坏性变更就升主版本,增加新能力升次版本,改个文案升补丁版本。这对后续更新追踪很有帮助。
3. 从零创建第一个插件:核心步骤与配置
3.1 初始化插件骨架
我常用一个简单的初始化命令创建目录。这个命令不做任何平台假设,只要你本地环境支持shell即可:
mkdir -p my-plugin/.claude-plugin \ my-plugin/agents \ my-plugin/skills/demo-skill/scripts \ my-plugin/skills/demo-skill/references然后手动创建plugin.json,把2.3节的内容填进去,再准备一个最简agent和一个最简skill。这个阶段的目标不是写完整能力,而是跑通“插件能被加载、agent能被调用、skill能被触发”的最小闭环。
3.2 写一个agent:角色描述与行为边界
agent文件就是一个markdown文档,通常在文件头部用frontmatter声明基础信息,正文是完整的行为指令。我沉淀出来一个比较健壮的模板:
--- name: log-analyzer description: 日志分析专家。当用户提到"日志分析""排查报错""看日志""分析崩溃"时自动激活。 --- # 角色说明 你是一位资深的日志分析专家,擅长从混乱的日志中提取有用信息、定位根因。 # 工作流程 1. 先要求用户提供日志来源、应用模块、时间范围,确认上下文。 2. 按 ERROR、WARN、INFO 排序,筛选关键行。 3. 分析根因时,必须引用具体日志行作为证据,禁止臆测。 4. 给出解决方案时,同时给出预防此类问题的建议。 # 行为边界 - 你不负责修改业务代码,只负责定位问题与给出建议。 - 对无法确认的根因,明确标注“需要进一步验证”,不要强行下结论。这里有两个容易踩的坑。
第一,description写得太泛。比如写“日志分析”,模型可能永远不知道该在什么时候激活这个agent,因为触发条件不够清晰。恰当的做法是枚举常见的用户说法。
第二,正文里没有明确的行为边界。没有边界的agent,会频繁越权去做别的事情,导致输出不可控。我在实践中发现,给agent立几条明确的“不做什么”,往往比告诉它“要做什么”更重要。
3.3 写一个skill:技能定义、触发词与配套脚本
skill文件的标准形态是SKILL.md,同样有frontmatter和正文。正文里最重要的是把“什么时候用”和“怎么用”写清楚。
看一个依赖扫描skill的骨架:
--- name: dependency-scan description: 扫描项目依赖版本与过期情况。触发词:检查依赖、依赖版本、deps scan。 --- # Dependency Scan 当用户需要检查项目中依赖是否过期,或多版本冲突时,执行以下流程: 1. 定位项目的依赖清单文件(如 package.json、requirements.txt、go.mod)。 2. 调用 scripts/scan.py 解析清单文件。 3. 输出过期依赖、当前使用版本、最新的可用版本。 4. 对存在安全风险的依赖,给出升级建议。 ## 使用示例 “帮我看下依赖有没有需要升级的” “这个项目里 lodash 版本太老了,扫一下”配套脚本的意义在于:把那些大模型不擅长的高精度操作(比如解析复杂文件格式、做版本号比较)交给确定性代码,避免模型“估算”出错。我这里的scan.py就负责解析依赖清单,并输出一个结构化markdown表格。
脚本写完之后,还要在SKILL.md里给出调用方式。模型执行技能时,看到的是“调用scripts/scan.py”这个命令,所以脚本与文档的联动关系必须写清楚。
4. 打包、安装与分发
4.1 三种分发方案对比
插件写好了,接下来就是让它在别人机器上跑。我实践下来常用的分发方案有三种。
第一种,丢进git仓库。这是团队内部最常见的做法。你把插件放在独立仓库中,同事clone之后在项目配置里声明插件路径。优点是更新方便,git pull即可得到最新版本。缺点是依赖使用者有git基础,零基础的人可能会卡在这一步。
第二种,发布为归档压缩包。把整个插件目录打成tar或zip,通过网盘或聊天工具分发,对方下载后解压使用。优点是门槛低,缺点是更新起来全靠人工再发一次包。
第三种,上传到团队内部插件索引。如果你的团队搭建了插件仓库或索引目录,提交插件后其他人能通过搜索安装。这是最省心的做法,但需要额外的基建投入。
三种方案不冲突。我在团队里的实践是:仓库托管为主、压缩包兜底,插件索引作为长期目标逐步建设。
4.2 安装到项目的两种方式
Claude Code中的插件安装,本质是告诉“主程序”到哪里去加载这个插件。实践中主要分项目级安装和会话级加载。
项目级安装,是在项目的配置层面登记插件路径,之后每次在这个项目里打开Claude Code都会自动加载。操作思路是编辑项目配置文件,在插件列表中追加本地路径或仓库地址。
会话级加载,则是临时在当前会话里声明这个插件,只对当前会话生效。这在调试阶段很有用——你改一个文件,立刻重新加载验证,不用反复退开会话。
如果你正在开发插件,我的建议是先走会话级加载调试,每次只改一个文件,确认加载无报错后,再正式登记到项目配置里。
4.3 命名、版本与文档管理
分享出来的插件就是你的“作品”,命名和文档决定了别人第一印象和使用意愿。
命名建议用短横线分隔、小写的格式,比如dependency-scan、frontend-reviewer,不要用空格,也不要用中文。原因很简单,插件名会出现在命令、路径和日志里,特殊字符只会带来无谓的麻烦。
README一定要写清楚三件事:这个插件解决什么问题、怎么安装、有哪些agent和skill都怎么触发。有一次我搞了个“看起来很美”的插件,结果同事装完不知道有哪些agent可用,又跑回来问我。后来我学乖了,README开头放一张“能力清单”表格,把所有技能和触发方式列出来,问题直接减半。
5. 实战:把日志分析agent和扫描skill一起打包
5.1 这个插件解决什么场景
我用一个自己折腾过的案例,把整个流程串起来。场景是这样的:团队里后端服务日志量大、格式五花八门,每次线上问题排查都要人肉处理。我想做一个“日志定位与依赖风险双重助手”,一次性把agent和skill都封装进插件。
这个插件的agent是日志分析专家,负责在会话中定位、分级、推断根因;skill则负责做确定性分析——解析日志采样文件产出统计摘要。两者配合,模型负责“聪明的部分”,脚本负责“可靠的部分”。
5.2 完整实现过程
先搭目录:
mkdir -p log-helper/.claude-plugin \ log-helper/agents \ log-helper/skills/log-sampler/scripts然后是plugin.json:
{ "name": "log-helper", "version": "0.1.0", "description": "日志分析与采样排查助手", "agents": ["agents/log-analyzer.md"], "skills": ["skills/log-sampler/SKILL.md"] }agent文件按3.2节的模板写。skill这里再展开一下:log-sampler技能的核心是从日志文件里按级别提取样本并生成摘要。它的SKILL.md正文包含:
- 触发条件:用户要求分析日志文件、采样、统计级别分布
- 执行步骤:解析日志路径 → 运行scripts/summarize.py → 返回统计摘要
- 输出格式:按级别分组,附带行号与代表性日志行
对应的summarize.py逻辑大约是:读取文件 → 正则匹配日志级别 → 按级别计数 → 输出markdown表格与若干示例行。脚本不需要多复杂,做到“输入一个文件路径,输出结构化摘要”即可。
5.3 验证流程与测试要点
插件做好后,我习惯按三个步骤自测。
第一步,检查路径。打开项目配置,加载插件目录,确认没有路径解析错误,agent和skill均被识别。
第二步,验证agent激活。新开一个会话,说“帮我看看这段日志是什么问题”,确认log-analyzer被激活,且回答过程中遵循了分级和证据逻辑。
第三步,验证skill调用。请求分析logs/error.log文件,观察Claude是否主动调用log-sampler技能,脚本是否输出正确摘要。
这轮实测下来,我发现最常见的失败点是“agent识别成功,但不会调用skill”。原因几乎都是SKILL.md里的description缺少触发词,模型不知道什么时候该用技能。把触发词补齐后,问题迎刃而解。
6. 常见问题与排查技巧实录
下面这些坑,都是我在多次分发插件的过程中真实碰到的,整理成速查表供参考。
| 现象 | 原因 | 排查与解法 |
|---|---|---|
| 插件加载后没有新增agent | plugin.json路径写错或agent文件缺少frontmatter | 逐项核对路径,确认以插件根目录为基准;检查frontmatter中的name字段 |
| agent能激活但不调用skill | skill描述中的触发词不匹配 | 在SKILL.md的description中补充用户常见说法,重新加载插件会话 |
| 技能执行时找不到脚本 | SKILL.md里的脚本路径写错 | 统一使用相对插件根目录的路径,脚本内不再拼接绝对路径 |
| 安装后别人复现的行为与你本地不一致 | 插件版本没锁 | 确认分发的是带版本信息的插件;README写明当前版本与变更记录 |
| 插件中包含敏感信息 | 打包时无意带出本地密钥或内网地址 | 打包前先运行“敏感信息扫描”,检查.env、token、IP段等内容 |
关于安全问题多说一句:插件本质上是代码与提示词的集合,它的边界能力取决于运行环境。分发时务必自查内容,不要包含任何凭据或内网细节;使用别人分享的插件时,先把SKILL.md全文读一遍,确认脚本没有可疑行为再加载。这条习惯应该像“用第三方依赖前先看两眼源码”一样自然。
还有一个提高调试效率的小技巧:改完插件文件后,不要反复开新会话去试,而是先检查日志输出里有没有“plugin loaded”这样的关键行。看到加载成功提示后再进入功能测试,能省掉大量无效等待。
最后再分享一点个人体会。Claude Code的插件化能力真正释放价值的地方,是它把“个人调教”变成了“团队资产”。你一个人的agent再聪明,作用也局限于自己的终端;一旦打包成插件分发,它就能成为整个团队的效率底座。所以我在写完每个新技能之后,都会问自己一句:这个能力值不值得被更多的人以插件的形式复用?如果值得,花半小时整理成插件,回报远远大于成本。