首页 › tutorials › 造智能提交技能:diff自动转规范commit

概述

本教程以从零打造一个「智能提交(smart-commit)」技能为线索,带你完整走通 Claude Code 技能的开发全流程:解剖结构、目录约定、frontmatter 字段、动态上下文注入、参数替换、支持文件(渐进披露)、可执行脚本、权限预授权、触发调试,以及用 skill-creator 做量化评估与迭代。学完后你不仅能照葫芦画瓢做出这个提交技能,还能迁移到任意自定义工作流。适合已经装通 Claude Code、想把自己的重复操作沉淀成可复用技能的开发者。

前置条件


第一步:先搞懂一个技能到底由什么构成

Claude Code 的技能(Skill)遵循开放的 Agent Skills 标准。它的物理形态非常朴素——一个目录,里面至少有一个 SKILL.md:

my-skill/
├── SKILL.md          # 入口文件(必需):frontmatter + 指令
├── references/       # 可选:详细参考文档,按需加载
├── examples/         # 可选:示例输出,告诉模型期望格式
└── scripts/          # 可选:可执行脚本,由模型调用而非读入

SKILL.md 由两部分组成:

  1. YAML frontmatter(夹在两个 --- 之间):声明元数据,告诉 Claude「这是什么、什么时候用、能用哪些工具」。
  2. Markdown 正文:Claude 被触发后真正遵守的指令。

一个关键认知:正文不是常驻上下文。技能的 description 会常驻(让 Claude 知道有这个能力),但正文只有在被触发后才进入上下文,且整个会话期间持续存在。所以正文要写得精炼——官方建议控制在 500 行以内,详细参考资料拆到支持文件里。

技能存放在哪里,决定了谁能用

级别 路径 生效范围
企业级 受管设置(managed settings) 组织内所有用户
个人级 ~/.claude/skills/<name>/SKILL.md 你的所有项目
项目级 .claude/skills/<name>/SKILL.md 仅当前项目
插件级 <plugin>/skills/<name>/SKILL.md 启用该插件处

同名时的覆盖优先级:企业 > 个人 > 项目。项目级技能甚至能覆盖内置的 /code-review。本教程用个人级目录,这样你在任何项目里都能用 /smart-commit。

小贴士:Claude Code 会实时监听技能目录的变化——新增、编辑、删除技能在当前会话内无需重启即可生效(前提是会话启动时该 skills 目录已存在)。


第二步:规划「智能提交」技能的设计

动手前先想清楚三件事,避免做出一个「能触发但不好用」的技能:

  1. 它干什么:读取已暂存的改动(git diff --staged),按 Conventional Commits 规范生成提交信息,必要时直接提交。
  2. 谁触发它:提交是有副作用的操作(会改变仓库历史),我们不希望 Claude 自作主张提交——所以设 disable-model-invocation: true,只能由你手动 /smart-commit 触发。
  3. 要展示哪些技能特性(教学目的): - 动态上下文注入 !command`:把实时 diff 注入提示 -$ARGUMENTS参数:支持--dry-run只生成不提交 - 支持文件:把提交类型目录放进references/(渐进披露) - 可执行脚本:scripts/validate-scope.sh校验 scope -allowed-tools:预授权 git 命令,免反复确认 -disable-model-invocation`:控制触发主体

设计表如下:

设计点 取值 理由
触发方式 仅手动 /smart-commit 提交有副作用
权限 预授权 git diff/status/log/commit 减少打断
参数 $ARGUMENTS,支持 --dry-run 安全演练
上下文注入 git diff --staged、git status 让模型看到真实改动
支持文件 references/commit-conventions.md 大段规范不污染主文件
脚本 scripts/validate-scope.sh 确定性校验 scope

第三步:创建目录与 SKILL.md 骨架

mkdir -p ~/.claude/skills/smart-commit/{references,scripts}

