首页 › tutorials › 从零构建提交信息生成Skill

概述

本教程带你从零构建一个提交信息生成 Skill(commit-message generator)——它会读取你暂存的代码变更,自动产出符合 Conventional Commits 规范的提交信息草稿。借此案例,你将完整掌握 Claude Code Skill 的核心机制:SKILL.md 的 YAML frontmatter、渐进式披露(progressive disclosure)、脚本封装与触发调试。适合已能基本使用 Claude Code、想封装第一条自定义能力的中级读者。

前置条件


第一步:搞清楚 Skill 到底是什么

很多人把 Skill、Slash 命令、MCP、CLAUDE.md 混为一谈。先花一分钟厘清边界,后面才不会选错工具:

能力载体 本质 加载时机 适合场景
CLAUDE.md 静态上下文/规则 每次会话全量注入 团队规范、编码风格、常驻约束
Slash 命令 一段提示词的快捷方式 用户主动输入 /xxx 固定流程的提示词复用
MCP 服务器 外部工具/数据源协议 显式连接后可调用 接入数据库、API、第三方系统
Skill 文件系统能力包 Claude 按语义自动判断是否加载 可复用的、有步骤的专业工作流

关键差异:CLAUDE.md 是"总在场"的背景,而 Skill 是"按需登场"的专家。Skill 的精髓在于 progressive disclosure——平时只把一段 description 摆在货架上,Claude 判断"现在需要这位专家"时,才把整本"操作手册"加载进上下文。这正是它比把所有规则塞进 CLAUDE.md 更省 Token、更精准的原因。

一句话记忆:CLAUDE.md 是公司的《员工手册》,Skill 是你随叫随到的「外包专家」,Slash 命令是你按下的「快捷按钮」,MCP 是接进系统的「外接设备」。

第二步:为什么拿"提交信息生成"练手

选择第一个实战 Skill 有三个标准:高频、自包含、可验证。提交信息生成完美命中:

更重要的是,它能完整覆盖一个 Skill 的所有要素:需要脚本提取 diff、需要参考资料记录 type 列表、需要正文指导 Claude 如何组织语言、需要 frontmatter 让 Claude 在合适时机自动触发——麻雀虽小,五脏俱全。

第三步:创建项目骨架

Skill 可以放在两个位置:

我们做的是一个通用工具,放用户级最合适。先建目录:

mkdir -p ~/.claude/skills/commit-message/scripts
mkdir -p ~/.claude/skills/commit-message/references

最终目录结构如下:

~/.claude/skills/commit-message/
├── SKILL.md                    # 入口文件(必需)
├── scripts/
│   └── staged-diff.sh          # 提取暂存区差异的脚本
└── references/
    └── conventional-commits.md # 规范速查(按需加载)

常见问题:目录名必须和 frontmatter 里的 name 字段一致,且只能是小写字母、数字、连字符(kebab-case),最长 64 字符。写成 commit_message 或 CommitMessage 都会导致加载失败。

第四步:编写 SKILL.md 的 frontmatter

SKILL.md 顶部是一段 YAML frontmatter,用 --- 包裹。其中只有两个字段是必填且决定生死的:name 和 description。

---
name: commit-message
description: 生成符合 Conventional Commits 规范的 Git 提交信息。当用户准备提交代码、
  询问"该怎么写 commit message"、"帮我写提交信息"、暂存了变更想总结改动,
  或者在提交前想确保信息规范时使用。读取暂存区的 git diff,产出可直接复制的
  提交信息草稿,包含 type、scope、subject 与可选的 body。
---

这里有一个反直觉但至关重要的设计:description 的写法直接决定 Skill 能否被触发。Claude 不会看到你的正文,它只看这段描述来决定"要不要请这位专家出场"。所以好的 description 必须同时回答两个问题:

  1. 这个 Skill 干什么(What)
  2. 什么情况下该用它(When)

写 description 的三条经验法则:

常见问题:把 description 写成 "一个关于提交的工具" 这种废话——Claude 永远不知道何时该调用它。务必具体到"什么场景 + 产出什么"。

第五步:编写正文指令(渐进式披露的灵魂)

frontmatter 之下就是 Markdown 正文。正文要精简——官方建议控制在 500 行以内。原则是:让 Claude 一眼读懂工作流,细节丢给脚本和参考资料。

# 提交信息生成

## 何时使用
用户准备 `git commit`、询问如何写提交信息、或希望总结暂存的改动时。

