caveman 的 caveman-review 技能详解:行级代码评审的输出契约、严重度标记与 Hook 接线机制
【免费下载链接】caveman🪨 why use many token when few token do trick — Claude Code skill that cuts 65% of tokens by talking like caveman项目地址: https://gitcode.com/GitHub_Trending/caveman1/caveman
caveman 项目中的caveman-review是一个"压缩式代码评审"技能:它把传统冗长的 PR 评审意见压缩为L<行号>: <问题>. <修复建议>.的单行格式,每条发现一行,只保留位置、问题与修复方案。本文以 skills/caveman-review/README.md 和 skills/caveman-review/SKILL.md 为主体,结合 模式解析器 与 技能注册表 等仓库源码,完整讲清该技能的输出契约、严重度体系、Auto-Clarity 放松规则、调用方式以及底层接线原理。读完后,你可以准确复述该技能的格式规范,并能从源码层面解释/caveman-review命令是如何被 Claude Code hook 和 OpenCode 插件识别并激活的。
技能定位:只做输出,不做任何副作用
caveman-review的核心定义是:单行式 PR 评论,只写位置、问题、修复,不写任何寒暄铺垫("No throat-clearing")。
根据仓库文档 docs/technical/skills-hooks-and-plugins.md 中的"Focused skills"契约表,该技能的边界被明确登记为:
| Skill | 输出契约 | 副作用 |
|---|---|---|
caveman-review | 行级(line-scoped)评审发现 | 不 approve、不 request-changes、不跑 linter |
这与 skills/caveman-review/SKILL.md 结尾的 "Boundaries" 一节完全一致:评审只做输出——不代写修复代码、不执行 approve / request-changes、不运行 linter,产物是"可直接粘贴进 PR 的评论"。README 中也再次强调 "Output only — does not approve, request changes, or run linters"。这种"纯输出契约"使该技能可以安全地嵌入任何已有评审流程,不与 CI、lint 工具链或 PR 状态机产生耦合。
在主 README.md 的命令总表中,/caveman-review被列在一次性安装附带的小工具里,描述为 "One-line, actionable review findings",与/caveman-commit(简洁提交信息)、/caveman-compress <file>(压缩记忆文件)等并列为独立命令。
输出格式:一行一个发现
技能的输出格式是严格的结构化契约,来自 SKILL.md 的 Rules 一节:
基础格式:L<line>: <problem>. <fix>.—— 评审多文件 diff 时扩展为<file>:L<line>: ...。
严重度前缀(可选,混合严重度时建议带上):
| 前缀 | 含义 |
|---|---|
🔴 bug: | 行为已损坏,会引发事故 |
🟡 risk: | 能跑但脆弱(竞态、缺空值检查、吞异常) |
🔵 nit: | 风格、命名、微优化,作者可忽略 |
❓ q: | 真正的问题(question),不是建议 |
README 给出的标准输出示例(可直接作为格式基准):
L42: 🔴 bug: user can be null after .find(). Add guard before .email. L88-140: 🔵 nit: 50-line fn does 4 things. Extract validate/normalize/persist. L23: 🟡 risk: no retry on 429. Wrap in withBackoff(3). L107: ❓ q: why drop the cache here? Reads on next request will miss.四个示例恰好覆盖全部四种严重度,并展示了两种行号写法:单行L42与行区间L88-140。注意每条都满足"位置 + 问题 + 具体修复"三段式:🔴 bug给出可定位的.find()与需保护的.email;🔵 nit给出可执行的拆分方案(extractvalidate/normalize/persist);🟡 risk给出具体包裹函数withBackoff(3);❓ q则说明不确定的因果("下次请求会 miss 缓存")。
Drop / Keep 规则:删掉什么、留下什么
格式规范之外,SKILL.md 还定义了两张清单,这是该技能区别于普通"简短评审"的关键。
必须删掉(Drop):
- "I noticed that..."、"It seems like..."、"You might want to consider..." 这类开场白;
- "This is just a suggestion but..." —— 改用
nit:前缀表达; - "Great work!"、"Looks good overall but..." —— 总体评价只允许在开头说一次,不能出现在每条评论里;
- 复述代码行本身在做什么 —— 评审者自己会读 diff;
- 一切模糊措辞(hedging):"perhaps"、"maybe"、"I think" —— 不确定就用
q:。
必须保留(Keep):
- 精确行号;
- 精确的符号 / 函数 / 变量名,且用反引号包裹;
- 具体修复方案,而不是 "consider refactoring this" 这类空话;
- 当修复方案无法从问题本身直接推出时,附上why。
SKILL.md 中给出了一组 ❌/✅ 对照,展示了"删词"前后的差异,值得完整参考:
| ❌ 冗长版 | ✅ 压缩版 |
|---|---|
| "I noticed that on line 42 you're not checking if the user object is null before accessing the email property. This could potentially cause a crash if the user is not found in the database. You might want to add a null check here." | L42: 🔴 bug: user can be null after .find(). Add guard before .email. |
| "It looks like this function is doing a lot of things and might benefit from being broken up into smaller functions for readability." | L88-140: 🔵 nit: 50-line fn does 4 things. Extract validate/normalize/persist. |
| "Have you considered what happens if the API returns a 429? I think we should probably handle that case." | L23: 🟡 risk: no retry on 429. Wrap in withBackoff(3). |
对照可见:压缩版不是简单截断,而是把"描述现象 + 猜测后果 + 委婉建议"三句合并为"现象(带精确符号)+ 动作(带具体函数名)"两句,并去掉全部模糊词。
Auto-Clarity:该详细时必须详细
纯压缩式输出有一个天然风险:在安全类发现、架构分歧或新人上手场景中,一行话可能不足以传达why。为此技能内置了Auto-Clarity机制(README 与 SKILL.md 均有说明):
遇到以下三类情况时,自动退出 terse 模式,写正常段落,其余发现恢复 terse:
- CVE 级安全发现—— 需要完整解释加引用依据(SKILL.md 表述为 "CVE-class bugs need full explanation + reference");
- 架构分歧(architectural disagreements)—— 需要理由阐述,一行不够;
- onboarding 场景—— 作者是新成员,需要知道why而不只是what。
README 对这一机制的表述是:"drops terse mode for CVE-class security findings, architectural disagreements, and onboarding contexts where the author needs thewhy. Resumes terse for the rest." 这与主技能caveman的 Auto-clarity 设计一脉相承——压缩永远让位于安全警告和不可逆操作的清晰度(见 docs/technical/skills-hooks-and-plugins.md 对主技能 "Auto-clarity relaxes compression" 的说明)。
调用方式与触发词
主命令:
/caveman-review自然语言触发词(来自 SKILL.md 的 frontmatter description):"review this PR"、"code review"、"review the diff"。
退出评审风格:说 "stop caveman-review" 或 "normal mode" 即可恢复冗长(verbose)评审风格(SKILL.md "Boundaries" 一节)。
源码解析:/caveman-review如何被解析为模式激活
技能的调用不是魔法,仓库中有明确的解析链路。核心在共享模式解析器 src/hooks/caveman-parse.js(parseModeChange函数),它被 Claude Code 的 hook 与 OpenCode 插件共同复用,文件头部注释说明其目的正是"让 hook 和插件不会与 tracker 的正则行为漂移"。
1.review是"独立模式",不能通过/caveman <arg>选择。解析器中定义:
// Modes handled by their own slash commands (/caveman-commit, etc.) — not // selectable via /caveman <arg>. const INDEPENDENT_MODES = new Set(['commit', 'review', 'compress']);(见 src/hooks/caveman-parse.js#L51-L53)。这意味着如果你输入/caveman review,解析器不会激活评审模式,而是返回unresolved并提示使用/caveman-review这个专属命令——独立模式只能走自己的斜杠命令入口。
2. 斜杠命令分支:同时支持 marketplace 命名空间形式。在parseModeChange的斜杠命令匹配段(src/hooks/caveman-parse.js#L213-L232):
if (cmd === '/caveman-review' || cmd === '/caveman:caveman-review') { return { action: 'set', mode: 'review' }; }两种形态都被识别:直接输入/caveman-review,或以 marketplace 插件命名空间形式出现的/caveman:caveman-review(代码注释指出此前只有 compress 和 stats 处理了命名空间变体,后来补齐了全部技能)。匹配成功后返回{ action: 'set', mode: 'review' },由调用方(hook 或插件)激活 review 模式。
3. OpenCode 路径:模板展开前的文字识别。OpenCode 会把用户键入的/caveman-review展开为命令文件的正文文本后再触发事件,因此解析器提供了expandedTpl选项来反向识别(src/hooks/caveman-parse.js#L170-L182):
if (/^review the current diff\b/.test(prompt)) { return { action: 'set', mode: 'review' }; }即当提示词以 "review the current diff" 开头时(这是评审命令模板的固定前缀),同样解析为激活review模式。注释特别强调这段逻辑必须在通用自然语言激活匹配之前运行,否则模板正文里的 "Activate caveman mode" 之类措辞会抢先触发默认模式。
4. 自然语言触发与防误触。解析器还会对整段提示词做自然语言匹配(如 "activate caveman" 类短语),并做了多重防护:引号包裹的文本("和`界定)在匹配前被置空,避免引用触发词(例如粘贴帮助卡片内容)误触模式切换;以/开头的命令文本不会反过来切换模式;疑问句("what is caveman mode?" 等)被识别为提问而非激活命令。相关回归测试见 tests/test_caveman_parse.js 与 tests/test_mode_tracker.py,OpenCode 插件侧的安装/行为测试见 tests/installer/opencode.test.mjs。
注册与校验:技能在仓库中的登记状态
caveman-review在 skills/registry.json 中被列入preserved_skill_ids:
"preserved_skill_ids": [ "cavecrew", "caveman-commit", "caveman-compress", "caveman-help", "caveman-review", "caveman-stats" ]从注册表结构看,skills数组登记的是参与 native pack 分发的技能(带delivery与suites字段,如caveman、caveman-setup等),而preserved_skill_ids是保留的传统技能集合——caveman-review属于后者,即它是通过常规 skill 安装路径分发、被注册表显式保留的技能,而非 native pack(caveman-local)的一部分。仓库的完整性校验脚本 tests/verify_repo.py 也会检查skills/caveman-review/SKILL.md路径存在,确保该技能目录不被意外删除。
技能的 SKILL.md 采用标准 frontmatter 描述,name: caveman-review,description声明了三个触发场景(/caveman-review、"review this PR"、"review the diff"),供 LLM 路由使用。
压缩评审的实际收益(仓库基准)
主 README.md 的基准表中包含一项与安全评审直接相关的任务:
| Task | Normal | Caveman | Saved |
|---|---|---|---|
| Review PR for security issues | 678 | 398 | 41% |
这说明在"PR 安全评审"这一典型场景下,caveman 风格的评审输出相对普通输出约有 41% 的 token 差(该数字来自主 README 的基准表,适用于仓库所述测试条件)。需要注意的是,该技能同时内置了 Auto-Clarity:对 CVE 级安全发现会主动放宽压缩、写完整段落,因此实际收益会随发现类型浮动。
适用前提与限制
- 技能面向"评审输出",不改变任何文件、不执行 lint、不改变 PR 状态——它的输出契约在 docs/technical/skills-hooks-and-plugins.md 中登记为"无副作用";
- 斜杠命令
/caveman-review依赖宿主 agent 的命令路由(Claude Code、Codex、Gemini、Cursor 等,具体可用命令取决于宿主支持的插件/hook 形态),自然语言触发词 "review this PR" / "review the diff" 则依赖 LLM 对 SKILL.md frontmatter 的路由理解; - 严重度前缀是"可选、混合时建议带",全 🔴 的 diff 可以不带前缀;
- 想退出评审风格,直接说 "stop caveman-review" 或 "normal mode"。
延伸阅读
- skills/caveman-review/README.md — 技能概览(本文主体来源)
- skills/caveman-review/SKILL.md — 完整的 LLM 面向指令(Drop/Keep 清单、Auto-Clarity、Boundaries)
- src/hooks/caveman-parse.js — 模式解析器,
/caveman-review到review模式激活的解析链路 - skills/registry.json — 技能注册表与
preserved_skill_ids - docs/technical/skills-hooks-and-plugins.md — 技能/钩子/插件的集成边界总览
- README.md — 仓库总览与命令表
【免费下载链接】caveman🪨 why use many token when few token do trick — Claude Code skill that cuts 65% of tokens by talking like caveman项目地址: https://gitcode.com/GitHub_Trending/caveman1/caveman
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考