注意:目录名就是命令名。.claude/skills/smart-commit/SKILL.md 会生成 /smart-commit。frontmatter 里的 name 字段只是显示名,不改变你输入的命令(插件根 SKILL.md 是唯一例外)。

创建 ~/.claude/skills/smart-commit/SKILL.md,先写一个最小骨架验证它能被识别:

---
name: smart-commit
description: Analyzes staged git changes and drafts a Conventional Commit message. Use when the user wants to commit, asks for a commit message, or says "提交".
---

# Smart Commit

骨架占位:稍后填充。

预期结果:在任意 git 项目里启动 Claude Code,输入 /sm 应当能在自动补全里看到 /smart-commit。输入「What skills are available?」应能在列表里看到它。如果看不到,多半是 YAML 写错了——可以用 claude --debug 启动查看解析错误(YAML 损坏时,技能正文仍会以空元数据加载,所以 /smart-commit 也许能跑,但自动触发会失效)。


第四步:写 frontmatter——技能的「契约」

frontmatter 所有字段都可选,但 description 强烈推荐。下面是我们这个技能的完整 frontmatter,每一行都很关键:

---
name: smart-commit
description: Analyzes staged git changes and drafts a Conventional Commit message. Use when the user wants to commit, asks for a commit message, or says "提交/commit". Refuses to commit secrets.
disable-model-invocation: true
allowed-tools: Bash(git diff *), Bash(git status *), Bash(git log *), Bash(git commit *)
argument-hint: [--dry-run]
---

字段详解:

字段 作用 本例取值
name 技能列表中的显示名 smart-commit
description Claude 据此判断何时用;前 1536 字符会进入技能清单 详细描述触发场景
disable-model-invocation true 则 Claude 不会自动触发,仅手动 true(提交有副作用)
allowed-tools 技能激活期间免确认使用的工具 预授权四类 git 命令
argument-hint 自动补全时显示的参数提示 [--dry-run]

description 写法要点:把最核心的使用场景放在最前面。因为技能清单里每条描述+when_to_use 合计在 1536 字符处截断,靠后的关键词可能被砍掉。先说「做什么」,再补「何时用」。

其他常用字段(本例暂未用,但开发复杂技能时必备):


第五步:写主体指令 + 动态上下文注入

这是技能的核心。关键是让 Claude 看到真实的暂存改动,而不是靠猜。Claude Code 的 !command`` 语法会在把正文送给 Claude 之前先执行命令,用输出替换占位符:

---
name: smart-commit
description: Analyzes staged git changes and drafts a Conventional Commit message. Use when the user wants to commit, asks for a commit message, or says "提交/commit". Refuses to commit secrets.
disable-model-invocation: true
allowed-tools: Bash(git diff *), Bash(git status *), Bash(git log *), Bash(git commit *)
argument-hint: [--dry-run]
---

# Smart Commit

为当前已暂存的改动生成 Conventional Commit 信息。

## 已暂存的改动(实时注入)
!`git diff --staged`
!`git status --short`

## 最近 5 条提交(对齐项目既有风格)
!`git log -5 --pretty=format:%s`

## 指令
1. 阅读上方的暂存 diff。若 diff 为空,告知用户「没有已暂存的改动」并停止。
2. 依据 references/commit-conventions.md 判定提交类型(feat/fix/docs/refactor/test/chore/perf/style/build/ci)。
3. 从改动路径推断一个简洁的 scope(如 `auth`、`api`)。
4. 写标题行:`<type>(<scope>): <subject>`,subject ≤ 50 字符、祈使语气、首词小写、句尾不加句号。
5. 改动非平凡时,补 body 说明「为什么」改。
6. 若 `$ARGUMENTS` 含 `--dry-run`:只打印拟用的提交信息,**不要提交**,到此结束。
7. 否则执行:`git commit -m "<title>" -m "<body>"`。

## 安全护栏
- 若 diff 中出现疑似密钥/令牌(如 AKIA、-----BEGIN、长 hex/token 串),**拒绝提交并警告用户**。
- subject 必须小写首词、无句尾句号。
- scope 用 scripts/validate-scope.sh 校验;若脚本判定不合法,则不带 scope。

