1. 从提示词漂移到可复用技能:我为什么开始写 SKILL.md
如果你用 Claude 写代码超过两周,大概率遇到过这个场景:同一个「生成接口文档」的提示词,今天输出带参数表,明天变成散文段落,后天干脆漏掉错误码。这不是模型变笨了,而是提示漂移——每次手敲的提示词都有细微差异,模型没有稳定的执行锚点。
Claude Skills(也叫 Agent Skills)解决的正是这件事。它把「任务是什么、怎么执行、输入输出长什么样」固化成一个带 YAML 前置元数据的SKILL.md文件,放进项目的.claude/skills/目录,Claude 在启动时只加载技能名和描述,命中任务后才展开完整指令。这套机制叫渐进式上下文披露,好处是你可以装几十个技能而不会把上下文撑爆。
这篇面向已经会用 Claude 写代码、但还没把零散提示词沉淀下来的开发者。我会给出可直接复制的SKILL.md骨架、settings.json里统一走 TaoToken API 通道的配置片段,以及一次技能触发的验证动作。目标很明确:让你把「每次重新解释一遍」的提示词,变成能进 Git、能过 PR 审查、能跨项目复用的 Agent Skills。
2. TaoToken 前置:统一 Key 与 API 通道
Skills 本身只是指令文件,真正执行时还是要调模型。如果你在多个项目、多个工具里各配一份 Key,轮换和额度管理会变成灾难。我的做法是让所有 Skills 触发的请求都走同一个 API 通道,Key 只维护一份。
TaoToken 在这里扮演的就是统一入口:一个 Key 覆盖模型对话、编码计划、控制台管理。你需要在控制台创建一个 API Key,然后把它写进 Claude 的配置里。注意区分两个地址——官网入口是https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=,API 基址是https://taotoken.net/api,后者不要加 UTM 参数,否则部分客户端会把查询串当成路径的一部分。
创建 Key 的入口在控制台的 API Keys 页面,建议按项目建不同 Key,方便单独吊销。拿到形如sk-开头的字符串后,不要硬编码进SKILL.md,而是放进环境变量或settings.json,这样技能文件本身可以安全地提交到仓库。
注意:
SKILL.md是给模型看的指令,不是密钥容器。任何 Key、token、内部地址都不应该出现在技能文件里,这是团队协作的基本纪律。
3. 可复制配置:SKILL.md 骨架与 settings.json
先看目录结构。一个技能就是一个文件夹,SKILL.md必需,其余可选:
.claude/ └── skills/ └── api-doc-writer/ ├── SKILL.md ├── references/ │ └── error-codes.md └── assets/ └── template.mdSKILL.md的骨架如下,前置元数据只有name和description是硬性要求,description要写清楚「什么时候用」,因为 Claude 在发现阶段只读这两行来判断相关性:
--- name: api-doc-writer description: 当用户需要为 REST 接口生成 Markdown 文档、补充参数表或错误码说明时使用此技能。 --- # API 文档生成 ## 何时使用 用户提到「接口文档」「API 说明」「参数表」「错误码」时触发。 ## 执行步骤 1. 读取用户提供的路由文件或函数签名。 2. 按 references/error-codes.md 的格式整理错误码。 3. 使用 assets/template.md 作为输出骨架。 4. 输出到 docs/api/ 目录,文件名用接口路径转换。 ## 输出要求 - 每个接口必须包含:方法、路径、请求参数表、响应示例、错误码。 - 参数表列固定为:名称、类型、必填、说明。 - 不编造未在源码中出现的字段。接下来是settings.json,把模型请求统一指向 TaoToken 的 API 通道。不同客户端字段名略有差异,核心是baseURL和apiKey两项:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的Key" }, "skills": { "directory": ".claude/skills", "autoDiscover": true } }如果你更习惯用环境变量而不是写进配置文件,可以在 shell 里导出:
export ANTHROPIC_BASE_URL="https://taotoken.net/api" export ANTHROPIC_API_KEY="sk-你的Key"两种方式选一种即可。写进settings.json的好处是团队新人克隆仓库后不用额外配环境,坏处是容易误提交,所以务必把settings.json加进.gitignore,仓库里只留一份settings.example.json。
4. 验证请求:一次技能触发与成功结果
配置完成后不要急着写复杂技能,先用一个最小技能验证链路通不通。我建了一个hello-skill,SKILL.md内容极简:
--- name: hello-skill description: 当用户说「打个招呼」或「测试技能」时使用。 --- # 打招呼 ## 执行步骤 1. 读取当前项目根目录名称。 2. 输出一句话:项目 <名称> 的技能通道已就绪。然后在项目里发起对话,输入「测试技能」。预期行为是 Claude 先匹配到hello-skill的描述,展开完整指令,读取目录名后返回类似「项目 my-app 的技能通道已就绪」。
如果这一步成功,说明三件事同时成立:技能被发现、指令被加载、模型请求通过 TaoToken 通道正常返回。接下来验证真实技能,用第 3 节的api-doc-writer,给它一个路由文件:
# 假设项目里有一个 Express 路由 cat src/routes/user.js把文件内容贴给 Claude 并说「给这个接口生成文档」。成功的标志是输出落在docs/api/下,且参数表列名与SKILL.md里定义的完全一致——列名一致才说明技能指令真正生效,而不是模型自由发挥。
想单独验证模型通道是否可用,可以打开模型对话页面直接发一条消息,确认返回正常后再回到 Skills 调试。如果对话正常但技能不触发,问题多半在description写得不够具体。
5. 本篇常见错排查
技能不触发:九成是description太抽象。写成「处理文档」模型无法判断相关性,要写成「当用户需要为 REST 接口生成 Markdown 文档时使用」。把用户可能说的原话关键词塞进去。
YAML 前置元数据解析失败:---必须是文件第一行,前面不能有空行或注释。name用小写加连字符,不要用空格或中文。
请求 401 或 404:先检查ANTHROPIC_BASE_URL是不是写成了带 UTM 的官网地址。API 基址就是https://taotoken.net/api,多一个字符都会导致路径拼接错误。401 则通常是 Key 复制时带了空格。
技能加载了但输出不符合模板:检查SKILL.md里的输出要求是不是用了模糊词,比如「尽量包含」。改成「必须包含」并给出固定列名,模型对确定性指令的遵循度明显更高。
改了 SKILL.md 不生效:部分客户端会缓存技能元数据,重启会话或重新加载项目即可。如果还是旧的,确认你改的是.claude/skills/下的文件,而不是仓库里另一份副本。
多技能互相干扰:当两个技能的description高度重叠时,模型可能选错。给每个技能划定清晰的触发边界,必要时在描述里写「仅当……时使用」。
6. 把技能沉淀为可版本管理的资产
走到这里,你已经有了一个能跑通的技能。接下来是让它真正产生复利的部分:把技能当代码管理。每个技能一个文件夹,改动走 PR,description的调整在 PR 描述里说明触发场景的变化。团队里谁发现某类任务反复出现,就提一个技能草案,评审通过后合并。
长期跑编码任务和 Agent 工作流的话,建议把额度集中管理,用 Coding Plan 承载高频调用,避免每个项目单独配 Key 导致的额度碎片化。技能文件本身保持纯净,只描述「怎么做」,不掺任何凭证。
我自己的习惯是每季度清理一次技能库:三个月没被触发过的技能,要么删掉,要么把description改到能命中真实场景为止。技能库和代码库一样,会腐化,需要定期修剪。当你的.claude/skills/目录里躺着十几个经过验证的技能时,你会发现「运行我的 api-doc-writer 技能」比每次重新解释一遍需求快得多,输出也稳定得多。