首页
/ caveman-commit 命令深度解析:在 opencode 中用一条斜杠命令生成 Conventional Commits 风格的极简提交信息

caveman-commit 命令深度解析:在 opencode 中用一条斜杠命令生成 Conventional Commits 风格的极简提交信息

2026-09-06 17:11:18作者:凤尚柏Louis

caveman 项目把"少即是多"的压缩哲学从对话输出延伸到了 Git 工作流。本篇以仓库中的 caveman-commit.md 命令模板为主体,完整拆解这条 opencode 斜杠命令的提示词结构与生成规则,再结合同仓库中更完整的 caveman-commit Skill 与插件源码 plugin.js,讲清楚这条命令如何被安装、如何被解析、生成的提交信息必须满足哪些格式约束。读完后你可以直接在 opencode 会话中使用 /caveman-commit 生成规范提交信息,也可以把同样的规则移植到其他 Agent 的提交信息生成流程中。

一、这条命令在 caveman 生态中的定位

caveman 的主旨是"why use many token when few token do trick"——让 Agent 用尽可能少的 token 传达尽可能完整的技术信息。这一哲学除了压缩对话输出,还落地为一组保留技能(preserved skills),其中就包括 caveman-commit。在 skills/registry.json 中,caveman-commitcavemancaveman-compresscaveman-reviewcaveman-stats 等一同列在 preserved_skill_ids 里,说明它属于核心交付面,而不是实验性功能。

面向不同宿主,同一个命令有三种等价载体:

载体 路径 形态
opencode 斜杠命令 src/plugins/opencode/commands/caveman-commit.md 提示词模板(Markdown)
Claude Code 命令 commands/caveman-commit.toml TOML 命令定义
独立 Skill skills/caveman-commit/SKILL.md 带完整规则与示例的技能文档

三者的核心约定一致:Conventional Commits 格式、subject 行 ≤50 字符、祈使句、type 之后小写、结尾不加句号、body 只解释 why 不解释 what、删掉一切填充词与模糊措辞。区别只在于详略程度:opencode 命令模板是压缩到极致的一页纸,Skill 版本则是把每条规则展开并配了正反例。

二、命令模板原文全解

caveman-commit.md 全文只有两大部分:一个 YAML frontmatter 和一段提示词正文,逐段看:

---
description: Generate a terse caveman-style commit message for staged changes
---
Generate a commit message for the current staged changes.

Conventional Commits format. Subject line ≤50 chars, imperative, lowercase
after the type. No period on subject. Body only when the "why" isn't obvious
from the subject — explain why over what. Drop filler, hedging, padding.

frontmatter 的 description 不只是给命令列表看的描述文案,它是 opencode 渲染 /caveman-commit 帮助信息、以及插件解析入口识别命令用途的依据。

正文逐句拆解

  1. Generate a commit message for the current staged changes. —— 明确输入边界:命令只针对git add 的暂存区改动生成信息,不触碰未暂存文件。这与 Skill 版"不执行 git commit、不暂存文件、不 amend"的边界声明互为呼应。
  2. Conventional Commits format. —— 输出必须遵循 Conventional Commits 规范,即 type(scope): summary 结构。
  3. Subject line ≤50 chars —— 主题行长度目标值。Skill 版进一步补充了硬性上限:≤50 字符是首选,72 字符是硬上限
  4. imperative, lowercase after the type. —— 祈使语气("add"、"fix"、"remove",而非 "added"、"adds"、"adding"),且 type 之后的内容首字母小写。
  5. No period on subject. —— 主题行结尾禁止句号。
  6. Body only when the "why" isn't obvious from the subject —— body 是条件性的:subject 已自明时跳过,只有"为什么这么做"无法从 subject 看出来时才写。
  7. explain why over what. —— 全篇的价值观总纲:解释动机,不复述改动。diff 已经说明了 what,提交信息只负责补上 why。
  8. Drop filler, hedging, padding. —— 删除填充词、模糊限定(hedging)和冗余修饰。

