Skip to content

Skills

Skill 是把一段工作流打包成 Claude Code 能自主调用的能力。你不用告诉它"用 git-cleanup",你说"帮我清一下这个仓库的过期分支",Claude 自己就会去翻 skill 列表,找到匹配的那一个,然后按里面的说明书办事。

Skill 是什么

Skill 是一份 markdown 文件,头部有一段 YAML frontmatter 写明这个 skill 叫什么、什么时候应该用它。剩下的正文是给 Claude 看的操作手册,可以是文字说明、也可以是引用同目录下的辅助脚本。

Claude Code 每次会话启动时会扫描本地所有 skill,把 name 和 description 装进上下文。当你的任务描述和某个 skill 的 description 匹配上,Claude 会主动通过 Skill 工具把这份 markdown 完整读进来,作为本次任务的具体做法。用完之后 skill 内容才占上下文,没被匹配上的 skill 只占几十字的元数据,性价比很高。

Skill 和 CLAUDE.md、Hooks 的定位差别一句话说清楚。CLAUDE.md 是永远在场的项目背景,Hooks 是自动触发的固定动作,Skill 是按需调用的可复用工作流。

目录约定

Skill 也分层级,和 settings.json、CLAUDE.md 保持一致。

  • 用户级:~/.claude/skills/<skill-name>/SKILL.md,对当前用户所有项目都可见。
  • 项目级:./.claude/skills/<skill-name>/SKILL.md,只对当前项目生效,进 git 之后团队共享。

<skill-name> 就是 skill 的短名,和 frontmatter 里的 name 保持一致,全小写、连字符分隔。同一个 skill 目录下除了 SKILL.md,还可以放辅助脚本、模板、参考文档,Claude 会按 markdown 里的相对路径引用它们。

一个 skill 一个目录

不要把多个 skill 塞进同一个目录。每个 skill 都独立一个文件夹,方便打包分发、也让 Claude Code 的扫描更简单。

Frontmatter 字段

Frontmatter 是这份 skill 的门面。字段少但每一个都不能马虎。

  • name:skill 的短名,唯一标识。小写、连字符分隔,比如 git-cleanup
  • description:一句话说清"什么时候用它"以及"它做什么"。Claude 判断要不要匹配这个 skill 就看这一句,写得越具体越准。

一个高质量 description 的写法是先列触发场景,再列它擅长处理什么,最后附上不适用的边界。举个例子:

yaml
description: |
  帮用户清理 Git 仓库里的过期分支。触发场景:
  "清一下过期分支""删掉已经合并的分支""仓库分支太多了"。
  会做:列出已合并到 main 的本地和远程分支、按最近提交时间排序、
  交互式确认后批量删除。不做:删未合并分支、删受保护分支。

这样写让 Claude 判断匹配的准确率显著高于只写一句"清理 Git 分支"。

一个完整的例子:git-cleanup

.claude/skills/git-cleanup/SKILL.md

markdown
---
name: git-cleanup
description: |
  帮用户清理 Git 仓库里过期的、已经合并的本地和远程分支。触发场景:
  "清一下过期分支""删掉已经合并的分支""仓库分支太多了"
  "git 分支该收拾一下了"。会做:列出候选、按最近提交时间排序、
  交互确认后批量删除。不做:删未合并分支、删受保护分支(main / master / release/*)。
---

# git-cleanup

## 什么时候用

用户想清理已经合并进主分支的旧分支,减少 `git branch` 输出的噪音。
适合定期维护,也适合仓库交接前的整理。

## 操作步骤

1. 先跑 `git fetch --prune` 同步远程状态,避免误删还活跃的分支。
2. 用同目录下的 `scripts/list-merged.sh` 列出候选:

   ```bash
   bash .claude/skills/git-cleanup/scripts/list-merged.sh
   ```

   脚本会输出所有已合并到 main 且最近 30 天没有新提交的分支,
   格式:`<local|remote> <branch-name> <last-commit-date>`

3. 把候选列表展示给用户,让用户确认要不要删。用户没明确说"都删"
   之前,不要动手。
4. 收到确认后,本地分支用 `git branch -d <name>`,远程分支用
   `git push origin --delete <name>`。禁止使用 `-D` 强删。
5. 完成后总结:删了多少条、跳过多少条、剩下多少条。

## 边界

- 受保护分支列表:`main``master``release/*``hotfix/*`
  这些哪怕已合并也不能删。
- 未合并分支(`git branch --no-merged main` 里出现的)绝对不删。
- 如果用户明确指定要删某条未合并分支,先反问一次,得到二次确认再动。

.claude/skills/git-cleanup/scripts/list-merged.sh

bash
#!/usr/bin/env bash
set -euo pipefail

PROTECTED='^(main|master|HEAD|release/.*|hotfix/.*)$'
CUTOFF=$(date -d '30 days ago' +%s 2>/dev/null || date -v-30d +%s)

git for-each-ref --format='%(refname:short) %(committerdate:unix)' refs/heads refs/remotes/origin \
  | while read ref ts; do
      short=${ref#origin/}
      [[ "$short" =~ $PROTECTED ]] && continue
      [[ $ts -gt $CUTOFF ]] && continue
      if git merge-base --is-ancestor "$ref" main 2>/dev/null; then
        kind="local"; [[ "$ref" == origin/* ]] && kind="remote"
        echo "$kind $short $(date -d @$ts '+%Y-%m-%d' 2>/dev/null || date -r $ts '+%Y-%m-%d')"
      fi
    done

这套结构里有两点值得留意。第一,SKILL.md 的正文写得像给新手同事看的操作手册,步骤化、有约束、有边界。第二,凡是能用脚本表达的判定逻辑都放进 scripts/,让 markdown 保持精简。Claude 只需要按顺序按下按钮,而不需要自己重新推理判断规则。

Skill 和 Slash 命令的边界

初学者很容易把 Skill 和 slash 命令搞混,两者都能"打包一段流程"。差别只在一件事:谁来决定触发。

  • Slash 命令是用户显式触发。你输入 /git-cleanup,Claude 一定去执行。
  • Skill 是模型判断触发。你说"帮我清一下过期分支",Claude 读到匹配的 description 后主动调用。

两种触发方式各有场景。

Slash 命令适合精确控制。你想让每一次触发都完全一样、不想让 Claude 自作主张改流程,用 slash。比如 /deploy-staging,参数、步骤、顺序都固定死。

Skill 适合自然语言场景。你不想每次都记住 slash 命令的名字,你只想描述任务,让 Claude 自己找工具。适合一个团队里几十个可能用到的能力,全部靠斜杠列出来记不过来,靠 description 匹配就自然多了。

什么时候两个都做

高频、参数固定的流程做成 slash 命令,让用户能快速触发;低频、需要模型判断上下文的流程做成 skill。两者也可以并存,甚至可以让 slash 命令内部触发 skill。

description 是 skill 的命根子

skill 匹配不上,正文写得再好也白搭。花时间打磨 description,把"触发场景"和"不适用的边界"都写清楚,胜过写更多正文。

本教程为社区中文学习整理,非官方发布。Claude Code 属于 Anthropic。