几个易错点:


第六步:加支持文件——渐进披露的精髓

把 Conventional Commits 的完整类型目录放进 references/commit-conventions.md,主文件只放一句指引。这样大段规范平时不进上下文,需要时才被加载:

~/.claude/skills/smart-commit/references/commit-conventions.md:

# Conventional Commits 类型目录

| type | 含义 | 示例 |
|:--|:--|:--|
| feat | 新功能 | feat(auth): 支持扫码登录 |
| fix | Bug 修复 | fix(api): 修复分页越界 |
| docs | 文档 | docs(readme): 更新安装步骤 |
| refactor | 重构(不改行为) | refactor(core): 拆分调度器 |
| perf | 性能优化 | perf(db): 给查询加索引 |
| test | 测试 | test(auth): 补登录边界用例 |
| build | 构建系统/依赖 | build(npm): 升级到 vite 5 |
| ci | CI 配置 | ci(github): 增加缓存步骤 |
| chore | 杂项 | chore: 整理示例数据 |
| style | 格式 | style: 统一缩进 |

## Breaking Change
在 footer 写 `BREAKING CHANGE: <说明>`,或在 type 后加 `!`,如 `feat(api)!: 重命名 /users 为 /accounts`。

在 SKILL.md 里引用它(前面正文已经引用了 references/commit-conventions.md),Claude 才知道这个文件的存在和加载时机。这是把「几百行规范」挡在常驻上下文之外的标准手法——和把 CLAUDE.md 里膨胀成操作流程的内容拆成技能是同一种思路。


第七步:加可执行脚本——把确定性逻辑交给代码

让模型判断 scope 容易飘忽,不如写个脚本兜底。脚本是被执行的,不会读进上下文。

~/.claude/skills/smart-commit/scripts/validate-scope.sh:

#!/usr/bin/env bash
# 用法: validate-scope.sh <scope> <allowed-scopes-file>
# 退出码 0=合法,1=非法
set -euo pipefail
scope="${1:-}"
allow_file="${2:-}"

# 没给 scope 视为合法(允许无 scope 提交)
[ -z "$scope" ] && exit 0
# 没有白名单文件视为合法
[ -z "$allow_file" ] && exit 0
[ -f "$allow_file" ] || exit 0

if grep -Fxq -- "$scope" "$allow_file"; then
  exit 0
else
  echo "scope '$scope' 不在允许列表中" >&2
  exit 1
fi

赋予执行权限:

chmod +x ~/.claude/skills/smart-commit/scripts/validate-scope.sh

在 SKILL.md 里用 ${CLAUDE_SKILL_DIR} 引用脚本路径——这个变量无论技能装在个人级、项目级还是插件级都能正确解析(需 v2.1.196+ 的 ${CLAUDE_PROJECT_DIR} 适用于引用项目内文件):

## scope 校验
运行 `bash ${CLAUDE_SKILL_DIR}/scripts/validate-scope.sh "<scope>" ./allowed-scopes.txt`,
退出码 0 才采用该 scope,否则不带 scope。

可选:在项目根放一个 allowed-scopes.txt(每行一个 scope),技能就会校验 scope 是否合规——这是把团队约定变成机器可执行规则的典型做法。


第八步:配置参数——--dry-run 的分支

前面 frontmatter 已经声明 argument-hint: [--dry-run],正文用 $ARGUMENTS 接收全部参数。你也可以用 $0、$1 取按位置的参数,或在 frontmatter 声明 arguments: [scope] 后用 $scope。

完整变量速查:

变量 含义
$ARGUMENTS 调用时传入的全部参数
$N / $ARGUMENTS[N] 第 N 个参数(0 基)
${CLAUDE_SKILL_DIR} 技能 SKILL.md 所在目录
${CLAUDE_PROJECT_DIR} 项目根目录
${CLAUDE_SESSION_ID} 当前会话 ID(可用于日志)
${CLAUDE_EFFORT} 当前推理力度 low/medium/high/xhigh/max