这段不到百词英文的提示词,实际上浓缩了一套可执行的提交信息风格规范。

三、完整规则展开:subject、body 与负面清单

opencode 命令模板是压缩形态;skills/caveman-commit/SKILL.md 给出了同一规则的完整版本,这里把它作为模板规则的权威展开来讲解。

3.1 Subject 行规则

  • 结构:<type>(<scope>): <imperative summary>,其中 <scope> 可选;
  • 允许的 type 集合:featfixrefactorperfdocstestchorebuildcistylerevert
  • 祈使语气:动词用原形,"add"、"fix"、"remove",而不是 "added"、"adds"、"adding";
  • 长度:尽量 ≤50 字符,硬上限 72;
  • 结尾不加句号;
  • 冒号之后的大写习惯跟随项目既有约定(命令模板里明确写的是小写,即 caveman 的默认约定)。

3.2 Body 规则(仅在需要时出现)

  • subject 自明时整体跳过 body,不要为了凑结构而写;
  • 只有以下四类情况才加 body:不显而易见的 why破坏性变更(breaking change)迁移说明(migration notes)关联 issue
  • body 按 72 字符换行;
  • 列表用 - 而不是 *
  • issue/PR 引用放在最后,格式为 Closes #42Refs #17

3.3 永远不能出现的内容(负面清单)

  • "This commit does X"、"I"、"we"、"now"、"currently"——diff 本身已经说明了做了什么;
  • "As requested by ..."——协作信息用 Co-authored-by trailer 表达;
  • "Generated with Claude Code" 或任何形式的 AI 署名——除非用户自己的规则要求 Assisted-by/AI-attribution trailer,那就作为 trailer 追加;
  • emoji(除非项目约定要求);
  • scope 已经标明模块时还复述文件名。

3.4 正反例对照

Skill 文档给出了典型反例与正例:

反例(信息密度低、复述 what):

feat: add a new endpoint to get user profile information from the database

正例(why 驱动,带 issue 引用):

feat(api): add GET /users/:id/profile

Mobile client needs profile data without the full user payload
to reduce LTE bandwidth on cold-launch screens.

Closes #128

破坏性变更的正例则展示了 Conventional Commits 的 ! 标记与 BREAKING CHANGE: 段:

feat(api)!: rename /v1/orders to /v1/checkout

BREAKING CHANGE: clients on /v1/orders must migrate to /v1/checkout
before 2026-06-01. Old route returns 410 after that date.

3.5 Auto-Clarity:不许压缩的场景

极简主义有一条明确的例外线:破坏性变更、安全修复、数据迁移、回滚先前提交的改动,这四类必须带 body。原因是未来的排障者需要完整上下文,把这类改动压成一行 subject-only 会丢掉关键信息。这是"why over what"原则的制度化例外。

3.6 边界声明

Skill 版还明确了能力的边界:该技能只生成提交信息本身——不执行 git commit、不暂存文件、不 amend,输出一个可以直接粘贴的代码块。用户说 "stop caveman-commit" 或 "normal mode" 时退回冗长提交风格。opencode 命令模板里的 "for the current staged changes" 同样隐含了这个只读边界:命令消费暂存区状态,不产生任何写操作。

四、opencode 侧的实现:安装、触发与命令展开

理解这条命令如何真正生效,需要看 src/plugins/opencode/plugin.js 及其配套文档 src/plugins/opencode/README.md

4.1 安装与目录布局

安装器执行 bin/install.js --only opencode 后,插件落到 ~/.config/opencode/plugins/caveman/,布局为:

~/.config/opencode/plugins/caveman/
├── package.json
├── plugin.js              # 插件主体
├── caveman-config.cjs     # 由 src/hooks/caveman-config.js 复制而来
└── caveman-parse.cjs      # 由 src/hooks/caveman-parse.js 复制而来