## 工作流程
1. 运行 `scripts/staged-diff.sh` 获取当前暂存区的变更摘要
2. 如果暂存区为空,提示用户先 `git add`,不要自行 add
3. 分析变更,判断本次提交的主导 type(参考 `references/conventional-commits.md`)
4. 产出提交信息,格式:`<type>(<scope>): <subject>`
5. 把信息展示给用户,**只生成草稿,绝不自动执行 commit**

## 输出规范
- subject 用祈使句、现在时,首字母小写,结尾不加句号,不超过 50 字符
- 当改动跨多个不相关模块时,建议拆分为多条提交信息而非一条大杂烩
- body 只在有非显而易见的背景时才写,每行不超过 72 字符

## 重要约束
- **只读 git diff,只生成建议**:任何 `git commit`、`git push` 都必须由用户确认后手动执行
- 不要为了凑 type 而强行归类;实在无法判断就用 `chore`

注意最后那条"重要约束"——这与"不要自动 commit"的工程纪律完全一致。Skill 的正文里要明确写死这类护栏,避免 Claude 自作主张。

常见问题:把所有 Conventional Commits 的细则全塞进正文——会让 SKILL.md 臃肿、每次加载都烧 Token。正确做法是把完整规范放进 references/,正文里只留"按需查阅"的指引。这就是渐进式披露。

第六步:封装脚本(bundled vs separated)

Skill 里的脚本分两种风格,要按复杂度选择:

提取暂存区差异是典型的"分离脚本"场景——它有健壮性处理(空暂存区、二进制文件),值得独立成文件。新建 scripts/staged-diff.sh:

#!/usr/bin/env bash
# 提取暂存区的变更摘要,供提交信息生成使用
set -euo pipefail

# 确认处于 git 仓库
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
  echo "ERROR: 当前目录不是 git 仓库" >&2
  exit 1
fi

# 获取暂存区变更的文件名清单(带状态码)
staged_files=$(git diff --cached --name-status)

if [ -z "$staged_files" ]; then
  echo "NOTICE: 暂存区为空,请先 git add 需要提交的文件。"
  exit 0
fi

echo "===== 暂存文件清单 ====="
echo "$staged_files"
echo ""
echo "===== 变更统计 ====="
git diff --cached --stat
echo ""
echo "===== 实际差异(截断超长内容)====="
git diff --cached | head -200

赋可执行权限(这一步常被遗漏,会导致 Skill 调用时脚本报权限错误):

chmod +x ~/.claude/skills/commit-message/scripts/staged-diff.sh

单独测试脚本,确认能跑:

cd ~/your-project
git add some-file.py
bash ~/.claude/skills/commit-message/scripts/staged-diff.sh

预期结果:依次输出文件清单、变更统计、实际差异内容三段。若暂存区为空,则输出提示并正常退出。

第七步:准备按需加载的参考资料

references/conventional-commits.md 是 Skill 的"工具书",平时不加载,只有 Claude 需要判定 type 时才翻开。内容保持速查风格:

# Conventional Commits 速查

## type 取值
- feat:     新功能(用户可感知)
- fix:      Bug 修复
- docs:     仅文档变更
- style:    代码格式(不影响逻辑:空格、分号等)
- refactor: 既非新增功能也非修 Bug 的重构
- perf:     提升性能的改动
- test:     增加/修改测试
- build:    构建系统或外部依赖(webpack、npm 等)
- ci:       CI 配置文件与脚本
- chore:    杂项(不修改 src 或测试的其他改动)
- revert:   回退某次提交

## 格式
<type>(<scope>): <subject>
<空行>
<body>
<空行>
<footer>

## 示例
feat(auth): add OAuth2 login flow
fix(api): handle null pointer in user lookup
docs: update README installation steps

这套"正文 → 脚本 → 参考资料"的三层结构,就是渐进式披露的标准落地形态。Claude 每次只加载它当前真正需要的层。

第八步:安装与验证

Skill 无需显式安装——放到正确目录即生效。验证它是否被识别:

claude  # 启动交互式会话

进入会话后,输入一句自然语言触发:

我刚改了登录模块,帮我看看暂存了什么、该怎么写提交信息

预期结果:Claude 识别到"提交信息"意图,自动加载 commit-message Skill,运行脚本、给出类似下面的草稿:

feat(auth): add remember-me checkbox to login form

- persist session token when checkbox is checked
- clear token on explicit logout

