1. 项目概述当维护开源插件遇上重复性升级任务如果你维护过一个深度集成第三方库的开源项目尤其是那种库本身还在快速迭代的那你一定懂我在说什么。我负责一个名为Mermaid Visualizer的开源 IntelliJ 插件它的核心功能是为 JetBrains 全家桶IDEA、PyCharm 等带来完整的 Mermaid.js 图表支持——实时预览、语法高亮、代码补全、错误检查一应俱全。听起来很酷对吧但这份酷炫背后藏着一个持续了将近一年的“甜蜜的负担”Mermaid.js 的版本升级。Mermaid.js 是一个活跃的图表渲染库几乎每个月都有新版本发布带来新的图表类型如近期的 ishikawa 石川图、新的语法关键字或是箭头样式的更新。对我的插件而言每次升级远不止是替换一个mermaid.min.js文件那么简单。这涉及到近十个文件的同步更新JFlex 词法分析器语法文件、基于 Grammar-Kit 的语法解析器、代码自动补全的数据目录、各类测试用例还有用户文档。整个过程步骤固定但细节繁多且环环相扣。漏掉任何一个文件轻则导致构建失败重则让用户用不上新功能而浑然不觉。最初我手动处理一次升级需要3个小时全程精神紧绷事后还常常发现遗漏。后来我尝试用 Claude 辅助效率有所提升但我依然是那个“指挥家”需要把每一步、每一个文件路径、每一个注意事项都口述给它。直到我发现了 Claude Code 的Skills技能功能并将整个升级流程封装成了一个可复用的自动化技能才真正将我从这项重复劳动中解放出来。现在一次完整的升级从分析变更日志到完成测试验证只需要45分钟到1小时并且实现了零遗漏。这篇文章我就来拆解这个自动化技能的构建思路、核心设计以及我踩过的坑希望能给面临类似重复性工程任务的开发者一些启发。2. 问题本质为什么简单的文件替换会如此复杂在深入技能构建之前有必要先理解这个“升级”任务为什么不能一键完成。我的插件Mermaid Visualizer并非简单地嵌入一个 JavaScript 渲染引擎。为了实现 IDE 级别的深度集成它的架构是多层次的核心渲染层捆绑mermaid.min.js文件通过 JCEFIDE 内嵌的 Chromium进行图表渲染。这是最直观的一层。语言支持层词法分析器 (Lexer)使用 JFlex 编写负责识别 Mermaid 语法中的所有关键词如graph TD,A--B、图表类型标识符和箭头模式。它定义了代码的“颜色”和基础结构。语法解析器 (Parser)使用 Grammar-Kit 生成构建 PSI程序结构接口树。这使得 IDE 能理解代码的层级关系为高级功能打下基础。智能功能层代码补全根据用户正在编写的图表类型是流程图graph还是时序图sequenceDiagram动态建议相关的关键词和箭头符号。语法检查能实时检测出未闭合的括号、错误的关键词等。导航与结构视图允许用户在大纲中查看图表的结构快速跳转到定义。关键在于所有这些层的数据和逻辑都硬编码了当前 Mermaid.js 版本所支持的语法集合。当上游 Mermaid.js 新增一个图表类型比如gitGraph我的插件需要在词法分析器中注册这个新类型标识符。在语法解析器中更新语法规则。在补全数据文件中添加该图表类型特有的关键词列表。更新测试用例确保新功能被正确解析和渲染。同步更新文档中的支持列表。这些文件之间存在严格的依赖顺序。例如你必须先更新词法/语法定义并重新生成对应的 Java 类文件然后才能更新基于这些类文件的补全提供器或测试用例。如果顺序错了构建就会失败或者新功能不生效。注意这里最隐蔽的坑是JFlex 的“最长匹配”原则。在定义箭头模式如--,-,-时更长的模式必须写在更短的模式之前。如果顺序颠倒--可能永远无法被正确识别因为它会被先匹配到的-或-截胡。这种领域知识如果不明确写出AI 助手很容易犯错。所以升级任务的核心矛盾在于流程高度标准化、可预测但执行过程细节密集、容错率低且依赖特定的领域知识。这正是自动化脚本或者说 AI 技能最能大显身手的地方。3. 解决方案选型为什么是 Claude Skill而不是脚本或普通提示词面对这个重复性任务通常有几个自动化选项写一个 Shell/Python 脚本、录制一个 IDE 宏或者写一个详细的提示词Prompt让 AI 助手每次照着做。我最终选择了Claude Code Skill原因在于它完美地平衡了灵活性、可维护性和知识封装能力。3.1 传统脚本的局限性首先考虑编写一个专门的升级脚本。这听起来很直接解析 Mermaid 的变更日志然后按照既定逻辑去修改那十个文件。优势完全自动化执行速度快。劣势变更感知能力弱Mermaid 的每个版本变更内容差异很大。有时是新增图表高影响有时只是内部 Bug 修复低影响。一个静态脚本很难智能地判断该执行哪些步骤容易“用力过猛”或“力度不足”。容错性差脚本对文件格式和位置的假设是硬编码的。一旦项目结构因重构发生微调比如移动了语法文件目录脚本就会崩溃需要人工调试和更新。开发维护成本实现一个能精准解析自然语言变更日志、并理解复杂代码语法的脚本其开发复杂度不亚于插件本身的一个核心模块。维护它又成了新的负担。3.2 普通提示词的不足其次是用一个超详细的提示词来指导 Claude 或 ChatGPT。优势灵活可以利用 AI 的理解能力应对一些微小变化。劣势难以复用和版本化提示词通常散落在聊天历史中难以查找、复用和迭代。下次升级时你可能需要重新整理或寻找无法保证过程的一致性。缺乏结构化和条件逻辑一个庞大的提示词虽然包含所有步骤但 AI 在执行时可能迷失在细节中。更重要的是很难在其中清晰地实现“如果……那么……”的条件分支。你需要手动告诉 AI 这次升级有哪些具体变更然后它再从头到尾执行整个冗长流程效率低下。知识无法沉淀那些关键的领域知识如 JFlex 文件的关键词在 17-66 行箭头模式顺序很重要每次都需要在提示词中重复或者依赖 AI 临时去代码中探索容易出错。3.3 Claude Skill 的核心优势Claude Skill 是一个存储在项目根目录.claude文件夹下的 Markdown 文件。它通过/技能名的命令方式调用。它的设计理念解决了上述问题项目化与版本化Skill 文件就在你的代码仓库里和你的源代码一起受 Git 管理。当项目结构变化时你可以同步更新 Skill。它成为了项目文档和工具链的一部分。封装领域知识Skill 的核心价值在于它将那些原本只存在于开发者脑海中的“隐性知识”显性化、结构化地记录了下来。文件路径、代码片段的位置用大致行数作为地标、关键约束条件如 JFlex 排序规则、操作之间的依赖关系——所有这些都白纸黑字地写在 Skill 里。AI 无需猜测只需严格执行。支持条件逻辑Skill 可以定义清晰的阶段Phases并且根据输入如对变更日志的分析结果决定跳过或执行某些阶段。这使得它能灵活应对不同类型的发布。可迭代优化和代码一样Skill 可以不断重构和优化。我的第一个版本很粗糙第二个版本加入了结构第三个版本才引入了成熟的条件分类机制。每次使用后你都能发现可以改进的地方并立即更新文件下次调用就是改进后的版本。人机协作的清晰边界Skill 负责执行那些明确、重复的步骤而开发者负责提供决策输入如本次变更日志的内容和处理边界情况如 Skill 执行后构建失败需要人工介入排查一个罕见错误。这种分工非常高效。核心洞察如果你有一项任务需要重复做且每次的步骤高度相似但需根据上下文微调同时任务依赖大量项目特定的领域知识那么将其编写成一个 Claude Skill 的投入产出比会非常高。它不是一个全能的 AI 代理而是一个针对特定场景的、高度定制化的“自动化工作流说明书”。4. 技能解剖一个11阶段的自动化升级引擎我将升级 Mermaid.js 的 Skill 命名为upgrade_mermaid。它不是一个简单的步骤列表而是一个包含决策引擎、精确操作指南和质量门禁的完整流程。整个技能被分解为 11 个阶段。4.1 阶段0变更影响分析与决策引擎这是整个技能的“大脑”。它不直接修改代码而是先分析 Mermaid 官方发布的变更日志通常是 GitHub Release Notes并对每一项变更进行分类。## 阶段 0 — 分析变更日志与影响分类 **输入**Mermaid.js 本次版本的完整变更日志文本。 **目标**确定本次升级需要触发的后续阶段。 请逐条分析变更日志将变更归类到下表并记录具体内容 | 变更类别 | 影响等级 | 影响文件范围 | 示例 | | :--- | :--- | :--- | :--- | | **新增图表类型** | **高** | ~10个文件 | venn-beta, ishikawa-beta | | **为现有图表新增关键词** | **中** | ~4个文件 | 为 venn 图新增 set, union | | **新增箭头模式** | **中** | ~4个文件 | half-arrowheads | | **破坏性变更** | **高** | 视情况而定 | 重命名图表类型、移除旧语法、API变更 | | **仅内部/性能/Bug修复** | **低** | 仅版本引用文件 | 性能优化、修复特定渲染问题 | **决策逻辑** - 如果存在 **“高”** 或 **“中”** 影响等级的变更则进入 **阶段 1-9** 的完整流程。 - 如果**只有“低”**影响等级的变更则**跳过阶段 2-7**词法/语法/补全更新直接进入 **阶段 8**更新捆绑文件。这个阶段至关重要。它避免了“一刀切”的升级方式。如果一个版本只是修复了内部 Bug那么技能就会智能地跳过所有语法层面的更新直接更新 JavaScript 文件版本号节省大量时间和避免不必要的风险。4.2 阶段1-3基础设施与语法层更新假设本次升级包含新图表类型技能会进入核心修改阶段。阶段1准备与下载调用项目内一个现有的 Gradle 任务./gradlew updateMermaid。这个任务是我预先写好的负责从 Mermaid CDN 下载指定版本的mermaid.min.js计算 SHA-256 校验和并原子性地替换项目中的文件。Skill 选择集成而非重写这个现有工具是遵循了“不要重复造轮子”的原则。阶段2更新 JFlex 词法分析器精准定位这是体现“领域知识封装”的典型。技能没有说“去更新词法分析器”而是给出了精确到代码区域的指南## 阶段 2 — 更新 JFlex 词法分析器 (仅当存在新类型/关键词/箭头时) **文件**src/main/grammars/Mermaid.flex ### 2.1 图表类型定义 (~第100-130行YYINITIAL状态) 在 DIAGRAM_TYPE 规则块中找到按逻辑分组如流程图类、时序图类的图表类型字符串列表。将新的图表类型字符串添加到合适的分组中。 **格式示例**graph \| flowchart \| ... \| 新图表类型 ### 2.2 关键词集合 (~第17-66行KEYWORDS HashSet) 找到以图表类型为标题的注释块如 // Flowchart keywords。在对应的分组下添加新的关键词。**注意**只添加语法规定的保留字而非任意标识符。 **格式示例**// 新图表类型 (如 Venn Diagram) keywords intersection, subset,### 2.3 箭头模式 (~第160-218行NORMAL状态) 在 ARROW 规则块中插入新的箭头模式。**必须严格遵守顺序** 1. 首先添加**变长**的箭头模式如 -.-。 2. 然后添加**固定长度**的箭头模式并确保**更长的模式排在更短的模式之前**例如 -- 必须在 - 之前- 必须在 - 之前。// 正确顺序 “-.-” | // 变长最先 “--” | // 固定长最长 “-” | // 固定长较短 “-” // 固定长最短实操心得使用~行数作为地标landmark而非绝对行号是保持技能健壮性的小技巧。因为随着文件编辑行号会变但代码块的结构和相对位置比如“关键词集合在文件开头图表类型定义在中间偏上”是稳定的。这比写死行号更能适应未来的修改。阶段3重新生成词法分析器类执行./gradlew generateLexer。这是一个关键依赖步骤必须执行否则后续所有基于新词法的功能都将失效。技能将其作为一个独立阶段是为了强调其必要性。4.3 阶段4-7功能层与数据层更新阶段4更新 Grammar-Kit 语法解析器根据新图表类型或关键词更新src/main/grammars/Mermaid.bnf文件中的语法规则。同样技能会指出需要修改的大致区域和规则名称。阶段5更新代码补全元数据补全功能依赖一个 YAML/JSON 格式的数据文件里面列出了每个图表类型的所有有效关键词。技能会定位到这个文件并在对应的图表类型节点下添加新的关键词。阶段6更新测试用例为了确保新功能被正确解析需要更新相关的测试夹具Fixture文件。技能会指导 AI 在src/test/resources目录下找到对应的测试用例文件添加使用新语法的新测试用例。阶段7更新文档最后更新README.md或docs目录下的支持列表确保文档与实现同步。4.4 阶段8-10收尾与验证阶段8更新捆绑的 JS 文件与版本引用这其实是阶段1的延续确保所有引用 Mermaid 版本号的地方如gradle.properties、插件描述文件都已更新到新版本。阶段9同步 Git 变更执行git add .和git commit -m “升级 Mermaid.js 至版本 x.y.z”。将自动化修改纳入版本控制。阶段10构建与验证门禁最关键阶段这是将“编辑操作”转化为“可交付成果”的质量关卡。技能会依次执行./gradlew build编译整个项目。./gradlew verifyPlugin运行完整的测试套件并执行 IDE 插件验证。这里有一个重要的设计如果测试失败技能不会直接报错退出而是会尝试进入一个修复循环。例如它可能会读取测试失败信息发现是因为某个新图表类型的测试用例引用了未更新的测试夹具然后自动去修复那个文件并重新运行测试。这个“尝试-反馈-修复”的循环是 AI 技能超越简单脚本的另一个体现。5. 从构思到可靠技能开发的迭代历程这个技能并非一蹴而就。我经历了三个明显的迭代版本才达到现在稳定可靠的状态。第一版过于模糊的指令最初的技能像是一个简陋的待办清单“更新词法分析器”、“更新补全数据”。结果就是Claude 经常把新关键词加到错误的代码块里或者弄错箭头顺序。它需要大量的上下文交互和纠正几乎没节省时间。教训AI 需要极其精确的“坐标”模糊的指令会导致不确定的结果。第二版有了结构但缺乏弹性我加入了文件路径和阶段划分情况好了很多。但它假设每次升级都是一样的“全套流程”。当遇到一个只有 Bug 修复的版本时技能还是会机械地去修改语法文件然后因为找不到所谓的“新语法”而困惑或者做出无意义的修改。教训真实世界的流程充满条件分支技能必须能处理这种多样性。第三版当前版引入决策引擎我增加了阶段0变更影响分析和基于此的条件阶段触发机制。同时我细化了每个文件内的操作指南加入了更多的“地标”注释和排序规则。这个版本终于可以“一键”处理大多数升级场景了。另一个关键改进是强化了底层的updateMermaidGradle 任务使其具备原子性和完整性校验为技能的可靠执行打下了坚实基础。注意事项开发一个复杂的 Skill 和开发一个软件功能很像需要迭代。不要指望第一个版本就完美。将其视为一个需要调试和优化的程序。每次使用后记下哪里不顺畅、哪里需要人工干预然后回头修改 Skill 文件。经过2-3个版本的迭代它就会变得非常顺手。6. 效果对比与收益分析量化一下使用技能前后的变化指标手动升级使用 Claude 临时提示词使用 Claude Skill平均耗时~180 分钟~90 分钟45-60 分钟精神负担极高需记忆所有步骤高需逐步指挥低提供变更日志即可错误/遗漏率较高尤其疲劳时中等依赖提示词完整性极低流程强制覆盖知识留存在开发者脑中散落在聊天记录固化在项目仓库中可重复性差依赖个人状态一般需查找历史优秀随时一键执行最大的收益不仅仅是时间节省更是质量的提升和可持续性的保障。因为技能强制进行全面的变更日志分析阶段0和系统性的文件遍历阶段2-7我再也没有遗漏过新功能。这对于一个旨在“紧密跟进上游”的开源插件来说是核心竞争力。作为个人开发者我不再需要为每次升级预留大段的、容易出错的工作时间这让我能更专注于开发新功能而不是维护旧集成。7. 如何为你自己的项目构建 Claude Skill如果你也被类似的重复性、高细节的维护任务所困扰以下是我总结的构建有效 Skill 的要点目标选择寻找那些你至少做过两次并且确信还会做第三次的任务。流程越固定、步骤越多、细节越容易忘Skill 的回报率越高。拆解与记录在下一次手动执行该任务时像给新手写教程一样记录下每一个步骤、每一个用到的文件及其精确路径、操作中的任何特殊规则或陷阱比如我们提到的 JFlex 排序。这份记录就是 Skill 的初稿。结构化与阶段化将线性记录转化为分阶段的 Markdown 文档。每个阶段目标明确如“准备数据”、“修改A模块”、“修改B模块”、“测试验证”。注入决策逻辑思考你的流程是否有“如果……就……”的情况。如果有在 Skill 开头设计一个分析或输入步骤并根据结果使用明确的指令如!-- 如果条件X成立则执行以下阶段 --和!-- 否则跳过至阶段Y --来控制流程分支。提供精确坐标尽可能使用文件路径、代码片段、搜索关键词或大致行数范围来定位修改点。避免使用“某个地方”、“相关文件”这样模糊的表述。设置质量门禁一定要包含构建、测试、代码风格检查等验证步骤。让 Skill 确保产出的是可工作的代码而不仅仅是一堆编辑记录。版本化与迭代将 Skill 文件如.claude/upgrade_xxx.md放入你的 Git 仓库。每次使用后如果发现不足就像修复 Bug 一样修改它。技能的进化史也是你项目运维知识的沉淀。最后我想强调的是这个案例虽然围绕 Mermaid.js 插件升级但模式是通用的。无论是定期更新依赖库的许可证信息、在大型代码库中执行某种重复的重构、还是为每个新功能分支执行一系列标准配置——任何模式化、多步骤、易出错的认知型任务都是 Claude Skill 的用武之地。它本质上是一种“可执行的、智能化的项目专属运维手册”。花一小时创建它节省的是未来无数个小时的重复劳动和心智损耗。