安装器同时会把 "plugin" 数组条目写入 opencode.jsoncommands/*.md 六个斜杠命令模板(/caveman/caveman-commit/caveman-review/caveman-compress 等)随之就位。.cjs 后缀的原因是该目录的 package.json 声明了 "type": "module",裸 .js 会被 Bun 当 ESM 加载。

4.2 斜杠命令如何被执行

opencode 对斜杠命令的处理方式是在消息到达插件钩子之前,先把用户键入的命令替换为命令文件的正文。这一机制在 plugin.jschat.message 钩子注释中写得很清楚:

expandedTpl: opencode replaces a typed slash command with its command file's prose before this hook sees it.

也就是说,当你在 opencode 里键入 /caveman-commit 时,模型实际收到的是 caveman-commit.md 正文那段 Conventional Commits 规则,而不是命令字符串本身——命令模板本质上是预注入的提示词

4.3 命令解析链路

caveman-parse.js 是斜杠命令与模式切换的共享解析器(由 caveman-mode-tracker.js 与 opencode 插件共同复用)。它识别的正是这批斜杠命令:

const cmd = parts[0]; // /caveman, /caveman-commit, /caveman-review, etc.
if (cmd === '/caveman-commit' || cmd === '/caveman:caveman-commit') { ... }

从源码结构看,解析器同时接受 /caveman-commit/caveman:caveman-commit 两种书写形式,并维护了一张"由各自斜杠命令处理"的模式表(/caveman-commit 等),避免这些命令被误当作 /caveman 主模式的参数。

4.4 与常驻模式的关系

opencode 插件负责动态状态:会话创建时写模式标记文件(session.created 事件)、解析用户消息中的命令与自然语言切换、每轮请求向 system prompt 注入一行强化提示。而常驻的 caveman 规则集来自 ~/.config/opencode/AGENTS.md(安装器一并写入),确保即使插件运行时故障规则仍然加载。因此 /caveman-commit 生成的提交信息处于两层规则叠加之下:AGENTS.md 里的全局极简风格 + 命令模板里的提交信息专用格式,两者共同约束最终输出。

五、规则可移植性与适用前提

这条命令的提示词没有任何对 caveman 运行时或 opencode 的硬依赖——它就是纯文本规则。因此可以:

  1. 原样复制:把 caveman-commit.md 的正文段落粘进任何支持自定义 prompt 的提交信息生成流程;
  2. 升级为完整版:直接复用 skills/caveman-commit/SKILL.md 的 Rules / Examples / Auto-Clarity / Boundaries 四节,获得更完整的约束;
  3. 对齐项目约定:冒号后大小写跟随项目习惯、issue 引用格式按仓库实际流程(Closes #42 / Refs #17)调整。

适用前提与限制需要说明:

  • 命令模板假定存在 git 暂存区概念,输入边界是"已暂存的改动";
  • 它只产出文本,不代替 git commit,落盘仍由开发者(或宿主工具链)完成;
  • 72 字符硬上限与 50 字符目标值来自 Skill 版文档,opencode 模板只写了 ≤50,二者以"尽量 50、绝不超 72"理解即可;
  • 上述实现细节(插件钩子、.cjs 复制、AGENTS.md 常驻规则)均以当前仓库 src/plugins/opencode 目录的实际代码为准。

六、小结

caveman-commit.md 用一个不到十行的提示词模板,把 Conventional Commits 规范、长度约束、语气约束和"why over what"价值观压缩成 opencode 里的一条斜杠命令。配合 skills/caveman-commit/SKILL.md 中的完整规则、正反例与 Auto-Clarity 例外线,这套规则是可复制、可审计、可移植的提交信息风格基线;而 src/plugins/opencode/plugin.jscaveman-parse.js 则展示了它在 opencode 中的安装布局、命令展开与解析链路,从源码层面印证了"键入命令 → 模板正文注入模型上下文 → 生成规范提交信息"的完整闭环。

登录后查看全文
热门项目推荐
相关项目推荐