
1. 我为什么最终把手写的技能说明全部改成了插件从“每次重讲一遍”到“复制即生效”先说一个让我彻底转向插件的场景。有一段时间我给团队搭了一套代码评审流程要求 Claude Code 在每次提交 MR 前按固定顺序检查先看变更范围再找潜在副作用最后给分级意见。这套规则我写在一个很长的CLAUDE.md里当时觉得挺完善。结果换到另一个项目时同事直接复制了那份配置却发现评审风格完全不对——因为那个项目的技术栈、目录结构和发布节奏都不一样。我又得花十几分钟手工调整路径、补充规则、删掉不相关的段落。更麻烦的是如果评审规则本身有改进比如新增一条“禁止在公共函数里抛裸错误”所有项目里的配置都要同步改一遍。插件出现以后这个问题变成了“打包已定义的 AI 能力”我只需要把评审流程、命令、辅助规则、示例输出全部塞进一个插件目录然后在项目里启用它。新项目接入时不用重新讲一遍上下文也不用复制一堆散落的配置片段。启用插件后这个能力就像内置在项目里一样我可以直接说“按团队评审规则检查这次改动”它会自动带上我提前定义好的检查步骤和输出格式。这一篇主要面向已经用过 Claude Code、熟悉/commands、会维护CLAUDE.md的开发者。如果你还在手工搬运提示词或者团队里每次新人都要“重新培训”一遍 AI 的使用方式那插件的价值会非常明显。它不是一个神秘的黑盒本质上是把“提示词 规则文件 子代理 脚本钩子”组合成一个独立目录然后交给 Claude Code 统一加载。从关系上看插件不是替代 Slash Command也不是替代 Agent而是它们的容器插件里面可以放多个命令、多个 Agent、多份规则文档。更准确地说插件解决的是“项目管理配置的复用问题”——以前你分享给同事的是一段话、一个文件现在分享的是一个文件夹这个文件夹到哪都能按原样工作包括里面的目录结构、参考示例、约束条件甚至触发时机。2. 解剖一个插件目录搞清楚每层文件到底在定义什么我们先不看官方文档的长篇大论直接拆一个插件的目录结构。以我维护的“前端代码评审插件”为例它在磁盘上长这样code-review-plugin/ ├── .claude-plugin/ │ └── plugin.json ├── SKILL.md ├── AGENTS.md ├── commands/ │ ├── review.md │ └── review-strict.md ├── agents/ │ └── dependency-checker.md ├── hooks/ │ └── pre-commit_review.js ├── examples/ │ ├── good-review.md │ └── bad-review.md └── assets/ └── checklist.csv2.1 顶层布局SKILL.md、AGENTS.md 和 .claude 目录如何协同plugin.json是插件的身份证里面声明插件名称、描述、版本、最低 Claude Code 版本以及插件自身允许访问的权限范围。我的习惯是把描述写得很具体比如“前端 MR 评审规则集合包含标准评审和严格评审两档”而不是笼统地写“代码评审工具”。因为当多个插件同时挂在一个项目里时Claude Code 需要根据描述来判断什么时候该自动调用它。SKILL.md是核心技能定义文件。它和 AI 能力的关系类比的话就像岗位说明书说明这件事在什么场景下做、大致分几步、最终产出什么格式。Claude Code 在读取 SKILL 时不只会看到这一份文件还会扫描examples/和assets/目录把示例和辅助素材一起作为上下文。这一点很关键很多新手只写几行“你应该这么做”但真正让 AI 表现稳定的是给它看几个“做得好的例子”和“做得差的例子”。AGENTS.md则是给项目里运行的多个 Agent 看的公共约定。比如我规定“所有涉及依赖升级的判断必须先调用dependency-checker子代理”这条规则写在AGENTS.md里插件内的每个 Agent 就都会遵守。它和CLAUDE.md的区别是作用域CLAUDE.md是整个项目的主规则AGENTS.md更偏向某个 Agent 集合的专属约定插件内部还能有自己的嵌套规则。2.2 为什么我坚持把示例和模板放进插件而不是只写提示词有一段时间我只写提示词比如“输出要简洁、要有分级、要指出风险”。听起来像那么回事但真正用的时候会发现输出飘忽不定。后来我把评审案例放进去以后效果立刻不一样了。原因很简单大模型的 few-shot 依赖示例而不是依赖形容词。你说“要简洁”它不知道简洁到什么程度你给它看一份只写三行结论的样例它就会照着这个尺度来。所以我现在做插件的固定套路是每个能力单元至少带一个正例和一个反例。比如good-review.md写的是信息密度高、分级的评审意见bad-review.md写的是啰嗦、没有优先级、通篇空话的评审意见。在SKILL.md里我会加一句话“参考 examples 中的两种风格回复必须接近 good-review 的状态”。这对输出稳定性是非常明显的提升。另外assets/checklist.csv会被 Claude Code 当成结构化数据读取用来逐项打分避免遗漏。hooks目录里的脚本给了插件处理“事件”的能力。比如团队要求在 git commit 之前自动跑一遍评审我可以在hooks/pre-commit_review.js里写逻辑先检查是否有未提交的变更再调用主模型生成评审把结果写入指定文件。hook 的粒度可以到项目也可以到插件内置关键是它让插件的“AI 能力”不只有被动问答还能主动参与开发流程。3. 手把手做一个“代码评审插件”从建目录到跨项目生效这一节我们直接做一个可以把 MR 评审能力打包进任何项目的插件。我的目标是在任何项目里启用这个插件后我只要输入“评审当前变更”它就能按固定流程输出结构化结果。3.1 创建插件骨架与评审流程定义第一步建目录和身份证文件。我在某个专门放插件的目录~/.claude/plugins/下建了项目文件内容如下{ name: code-review-rules, version: 0.3.0, description: 用于前端仓库 MR 评审的规则集包含标准评审、严格评审和依赖检查三类能力, min_claude_version: 2.0 }接着写SKILL.md。我会把评审的完整路径写得非常明确# 前端 MR 评审 当我要求“评审当前变更”“检查这次 MR”或“按照团队流程 review”时使用这个技能。 ## 适用场景 - 需要审查代码变更的副作用时 - MR 合入前需要给出分级结论时 - 变更涉及依赖升级、公共函数改动时 ## 评审流程 1. 先运行 git diff 获取当前未提交或指定范围内的变更。 2. 把变更的文件按影响范围分为三类核心业务逻辑、工具函数、样式与配置。 3. 对核心业务逻辑逐行检查是否存在未处理的空值、是否存在隐式类型转换、是否修改了共享状态。 4. 对工具函数检查调用方确认没有破坏原有接口。 5. 输出分级结论P0 必须修改P1 建议修改P2 可忽略。 ## 输出格式 结论段落必须包含 - 变更概览本次改动涉及文件数、新增行数、删除行数。 - 风险列表按 P0/P1/P2 分组每组至少给出文件路径和行号。 - 最终结论P0 数量为 0 时判定为“可以合入”否则为“需要修改”。这个流程不是凭空拍脑袋写的它对应的是我们团队实际发生过的几次线上事故。第 1 条里有降低难度的考虑让模型先跑git diff再思考避免它基于模糊记忆去猜变更内容。第 3 条和第 4 条是针对前端仓库里最常见的两类问题——空指针和隐式类型转换如果你们后端仓库多可以换成数据一致性和并发安全。重点是流程必须拆到“模型不需要自己决定下一步做什么”的程度。3.2 挂载、绑定到项目和首次运行验证插件目录建好之后要让它被 Claude Code 识别。我通常在一个已有仓库的根目录下执行claude plugin add ~/.claude/plugins/code-review-rules这会把插件注册到当前项目同时生成一个项目级别的.claude/settings.json来记录启用列表。如果想全局启用让所有项目都能用它可以不加项目参数或使用全局配置。我的建议是务必先按项目启用确认没有副作用再考虑全局因为全局插件数量一多会明显影响模型在无关任务上的注意力。首次验证我选择在一个小型仓库里做而不是直接拿生产仓库测试。我会故意制造一个包含明显问题的改动比如让一个可能为undefined的值直接参与字符串拼接然后输入按 code-review-rules 评审当前变更重点观察三件事第一它有没有真的执行git diff第二问题列表里是否抓到了我刚才埋的那个问题第三输出里有没有 P0/P1/P2 分组。第一次跑完大概率会遇到“流程对但输出格式不对”的情况。比如模型把结论放到了最后而不是开头或者风险列表只写了文件路径没写行号。解决办法不是改提示词里的形容词而是把examples/good-review.md写得再具体一点甚至给一个完全符合格式的两行样例。3.3 给插件加配置和上下文开关避免评审风格“一刀切”业务团队和基础架构团队对评审严格程度的预期完全不同。我见过最尴尬的场景是同一个插件在业务仓库里因为“改了工具函数但没更新类型定义”被打回而那个仓库的实际发版节奏是每天多次过度严格的评审只会被绕过。所以我在插件里加了一个配置概念环境变量或settings.json里声明REVIEW_MODE这个值决定调用哪个命令。我在commands/review.md和commands/review-strict.md两个文件的 frontmatter 里分别写--- name: review description: 标准评审模式适合日常迭代 mode: standard --- --- name: review-strict description: 严格评审模式适合版本发布前 mode: strict ---SKILL.md里再写一句判断逻辑如果当前分支是release/*或master则优先选择review-strict其他分支默认review。这样插件是一个能力是两个不会因为规则硬编码而让一部分项目觉得太重。配置项的粒度不需要设计得特别精细我建议保持在两到三档。超过三档以后模型在判断“当前属于哪个档位”时反而容易出错而且维护成本会明显上升。手动加一个开关的成本很低但收益很大它让插件能跨团队使用而不是只适配某一个固定流程。4. 插件的分发与团队落地我踩过的共享协作坑插件写出来以后最核心的问题是“怎么让别人用起来”。一开始我把整个目录压缩成 zip 发给同事解压后手动执行claude plugin add。这种方式在小团队里能用但版本一多就失控了。后来某技术小组教了我一套更稳的共享方式我整理成了四个步骤。4.1 用 Git 仓库分发插件时最容易翻车的两点把插件目录当作一个独立 Git 仓库维护是比发 zip 好得多的方式。具体操作是在插件仓库根目录打上语义化版本标签然后让使用方通过claude plugin add githttps://某个内网仓库/code-review-rules.git来添加。这样做的好处是升级方便插件作者修了一个 bug 后使用者只要重新拉取版本就能获得修复不需要手动解压覆盖。但这套方式里我踩过两个坑。第一个坑是插件仓库里不能有和宿主仓库无关的依赖安装逻辑。有人为了在 hook 里调eslint直接在插件仓库里放了package.json结果使用方执行插件时经常报依赖缺失。正确做法是让插件在运行前检查宿主环境里有没有对应命令没有就给提示而不是自动安装。插件应该轻装上阵把环境准备留给宿主项目。第二个坑和路径有关。插件里引用文件时我一开始写了绝对路径比如/home/某同事/plugins/code-review-rules/examples/good-review.md。这路径在我机器上能用换一个人就废了。后来全部改成相对路径以插件根目录为基准。同时在SKILL.md里明确写“示例文件与插件目录同级不要尝试在工作区里查找”。这样即使插件被安装在全局目录下路径也不会错。通过 Git 分发还有一个不可忽视的好处可以看变更历史。团队里有人改了我的评审规则我能通过提交记录看到他为什么改而不是拿到一份新压缩包后只能猜。改出问题也能git diff回退。这一点对于需要长期维护的插件价值非常大。4.2 团队内部如何维护插件版本与更新通知插件被多个项目引用后更新节奏要谨慎。我见过一个同事更新了插件主版本结果所有使用方项目在第二天全部报错原因是新版本要求min_claude_version更高而有的同事还没升级。为了防止这类问题我定了一条内部规则插件主版本号变化时必须同时更新description提醒使用方注意破坏性变更同时在发布说明里明确写出“升级前先备份宿主项目的.claude/settings.json”。更好的做法是设置一个插件市场或者内部索引文件。市场没有必要做得多复杂一个 Markdown 文件即可里面列出插件名、版本、导入命令、适用场景。团队里的同事只要看这个清单就知道该装什么不需要私下问来问去。我做了一个简单的marketplace.md放在内部知识库里效果非常好新同事按图索骥即可。至于什么时候该把通用能力抽成插件、什么时候只写项目内配置我的判断标准是“是否超过一个项目需要并且规则变化频率不高”。如果两个项目的评审目标完全不同把两份规则强行塞进一个插件反而增加了判断成本但如果规则只是细节差异比如文件命名风格就可以通过配置项区分。一个插件只解决一个明确的问题比做一个“万能插件”稳定得多。5. 调试插件的完整思路从“没生效”到“结果不对”插件不生效的时候大多数人的第一反应是删掉重装。这能解决一部分问题但很难定位真凶。我调试插件的思路分几步先确认插件有没有被加载再确认加载的是不是最新版本最后确认规则有没有被宿主项目覆盖。按这个顺序排查基本不会漏。5.1 插件未被加载目录命名和激活方式的排查链路插件注册到项目后并不代表它一定会被主动使用。Claude Code 只有在匹配到触发条件时才会把插件内容放进上下文。我调试时第一步会检查.claude/settings.json里是否真的出现了这个插件的名字。如果出现了但没生效我会在会话里直接问我能使用哪些插件它会列出当前上下文里可见的插件。如果列表中出现了我的插件但执行命令时报“未定义”那问题多半出在命令文件本身比如 frontmatter 里的name与调用名不一致或者命令文件放错了目录。我遇到过最隐蔽的问题是文件名大小写某个命令文件叫Review.md而plugin.json里写的小写review结果调用时完全匹配不上。另一个常见问题是插件更新后宿主项目缓存了旧版本。我会先执行插件删除再重新添加注意不是直接覆盖目录。这个动作看起来简单但它能清掉很多因为设置残留导致的怪问题。如果在删除后重新添加仍出现“找不到插件”的报错再看插件目录是否有plugin.json这个文件缺失时Claude Code 会完全忽略整个目录。5.2 规则互相覆盖CLAUDE.md、AGENTS.md、SKILL.md 的优先级关系有时候插件明明加载成功了但行为不符合预期。我会怀疑是规则覆盖问题。宿主项目的CLAUDE.md往往是最高优先级的项目规则插件里的SKILL.md是特定技能的规则两者对同一件事给出不同指示时模型容易困惑。比如CLAUDE.md里写了“所有函数必须有完整 JSDoc”但我的评审插件只检查逻辑不检查注释结果评审意见里总是不合规地出现“缺少注释”的建议拖慢输出。我的处理办法是在SKILL.md第一行写明“本技能只聚焦代码风险不对注释风格发表意见”。这不是多余的话它相当于给模型一个使用边界避免宿主规则和技能规则打架。反过来如果宿主项目有更加严格的内部要求比如“禁止使用any”插件反而应该默认遵守宿主约束。规则不是越写越多越好。插件里写的每一条额外限制都会占用模型处理长文本时的注意力资源。我会定期复盘插件规则里哪些被频繁触发、哪些从来没人提过。如果一个检查项在二十次评审中一次都没被触发过我就把它删掉让输出更聚焦。5.3 Hooks 执行失败与超时看见边缘问题最后说一个很容易让插件看起来“失效”的坑hook 脚本静默失败。我遇到过好几次命令本身能跑但pre-commit钩子总不执行。排查过程让我印象很深我直接手动执行node hooks/pre-commit_review.js发现脚本抛了一个Cannot find module错误。原因是我在脚本里用了宿主项目没有安装的依赖。解决办法是脚本开头做依赖探测如果缺失就在控制台输出清晰提示而不是让整个插件看起来“没反应”。hook 的执行时间也要留意。如果脚本执行超过几秒Claude Code 可能会直接中断。我在脚本里做了一个轻量级超时处理超过 15 秒就退出并返回“评审未完成”。在团队协作中一个超时的 hook 比没有 hook 更让人恼火——它不会拉高评审覆盖率只会让人想绕过它。所以 hook 里尽量只做计算不重的操作比如检查文件变更列表、收集文件名真正的 AI 评审交给主模型在对话流里完成。调完插件后我会在测试仓库里保留一个“故意有问题的分支”。每次改完规则我就在这个分支上跑一遍确认新的规则能抓出旧问题不会因为改动了流程而漏判。这个分支就是插件的回归测试集它比任何文档都更能说明插件在当前版本下的真实行为。我建议每个插件都配一个这样的“标定场景”这应该算是我做了多个插件后最有价值的一条经验。说实话插件机制的引入改变了我的使用习惯以前我会精心维护一份很长的全局配置期望它能适配所有项目现在恰恰相反我把大部分项目特异性规则都收进了插件全局配置反而越来越短。插件的目录结构天然地逼着你去思考“这个能力到底属于什么场景、需要哪些配套文件和示例”。如果你手里已经积累了不少验证有效的提示词和检查清单建议尽快把它们整理成插件——打包的不只是 AI 能力更是你过去踩过坑之后沉淀下来的判断框架。