刚开始用 Claude Code 的时候,我最大的困惑不是它能力不够强,而是每次都要在提示词里重复一大堆背景、格式和边界条件。明明上一条任务刚交代过“提交信息按 Conventional Commits 规范写”,下一条任务它又忘了,重新提醒一遍,生成出来的东西依然不稳定。后来我把 Claude Code Skill 这套机制从头到尾学了一遍,才发现之前那些重复劳动其实完全没必要。
这篇东西写给两类人:一是刚接触 Claude Code、听说过 Skill 但不知道从哪下手的新手;二是已经在用提示词模板、但总觉得“夹生”的开发者。我会从 Skill 的本质讲起,再带你手把手写一个能用的技能,最后把我踩过的坑和排查思路全部分享出来。全程不整虚的,直接可落地。
1. 先把“什么是 Claude Code Skill”讲明白
1.1 一句话理解:Skill 就是给代理的“岗位手册”
你可以把 Claude Code 当成一个能力很强但记性不太好的新员工。它底子好,什么都能干,可是每次开工前你都得重新告诉它一遍流程、规范和输出格式。Skill 要解决的就是这件事:把某类任务的完整做事方法打包成一个文件夹,里面有说明文档、模板、示例代码,Claude Code 遇到相关需求时,自动“翻出”这本岗位手册照着执行。
一个 Skill 本质上是一个目录,目录里必须有SKILL.md。这个文件用 Markdown 写成,开头一段 YAML 元信息,后面是具体的操作指引。目录里还能放进其他辅助文件,比如示例代码、提示模板、参考文档,统一放在resources子目录下。Claude Code 启动时会扫描这些目录,把 Skill 的名称和描述加载进来,后续只要对话内容匹配上描述里的场景,它就会主动调用这个技能。
举个例子:你写了一个“单元测试生成器”的 Skill,描述里写了“适用于为新函数生成 pytest 单元测试,包含边界条件和异常用例”。之后只要你让 Claude Code 给某个函数写测试,它就会自动加载这个技能,按照你预设的测试风格、断言规范和代码组织方式输出,而不是每次自由发挥。
1.2 Skill 与提示词、CLAUDE.md、MCP 的分工
很多人会把这几样东西搞混,其实它们的定位完全不同。普通提示词是“一次性口头吩咐”,优点灵活,缺点是不稳定,这次写得详细就执行得好,下次写简单点就跑偏。CLAUDE.md 是项目的“长期记忆”,放在项目根目录,记录项目背景、技术栈、代码规范,让代理每次干活前先了解上下文,但它并不会针对某一类任务给出操作流程。
Skill 则是“按场景触发的操作手册”。它比 CLAUDE.md 更聚焦,比普通提示词更规范,而且可以在不同项目之间复用。还有一个容易混淆的是 Slash Command(斜杠命令)。Slash Command 需要你手动输入/某个命令才会执行,Skill 则靠模型根据对话内容自动判断是否调用。一个偏手动,一个偏自动。
MCP 则解决的是“代理能调用哪些外部工具”的问题,比如查数据库、读网页、操作文件系统。Skill 解决的是“面对一类任务应该按什么流程做”的问题。它们是不同层面的能力,后面我会专门讲怎么配合使用。
1.3 新手最容易错过的三个价值点
第一点是输出一致性。团队协作时,代码风格、提交格式、文档结构往往有明确规范,靠口头提醒永远不够,Skill 能把规范固化进每一次执行里。第二点是“跨项目复用”。你在这个项目里写好的代码审查 Skill,换个项目同样能用,因为技能目录是独立于项目的。第三点是上下文节省。把大段规则塞进提示词会占用宝贵的上下文窗口,而 Skill 是按需加载的,平时只是“技能列表里的一行描述”,真正被调用时才展开细节。
很多教程只讲“怎么建文件夹、怎么写 YAML”,不讲这些底层逻辑。但明白了它们,你后面设计自己的 Skill 时,思路会清晰很多。
2. 环境准备与目录结构:开工前的硬知识
2.1 安装 Claude Code 与创建 skills 目录
动手之前,先确认你的 Claude Code 是最新版本。我建议用官方推荐的安装方式,装完后在终端里输入claude能正常启动对话就算就绪。
接下来要搞清楚 Skill 的两个存放位置:
- 用户级目录:
~/.claude/skills/,所有项目都能用。 - 项目级目录:
.claude/skills/,只对当前项目生效。
如果你只有一个个人工作流,放用户级最省事。如果某个技能是团队项目专用的,比如“按本项目的接口文档规范写服务端代码”,那就放项目级。创建目录很简单:
mkdir -p ~/.claude/skills/git-commit-helper/resources后面我会以git-commit-helper为例带你完整写一个,这里先建立基本认知:每个技能一个子目录,子目录里必须有SKILL.md,辅助资源放resources。
这里有个新手最容易犯的错:有人直接在skills目录下放一个SKILL.md,以为这就是一个技能了。不对。正确结构是skills/技能名/SKILL.md。Claude Code 按子目录来识别技能边界,目录名才是技能标识。
2.2 SKILL.md 的文件结构与字段解析
一个标准的SKILL.md长这样:
--- name: git-commit-helper description: Use this skill when the user asks to generate a git commit message, or when a set of staged changes needs to be summarized into a commit. Produces Conventional Commits style messages with scope and body. --- # Git Commit Helper ## 你的任务 当用户提供 git diff 或变更说明时,生成符合 Conventional Commits 规范的提交信息。 ## 核心规则 1. 第一行必须为 `<type>(<scope>): <summary>` 2. type 使用:feat、fix、refactor、docs、test、chore、perf、ci 3. summary 不超过 50 个字符,不要句号 4. body 使用祈使句,说明“为什么”而不是“做了什么” ## 输出格式 给出 commit message 时,直接用代码块包裹,方便复制。这里的name是技能的唯一标识,建议全小写加连字符,不要用空格。description是重中之重,它的质量直接决定技能能不能被正确触发。描述里要写清楚两件事:什么时候触发、输出什么风格。不要写“这是一个强大的技能”这种废话,模型不看这个,它看的是触发条件。
正文部分就是你给代理的工作手册。用清晰的标题、列表、示例来组织,避免大段模糊叙述。记住,这份文档会被原封不动加载进上下文,所以它本身就是一段“高质量提示词”。
2.3 skill 的发现、触发与加载方式
Claude Code 加载 Skill 是自动的。启动后,模型会知道所有可用技能的名称和描述,但不会加载完整正文。它会在对话过程中判断当前任务是否匹配某个技能描述,匹配了就调用那份手册。
触发有两种场景。一种是模型主动触发:你说“帮我写个提交信息”,它看到git-commit-helper的描述匹配,就自动加载执行。另一种是手动指定:在对话里输入#,通常能唤出技能选择列表,选中后技能会直接进入上下文。如果你的描述写得不好,模型可能永远不主动触发这个技能,那就只能靠手动,非常尴尬。
另外要留意,Skill 完整正文是“按需加载”的,触发后仍会占用上下文。所以正文要精炼,不要把你的毕生所学全塞进去。能用资源文件解决的问题,就别写进主文档。
3. 完整实操:做一个能用的 git-commit-helper
3.1 场景与设计目标:一次只解决一类事
我建议新手第一个练手的 Skill 不要选“万能助理”这种大而全的方向,而是选一个边界清晰、输出好验证的小场景。“生成提交信息”就很合适:输入明确(git diff),输出明确(一段 commit message),不存在副作用,试错成本极低。
设计目标只有一个:给定一个 diff,输出符合团队规范、可读性强的提交信息。不需要自动提交,不需要生成 changelog,不需要分析历史记录。一次只解决一类事,这是 Skill 设计的金律。
3.2 编写 SKILL.md:描述要能“命中触发”
打开终端,进入技能目录,创建SKILL.md:
cd ~/.claude/skills/git-commit-helper然后写入以下内容。注意,这份文档的设计逻辑是:先告诉代理这个技能何时适用,再给出生成规则,最后给格式示例。顺序很重要,代理阅读时如果开头就知道“我该不该用这个技能”,后面的规则才有意义。
--- name: git-commit-helper description: Use for generating git commit messages. Trigger when the user provides a git diff, asks to commit changes, or mentions writing a commit message. Outputs Conventional Commits style with type, scope, and a brief body explaining why the change is needed. --- # Git Commit Helper 当用户需要提交信息时,按如下流程操作: 1. 查看用户提供的 `git diff`,如果用户没有提供,可以先执行 `git diff --staged` 获取暂存区变更,但要先询问用户确认。 2. 根据变更内容推断 type: - 新功能:`feat` - 修复 bug:`fix` - 重构且无功能变化:`refactor` - 文档变更:`docs` - 测试相关:`test` - 构建或依赖变更:`chore` - 性能优化:`perf` - CI 配置变更:`ci` 3. 根据变更文件判断 scope,例如 `api`、`auth`、`db`、`cli`。拿不准时不写 scope。 4. summary 使用祈使句现在时,不超过 50 个字符。 5. body 写“为什么”,而不是逐行翻译 diff,控制在 2-4 行。 输出时直接给出 commit message 代码块,不要附加解释性文字。这个技能的核心是“按类型处理”,而不是“自由发挥”。“根据变更内容推断 type”这一条,比你在提示词里说“你帮我写个提交信息”要稳定得多。
3.3 为 skill 挂资源文件:示例与模板
主文档已经能跑了,但为了提升输出质量,我建议加一个资源文件。新建resources/commit-examples.md,里面放几个高质量的示例:
# 高质量提交信息示例 feat(api): add pagination support to list endpoint The list endpoint previously returned all records at once, which becomes unsafe when the row count grows. Add limit and offset query parameters with sane defaults to keep the response size under control. fix(auth): refresh token before expiration check The session middleware was checking the token age first and rejecting requests even when a refresh token was available. Flip the order so that expired tokens can still trigger a refresh flow. test(db): cover row count edge case in migration Add a test that ensures empty tables can pass the new integrity check, preventing a regression in clean installs.然后在SKILL.md里加上一句指令:
- 生成后对照 `resources/commit-examples.md` 的风格检查一遍,确保长度和语气一致。为什么要把示例放到独立文件,而不是写进主文档?因为主文档里的内容每次都会加载,示例多了会白白占用上下文。资源文件则按需读取,只有在你明确要求对照时才加载。这种“主文档只写规则,资源文件放细节”的结构,是 Skill 和普通 Prompt 最关键的差异。
3.4 现场测试:从“不生效”到“按模板输出”
回到 Claude Code 会话里,先手动触发一次:
#git-commit-helper 请生成提交信息然后贴一段真实的git diff。比如某次修改给一个登录接口增加了验证码校验,换了两行逻辑。正常情况下,代理会输出类似这样的结果:
feat(auth): add captcha validation to login endpoint The login endpoint accepted requests without captcha, which made automated brute-force attempts viable. Validate the captcha token before checking credentials so that failed attempts can be rate-limited more effectively.如果它没触发,先别急着怪模型。检查你是不是把技能放在了错误的层级,或者description里没有出现和提问匹配的关键词。把description里的“generating git commit messages”改成更自然的表述,比如“when the user asks for a commit message”,这一小步在实测里能显著提升命中率。
再测第二种情况:不手动指定,直接说“提交一下刚才改的登录接口”,看它会不会自动调用这个技能。如果不会,大概率还是描述没写好。
4. 我踩过的坑和排查清单
4.1 目录层级和命名:九成新手都卡在这里
我自己实际测试下来,最最常见的坑就是目录结构不对。skills/git-commit-helper/SKILL.md是正确的,但有些人会写成skills/git-commit-helper.md,或者把SKILL.md直接放在skills根目录。原因很好理解:以为一个 Markdown 文件就是一个技能。但 Claude Code 以目录为边界,目录里所有资源都是这个技能的一部分。
技能目录的命名也影响触发。name字段里不要用大写字母、空格和中文,推荐kebab-case。比如code-reviewer、api-doc-generator。命名不好,在某些交互场景下会导致无法通过#正常选中。
另外,修改了技能文件后,最好新开一个会话再测试。Claude Code 的技能列表经常是在会话启动时加载的,你改完文件,老会话里的技能描述可能还是旧的。这一点让我一度怀疑技能是不是没生效,后来才发现是缓存问题。
4.2 description 的两种典型失败模式
描述写得太笼统是第一个失败模式。“当用户需要帮助时使用”——这个描述等于没写,几乎所有任务都能匹配,模型反而不知道该不该调用。每次都会尝试加载,结果就是上下文被无关的技能浪费掉。
第二个失败模式是描述写得像功能列表,比如“生成漂亮的提交信息、支持各种类型、自定义输出格式”。模型拿到这样的文本,很难提炼出“触发词”。好的描述应该像一句指令:
Use when the user asks to commit changes, generate a commit message, or needs a summary of a git diff.这句话把触发场景全部用动宾结构写清楚。我在实际使用中,几乎每次调整描述都能带来明显的触发概率提升。记住:描写实际任务,不是描写抽象能力。
4.3 资源路径失效与上下文冲突
如果你在SKILL.md里写“读取resources/example.md”,这里有个潜在问题:代理何时知道去读这个文件?如果主文档没有明确指示,它可能根本不会去读这个资源。我在初版技能里就吃过这个亏,主文档写了规则,但忘了说“请参考示例”,结果代理从来没看过示例文件。
正确的做法是在主文档中把“什么时候读资源文件”写清楚:
- 生成提交信息之前,先阅读 `resources/commit-examples.md` 中的示例,理解目标长度和语气,然后按相同风格生成。路径建议使用相对当前技能目录的路径,不要带前导/或~/。经验不足时我试过写绝对路径,换一台机器就失效了,相对路径可控性最强。
还有一类冲突发生在多个技能同时匹配时。比如你在技能 A 里写了“严格遵循 Conventional Commits”,又在技能 B 里写了“提交信息必须带作者签名”,模型同时加载两者后,会无所适从。解决方法是保持技能职责单一,或者把公共规则提炼到全局的CLAUDE.md里,避免在技能内部重复定义。
4.4 高频问题速查表
| 问题现象 | 可能原因 | 排查与解决 |
|---|---|---|
| 技能从未自动触发 | description 太笼统或没用动词语句 | 改成“Use when…”;新开会话重试 |
已在目录里但#找不到 | 目录层级错误或文件名拼写错误 | 确认是skills/名字/SKILL.md |
| 触发了但输出不像规则要求的 | 正文规则被描述冲突覆盖 | 检查其他技能或 CLAUDE.md 是否互相矛盾 |
| 资源文件里的内容没生效 | 主文档未明确指示读取资源 | 在主文档加“先阅读 resources/xxx”的步骤 |
| 输出风格不稳定 | 示例不足 | 增加 2-3 个高质量示例,要求对照 |
| 上下文很快被耗尽 | 主文档太长或正文塞了示例 | 把示例移到 resources 文件 |
这张表是我实际排查时最常用的路线。遇到问题先对照第一列定位现象,然后去改输入,不是去怪模型。
5. 把 Skill 用得再深一点:进阶经验
5.1 让 skill 守住“单点职责”
我见过有人做了一个“开发助手”的 Skill,里面同时包含写代码、写提交信息、写文档、做代码审查、查数据库五件事。乍看很全能,实际效果极差。因为一个技能要想被正确触发,description必须非常具体,而技能职责一旦变多,描述就只能写得含糊,触发准确率立刻下降。
我的经验是:一个技能只解决一类任务。写代码审查的,别顺带写提交信息;写文档的,别顺带总结代码规律。如果需要多个能力组合,就让多个技能依次触发,或者分阶段调用。宁可技能数量多一点,也不要一个技能扛所有事。
5.2 把 skill 当团队规范库:用版本管理固化
Skill 文件本质是文本,完全可以放进 Git 仓库管理。我自己会建一个skills-collection仓库,把常用的用户级技能统一管理起来。改了技能内容,提交一次,其他同事 clone 后直接把整个目录软链到各自的~/.claude/skills,团队所有人的行为规范就保持一致了。
这里有个很实用的做法:给技能仓库加一个简单的校验脚本,检查每个子目录是否都有SKILL.md,以及name是否符合命名规范。别小看这一步,当技能数量超过十个,手搓校验能省下你大量排查时间。
团队落地时,我建议先从“提交信息规范”和“代码审查清单”两个技能开始,因为它们最容易看到统一效果,也最容易让团队成员接受。慢慢再扩展到接口文档模板、版本发布流程这些更复杂的场景。
5.3 与 MCP 配合:技能负责流程,工具负责取数
Skill 和 MCP 是互补关系。Skill 提供“怎么做”的流程,MCP 提供“能做到”的工具。举个例子:代码审查技能可以规定“每次审查必须运行静态检查工具”,如果你通过 MCP 或者命令行工具暴露了静态检查接口,技能正文里就可以明确指示代理调用它。这时 Skill 相当于组织流程的人,MCP 是执行动作的手。
如果你的技能需要动态数据支撑,最简单的做法是在步骤里写“调用xxx命令获取数据”,把获取到的数据带回上下文,再按技能规则处理。我在做 API 文档生成技能时,就是让代理先调用项目里的脚本扫出路由表,再按照模板生成文档。整个过程完成后,代理只是“按图施工”,但每一步都被固化了下来。
5.4 我的最后一个建议
Skill 的设计是一个不断迭代的过程。第一版能用就行,不要追求完美。先写一个简单的SKILL.md,跑通一次,再根据实际输出效果一点一点加规则加示例。我自己的提交信息技能,从最初十几行规则演进了三个版本,每次都是在看到不满意输出后,把“为什么会这样”写进新规则里。这个过程有点像带新人——交代一次不够,但每一次纠正,都会让之后的执行稳定一点点。
如果你能坚持把重复出现三次以上的任务都做成 Skill,积累三五个之后,你会明显感受到 Claude Code 从“一个加提示词的终端”变成了“一个有章法的协作者”。那种体验,值得你花一下午把这篇内容付诸实践。