带空格的参数要加引号:/smart-commit --dry-run 中 $ARGUMENTS 展开为 --dry-run。


第九步:测试与调试

进入一个练习仓库,做几处改动并暂存:

git add -A

手动触发

/smart-commit --dry-run

预期:Claude 读到注入的 diff,按规范生成提交信息并打印,不提交。确认无误后:

/smart-commit

预期:生成信息并执行 git commit。由于 allowed-tools 预授权了 git commit,过程中不会再弹权限确认。

验证它不会被自动触发

因为设了 disable-model-invocation: true,它的描述不进入上下文,Claude 不会主动用它。你可以这样确认:直接说「帮我把改动提交」,Claude 通常会走自己的流程而不会触发本技能——这正是我们想要的(提交必须由你显式发起)。

调试清单


第十步:用 skill-creator 做量化评估

「能触发」不等于「好用」。要验证,得做基线对比:收集几条真实提示,分别在「启用技能」和「禁用技能」的新会话里跑,比较结果。

skill-creator 插件把这个循环自动化了。安装:

/plugin install skill-creator@claude-plugins-official

若提示找不到插件,先刷新市场:

/plugin marketplace update claude-plugins-official
/reload-plugins

然后让 Claude 自己评估你的技能:

evaluate my smart-commit skill with skill-creator

它会:

实战建议:给 smart-commit 准备这几类用例——纯功能新增(期望 feat)、纯 bug 修复(期望 fix)、含疑似密钥(期望拒绝)、--dry-run(期望不提交)。跑一轮 benchmark,看命中率有没有因为加了 references 文件而提升。


第十一步:分享与分发

场景 做法
团队共享 把 .claude/skills/ 提交进版本库
跨项目复用 放 ~/.claude/skills/,或打包成插件
组织级下发 通过 managed settings 分发

打包成插件还能顺带带上 agents、hooks、MCP 服务器。如果担心别人项目里的技能给自己开了过宽的工具权限——记住:项目级技能的 allowed-tools 在你接受 workspace 信任对话框后才生效,检视陌生仓库的技能再决定是否信任。


实战案例:完整目录一览

到这一步,你的技能目录长这样:

~/.claude/skills/smart-commit/
├── SKILL.md                              # 入口:frontmatter + 指令 + 注入
├── references/
│   └── commit-conventions.md            # 类型目录(渐进披露)
└── scripts/
    └── validate-scope.sh                # scope 校验脚本

完整 SKILL.md(把前面碎片拼起来):

---
name: smart-commit
description: Analyzes staged git changes and drafts a Conventional Commit message. Use when the user wants to commit, asks for a commit message, or says "提交/commit". Refuses to commit secrets.
disable-model-invocation: true
allowed-tools: Bash(git diff *), Bash(git status *), Bash(git log *), Bash(git commit *)
argument-hint: [--dry-run]
---

# Smart Commit

为已暂存改动生成 Conventional Commit 信息。

## 已暂存的改动(实时注入)
!`git diff --staged`
!`git status --short`

## 最近提交风格
!`git log -5 --pretty=format:%s`

## 指令
1. 读上方 diff。空则回复「没有已暂存的改动」并停止。
2. 依 references/commit-conventions.md 定 type。
3. 从路径推 scope,用 `bash ${CLAUDE_SKILL_DIR}/scripts/validate-scope.sh "<scope>" ./allowed-scopes.txt` 校验。
4. 标题:`<type>(<scope>): <subject>`,subject ≤ 50 字符、祈使、小写首词、无句尾句号。
5. 非平凡改动补 body 说「为什么」。
6. 若 `$ARGUMENTS` 含 `--dry-run`:只打印,不提交。
7. 否则 `git commit -m "<title>" -m "<body>"`。