如果没触发,可以用 /skills 命令查看已加载的 Skill 列表,确认 commit-message 是否在册、description 是否被正确解析。

第九步:description 触发调试(最高频的坑)

Skill "装了却不触发"是新手最常踩的坑,根因 90% 在 description。排查清单:

  1. YAML 缩进/语法错误:frontmatter 解析失败时,整个 Skill 会被静默忽略。用 cat -A SKILL.md | head -5 检查是否有隐藏的 Tab 字符——YAML 只认空格。
  2. 触发词太抽象:把 "git 工具" 改成带场景的 "生成 Conventional Commits 提交信息,当用户准备 commit……"。
  3. 与其他 Skill 抢触发:多个 Skill 描述重叠时,Claude 可能选错。确保每个 Skill 的"何时使用"互斥。
  4. 误触发(过宽):用户只想看 diff 却被拉起提交信息——在 description 里收紧边界,比如"仅当用户明确要写提交信息时"。
  5. 目录名与 name 不一致:git rev-parse 式的低级错误,但确实常发生。

一个调试小技巧:临时把 description 改得极简极宽(如 "处理任何与 git 提交相关的事"),先确认能触发,再逐步收窄到精准范围。

第十步:迭代、复用与分享

Skill 跑通后,三条进阶路径:

完整实战案例:端到端走一遍

假设你在 ~/demo 仓库刚改完一个 API 的空指针处理:

cd ~/demo
# 修复 bug
sed -i 's/return user.name/return user?.name ?? "anonymous"/' api/user.py
git add api/user.py

启动 Claude Code,说一句"帮我把这次改动整理成提交信息"。你将看到完整的自动流程:

  1. Claude 判断意图 → 加载 commit-message Skill
  2. 运行 scripts/staged-diff.sh → 拿到 diff
  3. 按需查阅 references/conventional-commits.md → 判定为 fix
  4. 产出草稿并展示,等待你确认

最终你会拿到一条可直接复用的信息:

fix(api): guard against null user in name lookup

整个过程没有外部 API、没有密钥、完全离线,且 Claude 始终只扮演"建议者"——git commit 这一步始终留给你手动执行。

Skill 加载与执行流程

flowchart TD
    A[用户在会话中说话] --> B{Claude 扫描所有 Skill 的 description}
    B -->|语义匹配| C[自动加载 commit-message 的 SKILL.md 正文]
    B -->|不匹配| Z[不加载任何 Skill]
    C --> D[按正文工作流执行]
    D --> E[运行 scripts/staged-diff.sh 提取 diff]
    E --> F{需要判定 type?}
    F -->|是| G[按需加载 references/conventional-commits.md]
    F -->|否| H[直接生成]
    G --> H
    H --> I[产出提交信息草稿]
    I --> J[展示给用户,等待确认]
    J --> K[用户手动执行 git commit]

这张图揭示了渐进式披露的两层"按需":第一层,description 不命中则整个 Skill 不加载;第二层,正文加载后,references 仍只在需要时才被翻开。Token 始终花在刀刃上。

延伸阅读

训练营适用性评估

维度 评估
适合训练营类型 Claude Code 入门到进阶营、AI 工程化实战营、开发者效率提升营
学员基础 能独立用 Git、用过 Claude Code 基本对话
教学时长 讲授 45 分钟 + 动手实操 60 分钟,合计约 2 课时
交付物 一个可运行的用户级 Skill,及一份可提交到团队的 Skill 目录
难度 ⭐⭐⭐(中等偏低),适合作为"Skill 三件套"教学的首个落地案例

本案例特别适合作为训练营里"从使用者到构建者"的转折点——学员第一次亲手把一段重复劳动封装成 Claude 能自动调用的能力,这种正反馈往往成为持续探索 Agent 工程的起点。

参考来源

  1. Extend Claude with skills — Claude Code Docs — 官方 Skill 开发文档,frontmatter 字段、目录约定与渐进式披露规范的权威来源
  2. How to create custom skills — Claude Help Center — 官方帮助中心,从零创建 Skill 的图文步骤指引
  3. anthropics/skills — GitHub — 官方示例 Skill 仓库,正文写法与目录结构的最佳范本
  4. Claude Code Skills: How to Set Them Up and Use Them — dev.to — 社区技术博客,含触发调试与踩坑实录
  5. How to Build Claude Code Skills: 5 Examples — fp8.co — 含 SKILL.md 规范速查与多个可复用示例

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入