caveman-commit 命令深度解析:在 opencode 中用一条斜杠命令生成 Conventional Commits 风格的极简提交信息
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-commit 与 caveman、caveman-compress、caveman-review、caveman-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 帮助信息、以及插件解析入口识别命令用途的依据。
正文逐句拆解:
Generate a commit message for the current staged changes.—— 明确输入边界:命令只针对已git add的暂存区改动生成信息,不触碰未暂存文件。这与 Skill 版"不执行git commit、不暂存文件、不 amend"的边界声明互为呼应。Conventional Commits format.—— 输出必须遵循 Conventional Commits 规范,即type(scope): summary结构。Subject line ≤50 chars—— 主题行长度目标值。Skill 版进一步补充了硬性上限:≤50 字符是首选,72 字符是硬上限。imperative, lowercase after the type.—— 祈使语气("add"、"fix"、"remove",而非 "added"、"adds"、"adding"),且 type 之后的内容首字母小写。No period on subject.—— 主题行结尾禁止句号。Body only when the "why" isn't obvious from the subject—— body 是条件性的:subject 已自明时跳过,只有"为什么这么做"无法从 subject 看出来时才写。explain why over what.—— 全篇的价值观总纲:解释动机,不复述改动。diff 已经说明了 what,提交信息只负责补上 why。Drop filler, hedging, padding.—— 删除填充词、模糊限定(hedging)和冗余修饰。
这段不到百词英文的提示词,实际上浓缩了一套可执行的提交信息风格规范。
三、完整规则展开:subject、body 与负面清单
opencode 命令模板是压缩形态;skills/caveman-commit/SKILL.md 给出了同一规则的完整版本,这里把它作为模板规则的权威展开来讲解。
3.1 Subject 行规则
- 结构:
<type>(<scope>): <imperative summary>,其中<scope>可选; - 允许的 type 集合:
feat、fix、refactor、perf、docs、test、chore、build、ci、style、revert; - 祈使语气:动词用原形,"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 #42、Refs #17。
3.3 永远不能出现的内容(负面清单)
- "This commit does X"、"I"、"we"、"now"、"currently"——diff 本身已经说明了做了什么;
- "As requested by ..."——协作信息用
Co-authored-bytrailer 表达; - "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.json。commands/*.md 六个斜杠命令模板(/caveman、/caveman-commit、/caveman-review、/caveman-compress 等)随之就位。.cjs 后缀的原因是该目录的 package.json 声明了 "type": "module",裸 .js 会被 Bun 当 ESM 加载。
4.2 斜杠命令如何被执行
opencode 对斜杠命令的处理方式是在消息到达插件钩子之前,先把用户键入的命令替换为命令文件的正文。这一机制在 plugin.js 的 chat.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 的硬依赖——它就是纯文本规则。因此可以:
- 原样复制:把 caveman-commit.md 的正文段落粘进任何支持自定义 prompt 的提交信息生成流程;
- 升级为完整版:直接复用 skills/caveman-commit/SKILL.md 的 Rules / Examples / Auto-Clarity / Boundaries 四节,获得更完整的约束;
- 对齐项目约定:冒号后大小写跟随项目习惯、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.js 与 caveman-parse.js 则展示了它在 opencode 中的安装布局、命令展开与解析链路,从源码层面印证了"键入命令 → 模板正文注入模型上下文 → 生成规范提交信息"的完整闭环。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00