## 安全护栏
- 疑似密钥/令牌(AKIA、-----BEGIN、长 token 串)→ 拒绝提交并警告。
- scope 校验不过则不带 scope。

试用流程:

cd ~/some-practice-repo
echo "// new feature" >> app.js
git add app.js
claude

在会话里:

/smart-commit --dry-run     # 先预览
/smart-commit               # 确认后真提交
git log -1                  # 验证结果

工作流程图

下图展示从开发到触发的完整链路:

flowchart TD
    A[识别重复工作流] --> B[规划: 触发主体/权限/参数]
    B --> C[创建 ~/.claude/skills/smart-commit/]
    C --> D[写 SKILL.md frontmatter]
    D --> E[写正文 + 动态注入 !`git diff`]
    E --> F[拆 references/ 支持文件]
    F --> G[加 scripts/ 可执行脚本]
    G --> H[手动 /smart-commit 测试]
    H --> I{行为正确?}
    I -- 否 --> J[claude --debug 排查]
    J --> E
    I -- 是 --> K[skill-creator 跑 evals]
    K --> L{基线达标?}
    L -- 否 --> M[调 description/正文]
    M --> K
    L -- 是 --> N[提交到仓库 / 打包插件分发]

技能内容的生命周期(理解为什么正文要精炼):

flowchart LR
    S1[description 常驻上下文] --> S2{被触发?}
    S2 -- 用户 /smart-commit 或 Claude 自动 --> S3[注入 !`cmd` 输出]
    S3 --> S4[整段正文进入上下文]
    S4 --> S5[整个会话持续存在]
    S5 --> S6{上下文填满?}
    S6 -- 压缩 --> S7[重挂最近一次调用<br/>前 5000 token, 共享 25000 预算]
    S6 -- 否 --> S5

常见问题与解决方案

Q:/smart-commit 不出现在补全里? 检查目录路径(~/.claude/skills/smart-commit/SKILL.md)、目录名拼写。若会话启动时该 skills 目录不存在,新建后需重启 Claude Code 才能监听。

Q:Claude 该自动用时没触发? 本技能故意设了 disable-model-invocation: true,所以这是预期行为。若你做的是自动触发型技能却不触发:把用户会说的关键词写进 description 头部;确认 description 没被 1536 字符截断(用 /doctor 看);用 /context 的 Skills 行看实际进上下文的大小。

Q:技能触发太频繁? 让 description 更具体,或干脆加 disable-model-invocation: true 改为纯手动。

Q:项目里技能很多,描述被截断? 技能清单预算是上下文窗口的 1%。可在 settings 里调 skillListingBudgetFraction(如 0.02)或环境变量 SLASH_COMMAND_TOOL_CHAR_BUDGET;低优先级的技能在 skillOverrides 里设为 "name-only" 省预算。

Q:担心技能里的脚本被滥用? 用户/项目/插件级技能的 !cmd` 注入可用 settings 的disableSkillShellExecution: true` 关闭(托管设置里设可防用户绕过)。内置和受管技能不受影响。

Q:想在隔离环境里跑,别污染主对话? frontmatter 加 context: fork(配 agent: Explore 走只读探索)。注意:fork 模式下子代理看不到你的对话历史,适合「有明确任务」的技能,不适合「风格约定」类参考型技能。


延伸阅读


训练营适用性评估

参考来源

  1. Extend Claude with skills — Claude Code Docs — 官方权威:frontmatter 字段表、动态上下文注入、支持文件、子代理执行、skill-creator 评估全流程
  2. Agent Skills 开放标准 — 跨工具技能规范;Claude Code 在其上扩展了调用控制、子代理执行与动态注入
  3. Claude Code Skill Frontmatter: Every YAML Option Explained — 15 个 frontmatter 字段的逐项示例与取舍说明
  4. Claude Code Skills: How to Set Them Up and Use Them — 面向新手的目录结构与上手流程
  5. anthropics/skills — GitHub — 官方技能实例库,可直接参考真实 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学通信知识星球海报-扫码加入