Claude Code skills 怎么写:从第一个 skill 到带脚本、带参数的 skill
从零写一个 Claude Code skill:建目录、写 SKILL.md、测试;再讲放在哪里、怎么传参数、怎么带脚本和参考文件、怎么控制谁能调用,以及 Claude Code 团队总结的写 skill 的几条经验。
本文根据公开分享整理,本站尚未实测。操作前请对照文末的原始来源。
本页目录(14 节)
这篇教程解决一个问题:把你反复交代给 Claude Code 的那套做法,写成一个 skill,以后一句话或一个命令就能用。 步骤和字段来自官方文档,写法上的经验来自 Claude Code 团队的文章。
skill 是什么,什么时候该写一个
skill 是一个文件夹,里面至少有一个 SKILL.md 文件,写着给 Claude 的说明;还可以放脚本、参考资料和模板。Claude 在觉得相关时会自动加载它,你也可以用 /名字 直接调用。
官方给的判断标准:你发现自己总在往对话里粘贴同一段说明或同一份检查清单,或者 CLAUDE.md 里有一节已经长成了一套流程,就该写成 skill。
它和 CLAUDE.md 的区别在于加载时机:CLAUDE.md 每一轮都会加载;skill 的正文只在用到时才加载,所以很长的参考资料放在 skill 里几乎不占平时的上下文。
以前放在 .claude/commands/ 里的自定义命令已经并入 skills,旧的命令文件继续可用。
1建目录
先建一个个人 skill,它在你这台电脑的所有项目里都能用:
mkdir -p ~/.claude/skills/summarize-changes
目录名就是以后输入的命令名。
2写 SKILL.md
SKILL.md 有两部分:最上面用 --- 包起来的头部信息,告诉 Claude 什么时候用这个 skill;下面是 Claude 执行时要遵循的说明。
把下面的内容保存为 ~/.claude/skills/summarize-changes/SKILL.md(这是官方文档里的例子):
---
description: Summarizes uncommitted changes and flags anything risky. Use when the user asks what changed, wants a commit message, or asks to review their diff.
---
## Current changes
!`git diff HEAD`
## Instructions
Summarize the changes above in two or three bullet points, then list any risks you notice such as missing error handling, hardcoded values, or tests that need updating. If the diff is empty, say there are no uncommitted changes.
其中 !`git diff HEAD` 这一行是“动态注入”:Claude Code 会先运行这条命令,把这一行换成命令的输出,然后才把内容交给 Claude。所以 Claude 看到说明的时候,当前的改动已经写在里面了。
3测试
打开一个 git 项目,随便改一个文件,启动 claude。两种方式都试一下:
让 Claude 自己判断要不要用,问一句和 description 对得上的话:
What did I change?
直接调用:
/summarize-changes
两种方式都应该得到一段简短的改动总结和一份风险列表。
放在哪里
skill 存在哪里,决定了哪些会话能用到它:
| 位置 | 路径 | 在哪里生效 |
|---|---|---|
| 个人 | ~/.claude/skills/<名字>/SKILL.md |
这台电脑上你的所有项目(不包括云端会话) |
| 项目 | .claude/skills/<名字>/SKILL.md |
这个仓库里的会话。提交到仓库后,团队里的人都能用 |
| 子目录 | <子目录>/.claude/skills/<名字>/SKILL.md |
在这个子目录或更深处启动的会话;从上层启动的会话在 Claude 处理到这里的文件时加载 |
| 插件 | <插件>/skills/<名字>/SKILL.md |
启用了这个插件的地方,命令是 /插件名:skill名 |
重名时,个人的优先于项目的。
想在团队里共享,最简单的办法就是把 .claude/skills/ 提交到仓库。
最重要的一个字段:description
头部的字段都是可选的,但 description 强烈建议写:Claude 靠它决定什么时候加载这个 skill。
Claude Code 团队的经验是:description 是写给模型看的触发条件,不是写给人看的功能介绍。
| 例子 | |
|---|---|
| 写得弱 | A comprehensive tool for monitoring pull request status across the development lifecycle. |
| 写得好 | Monitors a PR until it merges. Trigger on ‘babysit’, ‘watch CI’, ‘make sure this lands’. |
两个要点:
- 把用户平时会怎么说写进去。
- 最关键的用途放在最前面。
description加上when_to_use在列表里最多显示 1,536 个字符,skill 多了之后还可能被进一步截短。
控制谁能调用
| 设置 | 你能调用 | Claude 能自动调用 |
|---|---|---|
| 默认 | 能 | 能 |
disable-model-invocation: true |
能 | 不能 |
user-invocable: false |
不能 | 能 |
有副作用的 skill(提交代码、部署、发消息)建议加上 disable-model-invocation: true,只在你明确输入命令时才运行。
传参数
在正文里用占位符接收参数:
| 写法 | 含义 |
|---|---|
$ARGUMENTS |
你输入的全部参数 |
$ARGUMENTS[N] 或 $N |
第 N 个参数,从 0 开始 |
官方的例子:
---
name: migrate-component
description: Migrate a component from one language to another
---
Migrate the $0 component from $1 to $2.
Preserve all existing behavior and tests.
运行 /migrate-component SearchBar JavaScript TypeScript,$0、$1、$2 分别被换成这三个词。带空格的参数用引号括起来。
免去重复确认:allowed-tools
allowed-tools 让 Claude 在调用这个 skill 的那一轮里,可以不经你确认就使用列出的工具:
---
name: commit
description: Stage and commit the current changes
disable-model-invocation: true
allowed-tools: Bash(git add *) Bash(git commit *) Bash(git status *)
---
要清楚它的边界:
- 它只是免确认,不是限制。其他工具仍然可以用,照常走你的权限设置。
- 只在调用 skill 的那一轮有效,你发下一条消息时就失效。
- 别人仓库里的 skill 也可以给自己开权限。 官方特别提醒:在一个仓库里运行 Claude Code 之前,先看一眼仓库里的 skill 写了哪些
allowed-tools。
带上脚本和参考文件
skill 是一个文件夹,不只是一个 Markdown 文件。把详细资料拆出去,SKILL.md 只留概要和指引:
my-skill/
├── SKILL.md 必需:概要和指引
├── reference.md 详细的参考资料,需要时才加载
├── examples.md 用法示例,需要时才加载
└── scripts/
└── helper.py 工具脚本,被执行,不加载进上下文
在 SKILL.md 里要写明每个文件是什么、什么时候去读,Claude 才知道去用。官方建议 SKILL.md 控制在 500 行以内。
在正文里引用脚本时,用 ${CLAUDE_SKILL_DIR} 表示 skill 所在的目录,这样不管 skill 装在哪里,路径都是对的。例如:
python3 ${CLAUDE_SKILL_DIR}/scripts/helper.py .
放到子代理里运行
加上 context: fork,skill 会在一个子代理里运行,不占用主对话的上下文:
---
name: deep-research
description: Research a topic thoroughly
context: fork
agent: Explore
---
Research $ARGUMENTS thoroughly:
1. Find relevant files using Glob and Grep
2. Read and analyze the code
3. Summarize findings with specific file references
注意:子代理收到的只有 skill 的内容,看不到你之前的对话,所以说明要写得能独立看懂。只是一些指导原则、没有具体任务的 skill 不适合这样用。
Claude Code 团队写 skill 的几条经验
Anthropic 内部有几百个在用的 skill。Thariq 总结的经验里,对新手最有用的是这几条:
不要写 Claude 本来就知道的事。 Claude 会写代码,也能读你的代码库。skill 里应该写的是能让它跳出默认做法的信息。
建一个“坑”的清单。 这是 skill 里最有价值的部分,从实际出过的错里积累,持续更新。例如:
subscriptions 表只追加不修改。要的是 version 最大的那一行,不是 created_at 最新的那一行。
预发布环境在 Stripe 的回调没有真正处理时也会返回 200。真实状态要看 payment_events。
给目标和约束,不要把每一步都写死。 写成六条编号的 git 命令,Claude 就没法随机应变;写成“把这个提交摘到一个干净的分支上,解决冲突时保留原意,摘不过去就说明原因”效果更好。
一个 skill 只做一类事。 想包办太多的 skill 会让 Claude 搞不清什么时候该用它。
让它能记住东西。 skill 可以保存数据,比如一个只追加的日志文件。写每日站会的 skill 保留一份历史记录,Claude 就能看出和昨天相比变了什么。
需要用户提供的设置,存成配置文件。 比如要发到哪个频道:存在 skill 目录的 config.json 里;没有配置时让 Claude 先问用户,再把答案存下来。
好的 skill 都是慢慢长出来的。 多数好用的 skill 一开始只有几行说明和一个坑,之后每次 Claude 在某个地方出错,就补一条。
团队内部效果最明显的一类是“产品验证”:教 Claude 怎么测试、怎么确认代码真的能用。文章里说,这类 skill 值得让一位工程师花一周时间去做好。
常见问题
写好了,Claude 不用它
- 检查 description 里有没有用户平时会说的关键词;
- 问一句
What skills are available?,看它在不在列表里; - 换个说法,更贴近 description;
- 直接用
/名字调用。
如果头部的 YAML 写错了,skill 的正文仍然会加载,/名字 还能用,但 Claude 没法根据 description 来匹配。运行 claude plugin validate ~/.claude/skills(项目 skill 用 .claude/skills)可以找出头部解析不了的文件,需要 v2.1.233 或更高版本。
Claude 太爱用它
把 description 写得更具体;或者加 disable-model-invocation: true,改成只能手动调用。
一开始照着做,后来不照做了
- 每次都必须遵守的规则,改用 hook 来保证。hook 可以直接写在 skill 头部的
hooks字段里。 - 需要它酌情运用的指导,措辞要覆盖整个任务,比如写“每次修改后都运行测试”,不要只写“运行测试”。skill 的内容只在调用时加入对话一次,之后不会重新读取文件。
- 对话被压缩过的话,重新调用一次 skill。压缩后可能只保留 skill 开头的部分,所以最重要的说明放在
SKILL.md的最前面。
skill 多了,description 被截短
Claude Code 把所有 skill 的名字和描述放进上下文,总量有预算(模型上下文窗口的 1%)。超出时会先去掉你最少调用的那些 skill 的描述。运行 /skill-doctor 可以找出值得关掉的 skill。
自己建的个人 skill 不见了
到 ~/.claude/skills/.trash/ 里找。v2.1.280 之前的版本存在一个会把 skill 文件夹移进这里的问题;把文件夹移回 ~/.claude/skills/ 就能恢复,默认 30 天后会被清理。
下一步
- 官方的 skill 示例:https://github.com/anthropics/skills
- 想让 Claude 在运行时改写自身的行为和界面,那是 Mods 的范围,见 Claude Code Mods 是什么。