1. 为什么你的 Claude Code 总是不按套路出牌
如果你已经在用 Claude Code 写代码,大概率遇到过这种场景:明明在项目里约定好了「所有接口必须走统一响应包装」「提交前必须跑 lint」「新增组件必须补单测」,但每次开新会话,它还是按自己的习惯来,你得反复在对话里提醒。提醒一次管一次,换个会话又忘光。
这不是模型笨,而是你给它的约束是「临时的」。普通对话里的要求只存在于当前上下文,会话一关就没了。CLAUDE.md 能解决一部分问题,它定义的是项目级规则,每次会话都会读,但它更像「宪法」——写的是不能干什么、边界在哪,而不是「某类任务具体分几步做」。
Claude Code Skills 补的正是这块。一个 Skill 本质就是一个SKILL.md指令包,告诉 Claude Code「在什么时机、用什么方法」完成一类任务。它是可复用的「岗位说明书」:普通对话是临时工,Skill 是签了合同的正式员工。你把它放到~/.claude/skills/或项目里的.claude/skills/,命中触发条件时它自动加载,也能通过 slash 命令手动调用。
这篇面向想让 AI 稳定遵循团队规范的开发者,从SKILL.md骨架、目录结构讲到 slash 触发和 MCP 协作,给出可直接复制的模板和settings.json片段,最后演示一次 slash 调用验证 AI 是否真的按规范输出。适合谁:已经在用 Claude Code、想让重复性工作固化成流程的人;如果你还没装,先看安装那篇再回来。
2. 前置准备:TaoToken 接入与 Skills 目录约定
在写 Skill 之前,先把「模型从哪来」这件事理顺。Claude Code 需要一个可用的 API 入口,我用的是 TaoToken 的接入方式,官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 端点是 https://taotoken.net/api 。它的作用是给你一个统一的调用入口,Claude Code 通过环境变量指向它即可,不用改 Claude Code 本身的代码。
先拿 Key。打开控制台 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,在 API Keys 页面创建一个密钥,复制出来。这个 Key 只显示一次,丢了就重建。拿到后配置环境变量,macOS/Linux 写进~/.zshrc或~/.bashrc:
export ANTHROPIC_BASE_URL="https://taotoken.net/api" export ANTHROPIC_AUTH_TOKEN="sk-你刚才复制的key"Windows 用 PowerShell 的话:
$env:ANTHROPIC_BASE_URL = "https://taotoken.net/api" $env:ANTHROPIC_AUTH_TOKEN = "sk-你刚才复制的key"改完重开终端,或者source ~/.zshrc让它生效。验证一下变量有没有进去:
echo $ANTHROPIC_BASE_URL echo $ANTHROPIC_AUTH_TOKEN两个都有输出就对了。接着确认 Claude Code 能连上,随便进一个目录跑一次简单对话,能正常返回就说明链路通了。这一步别跳过,后面 Skill 调试如果出问题,先排除是不是 Key 或端点没配对。
然后是 Skills 的目录约定。Claude Code 会从几个位置加载 Skill,作用范围不同:
| 位置 | 路径 | 生效范围 |
|---|---|---|
| 全局 | ~/.claude/skills/<名字>/SKILL.md | 所有项目 |
| 项目级 | <项目>/.claude/skills/<名字>/SKILL.md | 仅该项目 |
| 插件自带 | ~/.claude/plugins/cache/.../skills/<名字>/SKILL.md | 插件启用即加载 |
较新版本起,嵌套的.claude/skills目录会自动加载,插件里的 skills 也不需要 marketplace 就能识别。我的建议是:团队通用规范放项目级,跟着仓库走,同事 clone 下来就有;个人跨项目习惯放全局。技能名统一用 kebab-case,比如api-response-check、commit-lint,别用中文或空格,避免路径解析出问题。
3. 可复制配置:SKILL.md 骨架与 settings.json
先看一份最小可用的SKILL.md。frontmatter 里name和description是必须的,其中description是 Claude Code 判断「要不要调用这个 Skill」的唯一依据,写得越准,触发越稳。
--- name: api-response-check description: 当用户新增或修改后端接口、提到"接口规范""响应格式""统一返回"时调用,用于检查接口是否符合团队统一响应包装规范。不用于纯前端组件改动。 --- # API 响应规范检查 ## 触发时机 - 用户新增、修改任何 HTTP 接口 - 用户说"检查接口规范""响应格式对不对" - 代码 diff 中出现 controller / handler / route 相关文件 ## 前置判断 - 仅检查后端接口层,不检查数据库迁移脚本 - 如果改动只是注释或文档,跳过 ## 执行步骤 1. 定位本次改动涉及的接口文件 2. 检查返回体是否统一为 `{ code, message, data }` 结构 3. 检查错误分支是否也走同一包装,而不是直接抛裸异常 4. 检查 HTTP 状态码与业务 code 是否分离 5. 输出问题清单,每条给出文件、行号、修改建议 ## 不要做的事 - 不自动改代码,只输出检查结果 - 不检查与本次改动无关的历史文件 - 不臆造团队没定义的字段名正文按技能性质组织。刚性技能(TDD、排障、规范检查)写死步骤,一步都别省;柔性技能(知识库检索、方案调研)写原则加方法。典型结构就是上面这套:触发时机 → 前置判断 → 执行步骤 → 不要做的事 → 参考。
description的写法有个技巧:把「触发条件」和「排除条件」都写进去。上面那句「不用于纯前端组件改动」就是排除条件,能有效避免误触发。很多人只写「用于检查接口」,结果改个前端组件它也跑出来,上下文被污染。
接着是settings.json。Claude Code 的配置分用户级和项目级,项目级放<项目>/.claude/settings.json,跟着仓库走。下面这份片段控制 Skill 的展示与启用:
{ "skills": { "api-response-check": { "displayName": "接口规范检查", "defaultEnabled": true }, "commit-lint": { "displayName": "提交信息校验", "defaultEnabled": false, "fallback": "提交信息不符合规范时,提示用户手动修正" } } }displayName是给人看的名字,defaultEnabled控制默认是否启用,fallback定义异常时的兜底行为。这几个字段不是每个版本都完全一致,如果你的版本不认,删掉对应字段即可,SKILL.md本身照样能加载。
目录结构长这样:
<项目>/ ├── .claude/ │ ├── settings.json │ └── skills/ │ ├── api-response-check/ │ │ └── SKILL.md │ └── commit-lint/ │ └── SKILL.md一个技能一个目录,目录名和 frontmatter 里的name保持一致,省得自己绕晕。
4. 验证请求:用 slash 调用确认 AI 按规范输出
配置写完,得验证它真的生效。Claude Code 里 Skill 可以注册成 slash 命令,用户显式输入/技能名就能调用。先重启一次会话,让新 Skill 被加载。
第一步,确认 Skill 被识别。在 Claude Code 里输入/看命令列表,或者直接问它「现在有哪些可用的 skill」。如果api-response-check出现在列表里,说明加载成功。没出现就检查路径和文件名,SKILL.md必须是大写,目录层级别写错。
第二步,显式触发。假设你刚改了一个接口文件,输入:
/api-response-check 检查一下刚才改的 user 接口预期结果是它按SKILL.md里的步骤走:先定位文件,再逐条检查返回体结构、错误分支、状态码分离,最后输出一份带文件行号的问题清单,而且不会自动改代码——因为「不要做的事」里写死了。
第三步,验证隐式触发。新开一个会话,不提 skill 名字,直接说「我加了个订单查询接口,帮我看看响应格式对不对」。如果description写得准,它应该自动调用这个 Skill。这一步是检验description质量的关键:没触发说明描述太窄,乱触发说明排除条件不够。
第四步,验证边界。故意改一个纯前端组件,说「帮我看看这个组件」。按规范它不该触发接口检查。如果它还是跑了,回去把排除条件写得更明确。
实测下来,隐式触发是最容易翻车的一环。我的经验是:description里至少包含一个「动作词」(新增、修改、检查)和一个「对象词」(接口、响应、提交信息),再加一句排除。三者齐了,触发准确率会高很多。
5. 本篇常见错排查
Skill 不加载。先看路径:全局是~/.claude/skills/,项目级是<项目>/.claude/skills/,别把项目级写到用户目录去了。再看文件名,必须是SKILL.md,全大写。最后看 frontmatter,---必须成对,name和description缺一不可,YAML 缩进别用 Tab。
触发了但没按步骤走。大概率是正文结构太松。刚性流程一定要写成有序步骤,别写成一段话。Claude Code 对「1. 2. 3.」这种结构的遵循度明显高于散文式描述。另外「不要做的事」要具体,写「不要乱改」没用,写「不自动改代码,只输出检查结果」才有约束力。
误触发太频繁。在description里补排除条件。比如「不用于纯文档改动」「不用于依赖升级」。也可以把defaultEnabled设为false,改成纯手动 slash 调用,等描述打磨好了再开自动。
slash 命令找不到。确认会话重启过,Skill 是启动时加载的。如果用了settings.json里的displayName,slash 命令名仍以name为准,不是 displayName。版本差异也可能导致某些字段不生效,先删掉可选字段用最小配置验证。
和 MCP 配合时工具调不到。Skill 本身不提供工具能力,它只是「脑」,负责决定什么时候、怎么干;MCP 提供「手」,负责实际执行。如果 Skill 里写了「调用检索工具」但没配对应 MCP,它就会卡住。先确认 MCP 已接入并能单独调用,再在 Skill 正文里引用。两者配合才是扩展的精髓:MCP 给能力,Skill 给流程。
改了 SKILL.md 不生效。同样要重启会话。热更新不是所有版本都支持,稳妥做法就是改完重开。
6. 把规范固化下来,从第一个 Skill 开始
Skill 的价值不在于它多复杂,而在于它把「你对 Claude Code 的要求」变成了「Claude Code 自己的行为准则」。门槛低到一个 markdown 文件,收益是一次配置长期复用,还能跟着仓库分享给同事。
如果你想让团队规范真正落地,建议从最常重复的一件事开始:提交信息校验、接口规范检查、单测覆盖提醒,挑一个写成 Skill。写完用 slash 显式调一次,再用隐式触发验一次,确认稳定后再开defaultEnabled。
需要长期跑编码任务、或者想让 Agent 按固定流程干活的,可以了解下 Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。想先验证模型输出是否符合预期,直接去模型对话页试:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite 。接入过程中遇到 Key 或端点问题,看接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,或者回 API Keys 页面重建密钥:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。
下一个扩展点是 MCP,它负责把外部工具接进来——知识库、数据库、浏览器、编辑器。Skill 定流程,MCP 给能力,两个配起来,Claude Code 才真正变成懂你团队的那一个。