
做代码评审这事儿干得越久越有种说不清道不明的感觉。同样是看一个 Pull Request有人看五分钟就能嗅到问题所在有人对着 diff 翻来覆去看半天也说不出个所以然。差别不在谁更细心而是资深工程师脑子里挂着一套隐形的检查清单——数据库索引有没有失效事务边界是不是包错了这个接口是不是越权了异步线程池有没有被打满这些直觉养成的过程太长了长到没法直接教给新人。而我在两个月前做了一件事把这套“评审直觉”拆成了 25 条可执行的规则封装成一个可安装的 skill用 9 条命令驱动它工作。今天把整个设计思路和落地过程完整地写出来。这个 skill 解决的核心问题其实很朴素让 AI 编程助手的代码评审能力从一个“什么都懂一点的泛泛评论家”变成一个“盯准要害、自带优先级、按行号给建议”的同行评审人。它适合三类人被 PR 评审缠得喘不过气的技术负责人、经验还不够但想主动学着做深度代码走查的初中级工程师、以及所有在 Cursor、Claude Code 这类工具上折腾自定义工作流的人。我会把 25 个技能的构成逻辑、9 条命令的触发机制、安装目录的组织方式、实际评审时踩过的坑全部交代清楚。1. 为什么非得把“直觉”做成“skill”1.1 评审直觉的本质其实就是模式识别先说个基本判断。资深工程师看代码时的那股“不对劲”的感觉本质上是模式识别——见得够多以后大脑把一类问题压缩成了一个特征向量下次再遇到相似结构就自动报警。比如看到“先查库存再扣库存”的代码就算还没读到后面有没有并发锁老手心里已经开始打鼓了。这种能力不是知识是“知识场景后果”三者绑定后的经验记忆。问题是这种经验记忆极难传递。你把评审意见写在 PR 评论里别人看到的只是结论——这里要加锁。但你脑子里实际跑过的推演过程、曾经出过的事故、以及不同场景下的例外情况都沉淀不下来。这就导致技术的评审文化往往靠“一代人带一代人”的方式缓慢传承效率极低。skill 给了我一个完全不同的载体。它不是让人去学经验而是把经验拆成规则文件把规则文件变成 AI 可调用的工具。当我把自己脑子里那套“看到什么结构就该去查什么”的映射关系写进规则就等于把多年积累的 pattern 转移到了一个可以让 AI 按序调用的外部系统里。可以理解为把你的行业经验“压缩包”解压成了别人可以反复查阅的“手册”。1.2 普通提示词和 skill 的差别在哪很多人会问那我直接把这段要求写进 system prompt 里不就行了答案是行但很勉强。单个 prompt 的问题在于它不可组合、不可更新、不可精确触发。你把 25 类评审规则全塞进 system prompt上下文窗口会被大量占用AI 会被各种规则的表述稀释注意力最后每条规则都执行得很浅。更麻烦的是没法分开调优——某个规则误报率高了你想单独调它结果得重写整段 prompt牵一发动全身。skill 的设计思路则完全不同它是“按需装配”。25 个技能以独立规则文件存在平时不加载只有当对应的命令或上下文触发时才被召唤进来。系统提示词里只留了一条总纲剩下的是查命令路由、按需组合规则。这带来两个实际好处一是每次评审只带入少数几条强相关规则误报率明显下降二是规则的迭代不需要动主文件改某个规则文件本身就能生效。另一个体验上的关键差异是“确定性”。普通的 AI 评审每次结果都飘忽不定同一个 PR 评两次给出的答案可以不同。但带规则文件后只要触发条件一致进入调用链的规则集合就固定了输出结构也随之稳定。对做代码评审来说这种“稳定感”非常重要因为团队需要的是一个能预期、能对齐的评审标准。1.3 为什么选了“可安装”这个形态“可安装”是我设计时坚持的一个原则。原因很现实——我最初在单项目里做的内嵌规则只服务了一个仓库但没有团队会满足于只在某一个项目上做评审管控。把 skill 做成可安装的包本质上是把评审能力从“个人经验”变成了“团队资产”。任何成员拉下来放到指定目录就能用不需要理解内部细节任何团队 clone 到自己的工程里就立刻拥有一套统一的评审基线。而且更新也是单向的——我更新规则包团队拉取新版本所有人的评审标准就同步升级了。这在工程管理上的价值远远超过了技术本身。2. 25 个技能的构成逻辑与维度拆解2.1 先定框架评审到底要看哪些维度刚开始整理规则清单时我列了将近 60 条写出来发现毫无章法。后来退了一步先问自己一次像样的代码评审到底应该从哪几个维度切入最后收敛成六类正确性、安全性、性能、健壮性、可维护性、一致性。这六个维度的排序也是刻意安排的。正确性排最前因为它代表“这次改动是否会引入逻辑错误”是评审最优先要守的底线安全紧随其后因为线上环境里安全问题通常意味着直接损失性能排在第三但只关注“改动后是否会造成明显退化”不过度优化健壮性查边界可维护性查长期成本一致性查规范对齐。这个排序不仅是分类也决定了技能被触发时的问题输出优先级。2.2 二十五条规则清单以及它们背后的真实事故下面是最终落地的 25 个技能。每条规则背后都对应着我过去做过评审、或处理过线上事故的真实场景——每一条都可以讲一个具体的案例。这里先把清单列全编号技能名覆盖维度核心检查点SK001并发安全正确性共享状态无锁、非原子读改写、并发容器使用错误SK002事务边界正确性事务范围过大、跨资源无事务、事务内做远程调用SK003幂等设计正确性重复提交未拦截、回调处理非幂等、无唯一键约束SK004状态机校验正确性非法状态迁移、状态字段无枚举约束、缺少流转校验SK005边界条件正确性空列表、除零、位溢出、时间为空等极端输入SK006SQL 注入安全性字符串拼接 SQL、MyBatis ${} 使用、预编译缺失SK007越权控制安全性水平越权、垂直越权、仅校验登录未校验归属SK008敏感信息泄露安全性AK/SK 硬编码、明文密码、日志输出敏感字段SK009文件上传校验安全性后缀绕过、文件类型未校验、路径穿越SK010命令注入安全性Runtime.exec、ProcessBuilder 拼接执行SK011N1 查询性能循环内查库、未使用批量查询、懒加载穿透SK012循环内 IO性能for 循环里做网络请求、频繁写日志、批量调用拆循环SK013大对象处理性能大文件全量读入内存、列表未分页全量返回SK014阻塞操作性能异步上下文里做同步阻塞调用、线程池无超时SK015空指针与默认值健壮性未判空、错误使用 Optional、默认值掩盖异常SK016资源释放健壮性连接未关闭、流未关闭、线程池未 shutdownSK017超时与重试健壮性缺少超时控制、重试无退避、重试风暴SK018降级与熔断健壮性依赖故障无兜底、熔断开关缺失、降级策略粗糙SK019错误吞没可维护性catch 后空处理、异常转返回 false 无日志SK020日志缺失可维护性关键路径无日志、异常无堆栈、缺少业务追踪 IDSK021魔法数字可维护性裸数字、裸字符串、硬编码阈值SK022超长函数可维护性单函数超过 80 行、嵌套超过 4 层、职责混乱SK023重复代码可维护性复制粘贴、相似逻辑未抽取、多处修改风险SK024命名与注释可维护性命名无法表意、注释描述实现而非意图SK025代码规范对齐一致性格式化冲突、命名风格不统一、旧有约定未遵循设计这些规则时我给自己定了一条硬标准每条规则必须能映射到一个“可验证的代码特征”而不是一句模糊的建议。比如 SK011 不是简单说“注意性能”而是要求在循环体内检测数据库访问操作。规则越具体AI 识别出问题的可操作性就越强。2.3 为什么是“25”而不是更多更少25 这个数字不是凑出来的是刻意收敛的结果。最初 60 条里有很多交叉重复比如“并发安全”和“线程池”不能完全分开但写下来会变成两条相近的规则使用时会互相干扰所以需要合并另外一些规则过于偏门比如“序列化版本号缺失”这类问题在大多数项目中存在但实际影响度太低不值得占一条评审资源。收敛到 25 条以后我发现一个规律这个数量正好能满足“常见问题覆盖”的需求又不至于让模型在加载规则时出现注意力稀释。团队协作时25 条也刚好是一个能被完整记忆和讨论的体量。如果超过 40就会变成沉睡清单——写在那里但从来没人真正用起来。2.4 规则的粒度控制决定了误报率规则文件怎么写直接影响 AI 的命中率和误报率。我反复调整后沉淀出三个经验一是每条规则必须带“正例反例”的代码片段。只描述“检查越权”是不够的模型分不清什么是越权、什么只是看起来像。给两个片段做对比参照准确率会明显提高。二是必须带“严重程度”标签。每条规则有一个默认级别blocker / major / minorAI 输出问题时按这个标签排序。如果不强制分级AI 往往会平分笔墨把真正致命的并发问题跟无关痛痒的取名建议混在一起。三是必须写“误报抑制条件”。例如 SK011 里明确写了“如果查询条件包含唯一索引且结果集固定 ≤ 1 条则不报”这能帮模型避开把一些合理写法误判成问题。这个部分花的时间最多但对最终可用性的提升最明显。3. 九条命令的设计与实际用法3.1 为什么是命令而不是让 AI 自由发挥有了 25 个规则文件后摆在面前的是如何让 AI 知道“什么时候该调用哪些规则”的问题。我试过让模型自主决定——把规则说明全部喂进去让它看到代码后自己判断该检查哪些项。结果很糟糕它经常在一段代码上触发 20 多条规则输出满屏的 minor 问题严重问题反而不突出。后来换了思路由人来指定触发的主题而不是让 AI 自由决定。这正是命令模式的价值。命令是一种固定的、带参数的触发方式每一次调用意味着一个明确的意图AI 不需要猜只需要执行。3.2 9 条命令的完整速查表整个 skill 设计为 9 条命令覆盖安装、触发、管理、复盘四个环节。下面是把全部命令整理成速查表命令格式用途核心逻辑/review-now/review-now [文件路径]评审当前文件不依赖 git diff对指定文件做全维度扫描/review-pr/review-pr [目标分支] [基础分支]评审整个 PR 的 diff自动读取 diff按改动文件批量加载规则/review-focus/review-focus [维度] [文件]定向评审某类问题只注入对应维度的规则减少干扰/review-security/review-security [文件]安全专项评审专门触发 SK006-SK010 五个安全规则/review-explore/review-explore [文件] [行号]对指定行深度分析不按规则清单扫描而是做自由深度推理/skill-list/skill-list列出已安装的技能读取 skills 目录呈现可用的 25 个技能及启用状态/skill-toggle/skill-toggle [技能编号] [on/off]启用或关闭单个技能修改规则加载白名单/review-log/review-log [次数]查看评审历史记录读取最近若干次评审的输出文件/review-metrics/review-metrics统计本次评审的问题分布按严重级别和维度输出统计表这 9 条命令里前 5 条是真正干活的后 4 条管的是“查看和管理”。做这个拆分的原因是我观察到大部分 AI 工具失败的原因是“让人不知道它能干什么”。管理命令虽然看起来不起眼但它给了用户对工具的掌控感人格化一点说就是让工具“可被看见”。3.3 每条命令背后的运行逻辑拿最核心的/review-pr为例拆解一下。执行时skill 先自动获取目标分支和基础分支之间的 diff然后做几个处理步骤按文件类型过滤掉构建产物和配置文件否则会把 lock 文件当代码审毫无意义对 diff 做切片——如果改动超过 200 行就按 hunk 分段评审避免上下文窗口溢出对每个文件抽取变更函数的上下文而不是只拿改动行本身因为很多问题不看到完整函数结构根本判断不了。/review-focus则是另一种思路。假设团队这周在做安全整改你就只调用安全专项技能组把注意力全部集中到安全类问题上。过去用普通评审20 条规则一起上安全问题的权重会被均分定向技能一激活安全规则就成了唯一裁判。这在专项治理场景下特别实用。/review-explore是我加的控制性最弱的一条命令。它的设计不是为了让 AI 按规则找问题而是让模型就一段代码做自由推理——可以理解为退役资深工程师的“开放式点评”。它对大模型本身的推理质量要求很高不适合单独依赖但用来发现“规则清单覆盖不到的系统性设计问题”时效果出人意料地好。3.4 命令复杂度的取舍够用就好也有人问为什么不提供更多命令比如加一条/review-realtime让 AI 在编辑器里边写边评或者加一条/review-history对比多次评审差异。我做了但最终都砍掉了。原因在于每增加一条命令用户的学习成本和工具的维护成本都会同步上涨。9 条对于一个人在日常编码工作中频繁调用的场景来说刚好处于“不需要查文档就能记住”的临界点。超过这个数就会出现大多数人只会用一两条命令、其余全部沉没的尴尬局面。4. 安装落地与核心实现细节4.1 安装目录的结构设计“可安装”是所有设计的落点。安装目录的规范我用的是业界目前比较主流的 format——在用户级目录或项目根目录下建立skills/文件夹每个 skill 子目录内包含一个SKILL.md主文件和若干规则引用文件。以 Claude Code 系工具为例安装后的结构长这样.skills/ ├── review-master/ │ ├── SKILL.md │ ├── commands.md │ └── rules/ │ ├── SK001-concurrency.md │ ├── SK002-transaction.md │ ├── SK003-idempotency.md │ ├── SK004-state-machine.md │ ├── SK005-boundary-value.md │ ├── SK006-sql-injection.md │ ├── ... │ └── SK025-style.mdSKILL.md 是技能的“总闸门”里面定义了该 skill 的名称、描述、适用场景、以及默认启用的规则列表。commands.md 则是命令路由表它告诉 AI 解释器当用户输入/review-pr时应该加载哪些规则、执行什么流程、按什么结构输出。4.2 SKILL.md 核心配置逐行拆解主文件的配置方式直接决定了 skill 的可用性。我一开始写的版本把所有规则都塞进主文件结果文件达到 2 万多字符加载后对话响应速度严重变慢。重新设计后主文件只保留入口逻辑和执行指令规则细节全部外置到 rules 目录。主文件的核心配置大致如下这里提供一个精简示例实际配置会略多一些--- name: review-master description: 基于资深工程师评审经验的多维度代码评审技能覆盖正确性、安全、性能、健壮性、可维护性、一致性共 25 项规则。 version: 1.2.0 triggers: - /review-now - /review-pr - /review-focus - /review-security - /review-explore - /review-log - /review-metrics rules: default_enabled: true enabled_skills: - SK001 - SK002 - SK003 - SK005 disabled_skills: - SK024 severity_order: [blocker, major, minor] output: format: markdown group_by: severity include_line_numbers: true max_issues_per_rule: 5 ---enabled_skills和disabled_skills可以做到“全量默认开启但允许定向关闭”。severity_order决定 AI 输出时按什么顺序罗列问题——我强制它把 blocker 级别问题置顶让评审人第一时间看到必须决定能否合入的问题。max_issues_per_rule也很关键它限制单条规则最多输出几个问题避免 AI 揪住一个点开始无限罗列。如果不用这个配置方式让模型自己把 25 条规则全部执行一遍每次评审都像开了一场所有分支一起上线的部署大会根本没有重点。4.3 规则文件的一个完整示例单个规则文件的写法是 skill 成败最关键的部分。拿 SK006 SQL 注入示例--- id: SK006 name: SQL-Injection category: security severity: blocker detection: - 发现 MyBatis 映射文件或注解中存在 ${} 直接拼接 - 发现字符串常量与外部输入直接相加后传入 SQL 执行接口 - 发现 Order By 或 Column 参数存在不可控拼接 positive_example: | // 推荐写法使用 #{} 预编译参数 SELECT * FROM user WHERE id #{id} negative_example: | // 危险写法使用 ${} 拼接用户输入 SELECT * FROM user WHERE id ${id} suppression: - 查询条件来源为可信配置中心常量 - ORDER BY 字段名来自枚举白名单 action: | 推荐使用预编译参数若必须动态拼接表名或字段名请使用白名单校验detection部分不用自然语言的长篇描述而是列出一组可验证的特征让模型看起来像“检查清单”。positive_example和negative_example给模型建立对比suppression列出误报豁免场景。severity标记这里是 blocker这类问题一旦出现在修改代码中将会被 AI 最先标注。提示suppression是一个设计窍门它直接减少了评级干扰。如果规则文件写得太严没有豁免场景模型会把配置中心传入的白名单 SQL 也打成注入漏洞。加上豁免后能大幅降低无效报警让同事更愿意看评审结果。4.4 命令路由让 AI 精确知道触发后该做什么commands.md 示例中/review-pr的写法## /review-pr 评审整个 Pull Request 的改动内容。 执行步骤 1. 获取目标分支与基础分支的 git diff 2. 过滤非源码文件JSON、lock、minified 等 3. 若 diff 超过 200 行按 hunk 分段执行评审 4. 针对每个文件路径从 rules/ 目录加载对应的规则文件 5. 汇总输出为 Markdown 表格包含文件路径、行号、问题描述、规则编号、严重级别 输出格式 | 文件 | 行号 | 严重级别 | 问题描述 | 规则编号 | |------|------|----------|----------|----------| 特殊指令 - 如果 diff 中存在新增文件则按全文件评审 - 如果发现跨文件的关联修改接口签名变化导致调用方改动需补充影响面分析命令路由文件本质上给模型提供了一套“角色行为规范”触发某条命令后AI 不再是自己头脑风暴而是执行一段带固定流程、固定输出格式的既定程序。这就把每次评审的输出结构变得高度一致可靠程度和可读性都大幅提升。4.5 全局安装与项目级安装的取舍我实际测试下来不同安装方式对应不同使用习惯。如果你经常参与多个项目把 skill 放进用户级全局目录最实用Claude Code 类工具放在~/.claude/skills/Cursor 类工具放在用户配置目录下的.cursor/skills/也可以使用项目级目录这样团队可以通过 Git 管理评审基线做到团队全员共用一套 skill我的建议是个人探索用全局目录团队落地用项目级目录。全局目录方便你自己随时调用项目级目录则让团队评审标准可审阅、可改进、可执行。“可安装”没有固定的标准答案重点在于让技能包跟着项目走、跟着团队走。团队刚引入时可以先指定某个核心仓库作为 pilot 项目把项目级目录提交进 Git全员统一用同一套配置。等效果得到认可再复制到其他核心仓库。别一上来就全局推广不然容易因为触达不到预期而被保洁式废弃。5. 典型问题排查与避坑经验5.1 高误报是最容易出现的问题第一次在真实 PR 上跑完整评审发现 AI 输出的 47 个问题里有 30 个是噪音。例如它看到像User user userMapper.selectById(id);这行就报警说“没有判空”但实际上上层调用已经做了空值感知或者从流程上不可能为空。误报太多导致的后果非常严重——团队成员看完两轮后就不会再看第三轮。这个问题的根源不在于 AI 本身的能力而在于规则文件的detection部分给得太宽泛。解决的办法不是在 prompt 里写“请你谨慎一点”而是细化规则的触发条件。在 SK015 里我加了“仅当方法内存在对返回值的方法调用或显式的空值解引用时才输出”误报率直接下降了一半。5.2 规则之间互相打架怎么办另一个典型问题是两个规则的输出结论冲突。比如某段代码里有一个循环调用外部接口的操作SK012 报“循环内 IO 可能造成性能瓶颈”但 SK017 看到这个调用带了超时和重试机制可能又报“超时设置过长”。AI 如果同时输出这两条用户感觉很混乱因为两条建议的优化方向是相反的甚至有点矛盾。后来在 SKILL.md 主文件里加了规则优先级定义性能类规则优先于健壮性类规则。当两条规则针对同一段代码给出冲突建议时只保留优先级较高的那一条另一条降为“参考建议”不占用主问题列表。这个“仲裁机制”是大模型评级输出的一致性保障。5.3 上下文窗口不够用的破局方式一次评审整个大规模 PR 动辄几万行 diff模型的上下文窗口根本装不下。实验了几个方案最终选择“按 hunk 切分 按严重级别聚合”每个 hunk 单独执行规则扫描扫描结果直接追加到中间结果文件不留在对话上下文里全部 hunk 扫完后再统一汇总、排序、去重这个方案的代价是评审速度比一次性跑完整 diff 慢不少但好处是单个 PR 再大也不会撑爆窗口。对于那些动辄几千行的大 PR我优先建议直接在 CI 上跑静态扫描让 skill 专注在代码走查层面。5.4 团队落地时容易忽视的细节技能包版本要打 tag更新时在团队的发布群里同步变更说明尤其是规则某个条目被增强或删除时要重点提示命令说明要写一页简单的 cheat sheet不然新成员根本不会主动触发skill-list规则文件的命名要一致用 SK001 这种前缀而不是中文名否则跨工具迁移时文件名编码问题会很痛苦skill 的评审结果默认不要直接贴在 PR 评论区而是先由维护者筛选一轮。AI 直接贴评论的结果往往是刷屏式噪音影响很不好5.5 常见问题速查表现象原因处理办法命令完全没反应skill 包不在工具的配置目录里确认 skills 文件夹的路径重启会话再试只输出少量空泛评论规则文件没有读取到或主文件未声明规则目录检查 SKILL.md 的 rules 路径改用绝对路径单个规则疯狂刷屏max_issues_per_rule没设置给 SKILL.md 加上输出上限默认 5 条即可两个规则给出相反建议规则仲裁机制缺失在 SKILL.md 增加优先级定义后加载的高优评审结果不稳定每次触发加载的规则集合不一致检查命令路由是否固定了默认启用列表每次输出都过长没有按严重级别限制强制按 severity 分组最多各输出 10 条与大模型原生评审混在一起工具还有其他评审提示禁用其他 system 级评审 prompt避免双轨冲突6. 实测效果一次真实评审的前后对比6.1 同一个文件传统评审和 skill 评审的差异我用一个真实的 Spring Boot Controller 做了对照实验。这个文件里包含一个典型的水平越权问题用户传入一个订单 ID查询时只校验了登录态没校验该订单是否属于当前用户。传统模式的 AI 评审输出偏泛——它列出了“代码风格不统一”“变量命名不够直观”“建议增加日志”这类的意见安全问题完全没提出来。换用/review-focus 安全命令后输出的结果截然不同SK007 越权规则命中给出问题描述“接口/order/detail仅校验登录状态未校验订单归属存在水平越权风险任意登录用户可查看他人订单”附带行号、风险等级 blocker、以及修复建议在查询前增加归属校验还顺带查了一条关联问题——该 Controller 继承了BaseController中的通用查询方法绕过鉴权的风险波及了多个接口评审准确率和实用性完全是一个量级的差异。评审不再只停留在代码风格层面而是真正指向了需要被阻断的核心问题。6.2 从评审输出到团队协作的闭环skill 跑出来的结果不应该是终点。我在团队内部设置了一个反馈闭环——每次用命令评审出的问题里如果发现误报就在规则文件里补一条suppression如果发现漏报就给对应技能新增一个detection特征。这样技能包持续在迭代每用一次就准一次。这个闭环其实是把“团队的经验”不断写入技能包的机制。资深评审人的直觉在这个循环里被持续沉淀新员工也可以通过读取规则文件本身来理解什么值得关注。于是 skill 不只是评审工具它同时变成了团队的知识库和入门的教材。最后再分享一个我在实际使用中的体会这个技能包不是为 AI 准备的是为人的经验准备的。工具不会替你做思考它只负责把你从前踩过的坑、见过的错误、听过的教训按准确的时机重新摆到你面前。真正有价值的东西不在那 25 个数字和 9 条命令里而在你肯不肯把脑子里的“我觉得这里有问题”翻译成别人也能执行的“这里需要检查什么”。如果这套方法对你有一点启发我的建议是从自己的事故记录清单开始先写 5 条你真正踩过的坑做成你最需要的那个技能包然后让 AI 在下一次你写代码的时候提醒你。