6. 综合练习
这是什么:技能包 = 一组围绕同一主题的技能文件夹,加上目录说明和分发方式,提交进仓库,谁 clone 下来都能用。
为什么用:单个技能是小技巧,技能包才是「团队的知识资产」。前者靠人记住,后者靠仓库记住——新人 clone 完就自动获得。
如何用:本章按五步走完一个真项目:定主题、写技能、拆资源、跨工具分发、加安全约束,每步都有验收标准。
6.1 目标与验收清单
目标:给一个小项目(自己的也行)配出一套「日常协作技能包」。
本次要写的三个技能:
| 技能 | 干什么 | 类型 |
|---|---|---|
commit-message |
按团队规范写提交信息 | 任务型 |
pr-review |
按清单做代码评审 | 任务型 |
release-notes |
从 Git 历史生成变更日志 | 任务型 |
验收清单:
- 第 1 步:写下一份技能包设计说明(主题、边界、命名)
- 第 2 步:三个技能都能被
skills-ref validate通过 - 第 3 步:
release-notes带scripts/和references/,正文不超过 100 行 - 第 4 步:同一个技能在 Claude Code 和 opencode 里都能被发现
- 第 5 步:技能包里有安装说明和安全约定,第三方技能不裸奔
6.2 第 1 步:定主题与边界
先想清楚这套技能包解决什么。本例的答案是:「把每次都要口头交代的协作规范固化成技能,新人 clone 下来就有」。
定三条边界,后面每写一个技能都对照检查:
- 只写「规范」,不写「实现」——脚本能干的进
scripts/,其余写清步骤 - 一个技能只管一件事——
pr-review不顺带帮你改代码 - 描述里写清触发场景——用户嘴里的词("提 PR"、"发版"、"写提交信息")要出现在
description里
在项目里先落一份说明:
# skills/README.md
本目录是团队的日常协作技能包,提交进仓库,所有人 clone 即得。
| 技能 | 用途 | 何时触发 |
|---|---|---|
| `commit-message` | 写符合规范的提交信息 | 用户要提交、要写 commit message |
| `pr-review` | 按清单评审改动 | 用户要 review、看 diff |
| `release-notes` | 从 Git 历史生成变更日志 | 用户要发版、写 changelog |
安装:把 `skills/` 下的文件夹复制到你的工具技能目录(或在项目里建 `.claude/skills/` 软链)。
6.3 第 2 步:写第一个技能
先写最简单也最常用的 commit-message:
---
name: commit-message
description: 按团队规范写 Git 提交信息(Conventional Commits 风格,标题 ≤ 72 字符)。用户要提交代码、写 commit message、或说「帮我写提交信息」时使用。
---
写提交信息:
1. 先跑 `git diff --staged` 看改了什么,`git status` 看还有哪些没暂存。
2. 判断类型:修复用 `fix`,新功能用 `feat`,重构用 `refactor`,文档用 `docs`,杂项用 `chore`。
3. 标题格式:`类型(范围): 祈使句摘要`,中文摘要,≤ 72 字符,不加句号。
4. 有破坏性改动时,正文第一行写 `BREAKING CHANGE: <说明>`。
5. 只写一行摘要时也要说清「为什么改」,别只写「更新代码」。
输出:先给一行标题,需要时再补正文。给出后问用户是否直接提交。
对应的目录:
skills/commit-message/SKILL.md
注意两处细节:
- 描述里塞了「提交」「commit message」这些用户真会说的词
- 最后一步是「问用户是否直接提交」——有副作用的动作留给用户确认,这本身就是一条安全约定
6.4 第 3 步:拆资源
release-notes 是最能体现分层价值的技能。正文只留步骤,重活交给脚本,长规则下沉到参考文件:
skills/release-notes/
├── SKILL.md
├── scripts/
│ └── collect-commits.sh
├── references/
│ ├── versioning.md
│ └── categories.md
└── assets/
└── changelog-template.md
SKILL.md:
---
name: release-notes
description: 从 Git 标签之间的提交历史生成变更日志。用户要发版、写 changelog、或问「这版改了什么」时使用。
allowed-tools: Bash(git:*) Read Write
---
生成变更日志:
1. 确认上一个版本标签:`git describe --tags --abbrev=0`。
2. 收集提交:跑 `scripts/collect-commits.sh <上一个标签>`,输出分类好的条目。
3. 定版本号:按 `references/versioning.md` 判定(SemVer,破坏性改动升主版本)。
4. 套模板:用 `assets/changelog-template.md` 的结构,把第 2 步的输出填进「本次变更 / 破坏性改动 / 修复」三段。
5. 写到 `CHANGELOG.md` 顶部,**只写文件,不打 tag、不推送**——打 tag 与推送交给用户。
scripts/collect-commits.sh:
#!/usr/bin/env bash
# 收集上一个标签以来的提交,按类型分组输出
set -euo pipefail
last_tag="${1:-$(git describe --tags --abbrev=0)}"
git log "${last_tag}"..HEAD --pretty=format:'%s' \
| awk '
/^feat/ { print "feat: " substr($0, 6) }
/^fix/ { print "fix: " substr($0, 5) }
/^docs/ { print "docs: " substr($0, 6) }
/^BREAKING/ { print "breaking: " substr($0, 10) }
{ other[++n] = $0 }
END {
for (i = 1; i <= n; i++) print "other: " other[i]
}'
跑一下看看:
chmod +x scripts/collect-commits.sh
./scripts/collect-commits.sh
你会看到(示意):
feat: 增加登录页的验证码
fix: 修复导出 CSV 时中文乱码
other: 更新依赖
references/versioning.md 里写 SemVer 判定规则,assets/changelog-template.md 里写三段式模板——正文里点名引用,Agent 才会去读。
6.5 第 4 步:跨工具分发
技能包要在多个工具里都能用,有两种放法:
放法一:进仓库(推荐给团队)
your-project/
├── .claude/skills/
│ ├── commit-message/SKILL.md
│ ├── pr-review/SKILL.md
│ └── release-notes/...
└── skills/ # 源目录,CI 负责同步
Claude Code 原生认 .claude/skills/,opencode 也认(它兼容 Claude 目录)。这样新人 clone 完就有。
放法二:装到个人目录(推荐给自己)
# Linux / macOS
cp -r skills/* ~/.claude/skills/
cp -r skills/* ~/.config/opencode/skills/
# Windows PowerShell
Copy-Item -Path skills\* -Destination "$env:USERPROFILE\.claude\skills\" -Recurse
装完各工具里验证一下:
skills-ref validate ./skills/release-notes
openclaw skills list # 用 OpenClaw 的话
Claude Code 里可以用 /skills 菜单看已加载的技能;opencode 里看 <available_skills> 列表。
6.6 第 5 步:安全约束与团队约定
给技能包加一页「安全约定」,放在 skills/README.md 末尾:
## 安全约定
- 第三方技能一律先读 `SKILL.md` 再装,装前跑 `skills-ref validate`。
- 涉及写文件、删分支、推送、发版的技能,一律在正文最后一步把决定权交回用户。
- 技能里不写死密钥、Token、内网地址;需要凭据的走环境变量。
- 技能目录进仓库前过一遍 `git diff --cached`,确认没有误提交敏感内容。
这几条不是形式主义——技能是 Agent 的操作说明书,说明书里写着「直接推 main 分支」,Agent 就会照做。
6.7 常见翻车现场
| 症状 | 原因 | 改法 |
|---|---|---|
| Agent 从不主动用这个技能 | description 没写触发场景 |
把用户会说的词写进去 |
| 技能加载了但做错事 | 正文是散文不是步骤 | 改成编号步骤,一条一步 |
| 每次都烧一堆 token | 细节全塞正文 | 拆进 references/ |
| 换个工具就失效 | 用了某家的私有字段 | 守住规范六个字段 |
skills-ref 报 name 不合法 |
大写、连续连字符、或和目录名不一致 | 按 ^[a-z0-9]+(-[a-z0-9]+)*$ 改 |
| 装了但看不见 | 文件名不是 SKILL.md,或权限被 deny |
查大小写与权限配置 |
| 脚本在不同机器上表现不同 | 依赖没写清 | 脚本自包含,或在文档里写明依赖 |
动手改
- 把你的三个技能目录建好,逐个跑
skills-ref validate,把报错逐条修掉 - 给
release-notes加一个scripts/collect-commits.sh,并把分类规则下沉到references/categories.md - 在两个工具里各试一次:先让 Agent 主动触发(说一句「帮我写个提交信息」),再用
/技能名手动触发,对比两种路径的表现 - 给技能包写一页安全约定,贴进仓库
README.md
小结
- 技能包 = 若干技能 + 一份说明 + 一套分发方式,提交进仓库就是团队资产
- 三条边界:只写规范不写实现、一个技能只管一件事、描述写清触发场景
- 分层落地:正文 ≤ 100 行,脚本干确定性活儿,长资料进
references/,模板进assets/ - 跨工具分发:进
.claude/skills/给团队,装个人目录给自己 - 安全约定写进仓库:第三方技能先读先验、副作用动作交回用户、凭据走环境变量
下一站:脚手架 Harness,看看技能之外,模型要想真正干活还需要什么 🐸