AI编程技能包实战:用SKILL.md构建自动化代码审查工作流

AI编程技能包实战:用SKILL.md构建自动化代码审查工作流 1. skills到底是什么一次从提示词到技能包的能力升级做AI编程助手深度用户这么久我越来越觉得skills这个目录名值得好好聊一聊。如果你经常用支持自定义技能的AI编程工具比如Cline、Roo Code这一类你一定见过项目里出现一个名为.cline/skills或者.roo/skills的文件夹。以前我总觉得这就是放几个Markdown模板的地方直到有次接手一个遗留项目才真正意识到skills机制解决的是什么问题。先说结论skills本质上是一套结构化的“能力包”。它让AI助手不再只是被动地回答你“现在该做什么”而是可以在特定任务被触发时主动加载一套完整的工作流、领域知识和执行脚本像一位老员工一样按你预设的SOP把活干完。以前你要在每次对话里反复粘贴大段提示词告诉AI“按这个规范来”“优先看这几个文件”“报错时执行这个脚本”现在这些动作全部被打包进一个目录交给skills机制去管理。这个机制解决的核心痛点非常明确重复劳动和上下文碎片化。我统计过自己过去三个月用AI写代码的时间分配至少三成花在“重新交代背景”上。每开一个新会话就要把项目结构、编码规范、测试命令、注意事项重新说一遍。skills出现以后这些成本被一次性消灭。它适合谁来用我觉得分三类人。第一类是重度AI编程用户每天几十次对话需要把高频任务沉淀成固定流程第二类是团队技术负责人想把代码审查规范、发布检查清单、新人引导流程固化下来让AI代理按照团队标准执行第三类是接外包或做多项目的自由开发者每个项目都有不同的约定用skills隔离不同项目的能力栈比在全局配置里改来改去可靠得多。2. 技能包的核心结构一个被严重低估的三层目录设计说实话我第一次打开别人的skills目录时是有点懵的。里面什么文件都有有的放Markdown文档有的放Python脚本有的放资源文件夹看起来毫无章法。后来自己动手写了十几个技能包又被AI坑了好几轮才算摸清楚这套设计背后的逻辑。2.1 技能包的三层结构指令、脚本、资源一个标准的技能包通常由三个部分组成SKILL.md指令文件、scripts脚本目录、assets资源目录。这三层各司其职缺一不可。SKILL.md是整个技能包的大脑。它负责定义这个技能是干什么的、在什么条件下被触发、按什么步骤执行。AI代理读到这个文件后会把它当作一次任务的详细工单。这里面的核心不是“教AI怎么写代码”而是“告诉AI按什么顺序、以什么标准完成一件事”。写得好的SKILL.md读完一遍你甚至不需要再补充任何背景。scripts目录放的是可执行脚本负责处理那些“纯文本指令搞不定”的动态逻辑。比如你要AI去统计一个目录下所有Python文件的函数数量这种任务靠提示词做不准确但写一个十几行的Python脚本就能精确完成。AI可以在执行过程中调用这些脚本自己看输出结果再决定下一步动作。这相当于给AI装了一双可以真正触摸系统的手。assets目录则是知识库和模板库。比如一份架构决策记录模板、一段数据库索引规范、几个典型代码示例都可以塞在这里。AI在执行任务时会被明确告知“去assets下找参考文件”不用依赖模型自身的记忆。这对那些模型没训练到、或者经常更新的内部规范尤其好用。2.2 技能包和提示词、MCP的本质区别很多人会把skills和MCP模型上下文协议搞混官方文档里也是各说各话。我在实际使用中总结了一个比较朴素的理解方式提示词是口头交代MCP是工具连接器skills是完整的带教手册。口头交代的问题在于AI每次理解都可能跑偏而且交代的内容会占用大量上下文窗口。MCP解决了“AI怎么连上外部系统”的问题比如连数据库、查Jira工单、操作浏览器但它不负责“告诉AI按什么流程做事”。skills恰恰补上的是流程和规范这一层。一个更直白的类比MCP像给AI配了一整套工具箱但它不知道什么时候该用扳手、什么时候该用改锥skills则是那个在旁边指导的老师傅告诉它“第一步先干这个第二步看结果再决定下一步如果出现某某情况就执行某某脚本”。两者叠加才会产生质变只配工具不配流程AI只会更忙乱不会更聪明。2.3 为什么说目录命名决定了技能的命运这里分享一个我踩过的大坑技能目录的命名和描述字段直接决定了AI能不能在关键时刻想起你。我最早写的一个“python代码审查”技能包描述写的是“审查Python代码并提供改进建议”。听起来没毛病对吧但实际触发率低得可怜AI经常在改动代码时根本不加载它。后来我仔细看AI的调度逻辑才明白它判断要不要使用某个技能主要靠的是一段简短的描述和触发条件描述太长它读不完太短又没有辨识度。我的描述写得跟普通的系统提示词没什么区别AI认为“不用加载技能我也能完成”。改成“当用户提交一段超过50行的Python代码变更时按团队规范执行审查流程检查错误处理、类型标注、性能隐患并输出结构化审查报告”之后触发率立刻上来了。关键在于把触发条件和执行动作写具体让AI能明确判断“这就是该用那个技能的时候”。3. 从零构建一个技能包完整实操流程拆解现在进入正题我带你把一个技能包完整写出来。这里选用“代码审查技能包”作为示例因为它逻辑清晰、可复用性高而且踩坑点足够多方便我边走边讲。整个过程大约需要20分钟你掌握后可以迁移到任何其他技能场景。3.1 先规划再动手写技能包前必须想清楚的三个问题动笔之前先别急着建文件先回答自己三个问题。第一个问题这个技能包的边界在哪里你要让技能做一件“能被明确描述的事”而不是一个大而全的“智能助手”。比如“代码审查”是个合格的边界但“提高代码质量”就不行后者的执行路径太模糊AI根本不知道第一步该干什么。第二个问题触发条件是什么这里的触发条件要具体到能判断。以“代码审查”为例触发条件可以是“用户要求审查某段代码”或者“用户提交了改动并明确说请审查”。如果你希望它在更复杂的场景下自动触发还需要在描述里补充“当检测到多文件改动涉及异常处理时优先加载此技能”这类细则。第三个问题需要哪些外部信息技能执行时要从哪里拿数据——是读工作区文件、跑测试命令还是调用某个脚本提前想清楚因为后续要把这些动作写进SKILL.md的步骤里。以代码审查为例技能至少需要读取待审查文件的路径、相关的测试输出、以及团队的编码规范文档。这三个问题想清楚后再开始动手效率会高很多。否则经常会出现写一半发现某个信息拿不到或者AI按流程走的时候总是卡在中间某一步。3.2 创建技能包目录与核心文件技能包本质上就是一个文件夹放在项目的.claude/skills、.cline/skills或者对应的skills目录下具体位置取决于你用的工具。以我常用的Cline为例目录结构是这样的.cline/skills/code-review/ ├── SKILL.md ├── scripts/ │ └── analyze_changes.py └── assets/ └── team_coding_standards.md先创建目录然后我们来写最核心的SKILL.md文件。这个文件分两部分YAML格式的frontmatter头部和Markdown格式的正文指令。--- name: code-review description: 当用户提交Python代码变更并要求审查时按团队规范执行代码审查检查错误处理、类型标注、性能隐患并输出结构化审查报告。适合增量变更和多文件改动场景。 --- # 代码审查技能 ## 目标 对代码变更执行标准化审查输出可执行的改进建议。 ## 触发条件 - 用户明确要求审查代码 - 用户提交diff或代码片段并询问“有没有问题” - 变更涉及错误处理、数据库连接、文件IO时自动启动 ## 执行步骤 1. 使用 scripts/analyze_changes.py 读取工作区中的待审查文件列表 2. 对每个文件执行静态扫描重点检查 - 是否在except块中只写pass或print - 函数参数和返回值是否有类型注解 - 是否在长循环中执行了不必要的IO或网络请求 - 是否存在可变默认参数 3. 对比 assets/team_coding_standards.md 中的规范要求标记偏离项 4. 输出markdown格式的审查报告按严重程度分级阻塞、警告、建议 ## 注意事项 - 如果发现阻塞级问题补充具体的代码修复示例 - 审查报告必须包含文件路径和行号 - 不要修改任何源文件只输出报告3.3 让技能具备动态能力编写辅助脚本纯指令能覆盖流程但真正让技能变得“聪明”的是能在执行过程里动态获取信息的辅助脚本。下面这个脚本的作用是递归扫描工作区中的Python文件提取待审查文件的路径和基础统计信息供AI参考。#!/usr/bin/env python3 import os import sys from pathlib import Path def collect_python_files(root: Path) - list: 收集所有Python文件排除虚拟环境和构建目录 skip_dirs {.venv, venv, __pycache__, .git, node_modules, dist, build} result [] for dirpath, dirnames, filenames in os.walk(root): dirnames[:] [d for d in dirnames if d not in skip_dirs] for fname in filenames: if fname.endswith(.py): full_path Path(dirpath) / fname result.append(full_path) return sorted(result) def main(): root Path(sys.argv[1]) if len(sys.argv) 1 else Path.cwd() files collect_python_files(root) print(f找到 {len(files)} 个Python文件) for f in files: try: with open(f, r, encodingutf-8) as fh: lines fh.readlines() print(f{f} | {len(lines)}行 | 最后修改: {os.path.getmtime(f):.0f}) except Exception as e: print(f{f} | 读取失败: {e}) if __name__ __main__: main()这个脚本本身很简单但它告诉AI一个重要信息执行时先把所有文件列出来防止遗漏。我在之前写的技能包里经常发现一个问题——AI审查代码时会“选择性失明”总是关注中间几个文件开头和结尾的文件容易漏掉。有了这个脚本先输出全量清单AI就必须面对所有文件。3.4 填充资源文件团队规范的沉淀地assets目录下我放一份team_coding_standards.md内容就是团队的编码约定但不需要写那些大而全的教条只写技能执行时需要对照的硬性规则。比如# 团队编码规范技能审查专用版 ## Python后端 - 函数必须包含类型注解禁止使用裸def func(a, b) - 禁止在except块中仅使用pass至少记录错误日志 - 所有敏感配置项通过环境变量注入禁止硬编码 - 数据库查询必须使用参数化SQL禁止字符串拼接 - 新增接口必须配套单元测试覆盖率不低于80% - 循环内禁止发起HTTP请求如有需要改为批量处理后合并请求 ## 通用 - 所有日志必须包含可索引的标识字段如request_id、task_id - 禁止在共用代码中打印调试信息到stdout这份文件的价值在于它把“凭经验判断”变成了“比对检查清单”。AI的代码风格判断能力其实并不差但容易受上下文影响而飘忽给它一份明确的比照标准后审查结果稳定很多。团队成员更新规范时只改这一个文件就生效所有AI代理下次执行时都会遵循新标准。4. 技能包的调试与迭代一次好的实践是如何打磨出来的写技能包和写代码一样很少有人能一遍通过。我前前后后写过二十几个技能包真正好用的都是反复调试过三四轮的。这个环节最容易让人劝退因为你感觉明明写得挺清楚AI就是按自己的思路乱来。别急下面几个方法帮我解决掉绝大多数问题。4.1 最小化验证先用最简单的场景跑通流程我写技能包的习惯是先不追求完整用最小的场景把整个链路跑通。比如代码审查技能第一版我只让它做一件事——读analyze_changes.py的输出然后挑一个文件做简单检查。确认AI能正确调用脚本、能读到assets里的规范、能按步骤输出报告后再逐步增加审查维度。这个方法的直接好处是出问题时你能快速定位是哪个环节的问题。链路跑不通时至少能做到“锅只在当前这一个新增点上”排查成本大大降低。我见过很多朋友一次性写完大而全的技能包然后发现AI的行为完全不可控根本无从下手修。4.2 用“样例问答法”模拟调试调试技能包最直接的方式是开一个新会话手动触发这个技能看AI的实际反应。每次跑完后把“预期行为”和“实际行为”记录下来对比差异。举个例子我第一版代码审查技能执行时AI输出的报告只有建议没有把“阻塞”级别标出来。我检查了SKILL.md发现我确实写了分级输出的要求但“阻塞”的定义写得不够具体——“如果发现阻塞级问题”。AI理解不了什么叫阻塞它只能判断“这段代码哪里不够好”。于是我改成“当代码中存在未处理的异常、数据库连接未关闭、循环内发起HTTP请求时判定为阻塞级问题”。之后它每次都能正确分级。这说明一个关键规律SKILL.md中的每一项要求都应该具体到可以机械判断而不是依靠AI的语义理解去猜。4.3 技能包效果评估别只看输出要看行为改变评估一个技能包到底有没有用不是看AI输出的审查报告漂不漂亮而是看它是否真正改变了你后续的代码行为。我做技能包调试时有一条经验每次技能执行结束后我会额外问几个追问问题比如“这个函数性能瓶颈在哪”“这段异常处理有没有覆盖连接关闭”看AI在技能“卸载”后是否还保留了对任务的理解。如果AI离开技能流程后立刻忘记了上下文说明技能的指令引导还不够深导致模型只是机械地走了一遍流程没有真正吸收你的工作方式。这个情况可以通过往SKILL.md里加一个“输出示例”板块来缓解给AI一个具体范例它模仿起来会稳定得多。4.4 常见问题速查表这里整理了一个技能包调试阶段高频问题的速查表都是我实际踩过的坑现象根本原因解决方案技能从不自动触发description里的触发条件太模糊AI不确定该不该用把触发场景写具体含“当用户提交…时”这类句式技能执行到一半就停了步骤之间存在歧义AI不确定下一步该干什么给每步加一个明确的产出物描述如“输出审查报告草稿”脚本路径找不到技能包在子目录时相对路径基准不同在SKILL.md中写明“所有路径相对于本技能目录”AI不读assets里的规范没有在步骤里强制要求读取在步骤中明确写“阅读assets/xxx.md并逐条比对”输出格式每次都不一样没有定义输出模板在SKILL.md中增加“输出格式”章节给一个完整示例5. 提升技能包可靠性的几个进阶设计思路当你写了几轮技能包、跑通基本流程后会发现这些技能包还是“有点笨”。它会按你的指令走但没有达到“老员工”的水准。这个阶段我开始琢磨怎么让技能包更智能、更可靠下面这几个设计思路是我对比了多个AI代理工具后沉淀下来的适用性很强。5.1 技能嵌套与组合从单点能力到系统能力单个技能包只解决单一任务但真实工作中的任务往往是复合的。我处理过一个场景代码审查完成后AI不仅要输出报告还要根据报告直接创建修复任务的工单。这就涉及两个技能的协作——审查技能和工单创建技能。实现方式是在审查技能的步骤里明确写一句“当阻塞级问题数量大于0时切换至create-jira-ticket技能提交优化任务并将本报告的摘要作为工单描述”。AI代理普遍支持这种跨技能调用前提是你定义的技能边界清晰且描述里说明了调用条件。技能组合的价值在于你可以把可复用的基础能力独立编写再像搭积木一样组合成复杂的业务流程。这个思路尤其适合团队场景比如一个“版本发布”技能可以囊括测试、构建、生成变更日志、触发部署等多个子技能。5.2 把错误处理写进技能指令这个点是小白最容易忽略的。大多数技能包只写“正常流程怎么做”不写“出问题怎么办”结果AI遇到异常情况时就会自创一套处理方式经常把事情搞得更糟。我现在写技能包时会专门增加一个“异常处理”章节。比如代码审查技能里就有这么一段## 异常处理 - 如果 analyze_changes.py 执行失败如权限不足输出错误信息并退化为直接读取用户指定的文件进行审查 - 如果目标目录不存在不要自行创建提示用户检查项目路径 - 如果待审查代码严重超出上下文窗口按文件拆分审查并汇总每份报告的结果这个设计让AI在异常面前有了“应急预案”而不是尴尬地站在原地或者绕开问题强行推进。按我的经验加了异常处理章节之后技能包的可用性会提升一大截。5.3 版本管理与团队共享技能包也是代码也需要版本管理。现在我会把skills目录纳入git仓库并在SKILL.md的frontmatter里加一列version字段。每次改动版本号就递增然后顺手在changelog记录一下改了什么。这样团队里其他人拉取到新版本时可以快速了解技能包的变化。还有一个容易被忽视的点技能包最好有一个“能力自检”入口。我通常会在SKILL.md末尾加一个自检清单列出“本技能完成的标准是什么”。AI执行完任务后可以自检一遍确认没有遗漏步骤再向用户汇报。这个小设计对复杂任务特别有用相当于给AI加了一次“交付前检查”。6. 实战心得技能包方案如何扩展你的自动化疆界技能包这套机制本质上是在AI能力和你的具体业务之间建立了一层可配置的中间层。它的上限有多高取决于你对业务的拆解能力和对AI行为边界的理解深度。我能分享的只是过去半年里在真实项目里反复打磨技能包后积累的个人感受。我现在维护的每个项目都会在一开始花半小时搭好技能包骨架。最常见的是三种代码审查、提交信息规范化、接口文档生成。项目本身有自己独特的工程约定时就再写一个项目专属技能。后面每一次AI执行任务都在按我沉淀下来的流程走节省了我大量重复解释的时间。再分享一个最近琢磨的妙用技能包也可以用来做“知识遗忘控制”。当某个技能的指令编写得足够详细时AI在任务结束后对项目背景的记忆其实不那么重要了因为一切都在技能包里有据可查。这意味着我可以更放心地频繁开新会话不用担心上下文丢失影响任务质量。这个思路在接多项目并行时尤其受用。当然技能包也不是万能的。它不能替代你对业务的判断也不能把毫无头绪的任务变成清晰流程。它的价值在于“把确定的事情自动化把不确定的事情半自动化”。这是我在一堆失败实验之后才慢慢想明白的定位。如果你正打算尝试这个方向建议先从复制本文的代码审查技能包开始边用边改慢慢就能写出顺手又可靠的自定义技能了。