1. 为什么你的 Skill 越写越卡:从一次上下文爆掉说起
Claude Skill 是 Claude Code 里用来封装领域能力的资源包,它最核心的设计不是「把提示词分文件夹放」,而是渐进式分层加载——按需把内容塞进上下文。适合谁?适合那些手里攒了十几套业务规范、每次会话都被无关手册稀释注意力的开发者。
我最早接触 Skill 的时候,想法特别朴素:不就是把团队代码规范、部署流程、报表模板写成 Markdown 嘛,那我全塞进 System Prompt 不就完了。结果项目里堆到第八套技能时,会话开始明显变慢,模型回答质量断崖式下滑——明明问的是 Java 命名规范,它却把 Python 部署脚本的注意事项也扯进来。后来把上下文长度打出来一看,光技能手册就吃掉十几万 token,真正留给用户问题的空间被挤得所剩无几。
这个坑的根源在于:System Prompt 是常驻的,你写多少它就占多少,每一轮对话都要重新计费、重新参与注意力计算。而 Claude Skill 的渐进式分层加载机制,本质是一套上下文懒加载调度方案——常驻的只有一份极简索引,完整手册要等任务匹配上才临时载入,附属脚本更是走到对应环节才读。三层结构各管各的,token 占用能压到全量塞入的百分之几。
这篇我会从 SKILL.md 的目录结构讲起,拆开三层加载的触发时机,再顺着斜杠命令的调用链路走一遍,最后给你一份可复制的分层配置和加载顺序验证步骤。你跟着敲一遍,就能自己复现「索引常驻、正文按需、脚本延迟」这套机制到底怎么跑起来的。
2. TaoToken 前置准备:把 API Key 和 Base URL 配好
在动手写 SKILL.md 之前,得先让 Claude Code 能正常发请求。这一步用 TaoToken 做接入,它的 API 地址是 https://taotoken.net/api,兼容 Anthropic 的接口格式,Claude Code 直接改环境变量就能用。
先说清楚要准备的三件套,缺一不可:
| 配置项 | 值 | 说明 |
|---|---|---|
| Base URL | https://taotoken.net/api | 请求入口,不要带结尾斜杠 |
| API Key | 在控制台生成 | 形如 sk- 开头的一串字符 |
| Model ID | claude-sonnet-4-5 等 | 按你订阅的模型填 |
API Key 的生成入口在控制台里,打开 https://taotoken.net/console 登录后进 API Keys 页面,点新建,复制出来存好——它只显示一次。如果你还没决定用哪个模型,可以先到模型对话页面 https://taotoken.net/models 试几句,确认响应正常再往下走。
配环境变量有两种方式。临时生效的,直接在终端里 export:
export ANTHROPIC_BASE_URL="https://taotoken.net/api" export ANTHROPIC_API_KEY="sk-你的key" export ANTHROPIC_MODEL="claude-sonnet-4-5"想长期生效就写进 shell 配置文件。用 zsh 的话:
echo 'export ANTHROPIC_BASE_URL="https://taotoken.net/api"' >> ~/.zshrc echo 'export ANTHROPIC_API_KEY="sk-你的key"' >> ~/.zshrc echo 'export ANTHROPIC_MODEL="claude-sonnet-4-5"' >> ~/.zshrc source ~/.zshrc如果你用的是 Claude Code 的 settings 文件方式,那就写 JSON。路径通常在~/.claude/settings.json,内容长这样:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的key", "ANTHROPIC_MODEL": "claude-sonnet-4-5" } }注意这个 JSON 里 Base URL 和 Key 必须成对出现,只填一个会报认证失败。配完之后别急着写 Skill,先跑一条最小请求验证链路通不通:
curl https://taotoken.net/api/v1/messages \ -H "x-api-key: sk-你的key" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{ "model": "claude-sonnet-4-5", "max_tokens": 64, "messages": [{"role": "user", "content": "说一句你好"}] }'返回里能看到content数组带一段文本,就说明 Base URL、Key、Model ID 三件套都对上了。这一步过了,后面 Skill 的加载验证才有意义——否则你分不清是 Skill 配置错了还是请求根本没发出去。
3. 可复制配置:SKILL.md 分层结构与懒加载触发点
现在进入正题。Skill 不是一段纯文本,而是一个标准化目录资源包。先看标准模板长什么样:
pdf-handle/ ├── SKILL.md # 核心主配置(必填) ├── reference.md # 复杂业务补充说明 ├── forms.md # 专项表单处理规范 └── scripts/ └── fill_form.py # 可执行业务脚本整个包没有编译步骤、没有额外依赖,纯文本文件,扔进目录就能用。SKILL.md 最顶部用---包一段 frontmatter,这是分层加载的索引来源:
--- name: pdf-handle description: 处理PDF读取、合并、表单填充,用户提及PDF相关操作时自动调用 allowed-tools: Read, Bash disable-model-invocation: false --- # PDF处理完整流程 ## 读取 调用 scripts/read_pdf.py 解析目标文件,参数通过 $ARGUMENTS 传入。 ## 表单填充 表单字段映射规则见 forms.md,复杂校验逻辑见 reference.md。name对应斜杠命令/pdf-handle,是唯一标识;description是模型匹配任务的核心依据,必须写清楚「什么场景会用到」。可选字段里allowed-tools限制这个技能能用哪些工具,disable-model-invocation设成 true 就禁止 AI 自主调用,只留人工斜杠触发。
三层加载的触发时机是这样的:
第一层,Agent 启动时扫描所有 Skill 目录,只提取每个技能的name加精简description,生成一份极简清单常驻上下文。源码里有硬约束——整套索引只分配窗口 1% 的 token 额度,单条描述最大 250 字符,超了自动截断。所以你的 description 要写得像「用户要求评审代码、检查变量命名时启用」,而不是「本工具支持多种代码检查功能」。
第二层,当模型判断当前任务和某条描述匹配,才去读完整的 SKILL.md 正文,以元用户消息的形式插入本轮对话。关键点是它不改全局 System Prompt,所以不会破坏缓存、不会每轮重新计费。这条消息在终端界面不展示,但模型能完整读到。
第三层,SKILL.md 正文里只写指引语句,reference.md、forms.md、脚本这些不会同步载入。只有流程走到对应环节,Agent 才去读,用完不长期驻留。
给你一份可直接复制的分层配置,以代码评审为例。先建目录:
mkdir -p ~/.claude/skills/code-lint/scripts写 SKILL.md:
--- name: code-lint description: 用户要求评审代码、检查变量命名或异常处理规范时自动启用 allowed-tools: Read, Grep --- # 代码检查清单 1. 变量必须具备业务语义,禁止 a、tmp 等无意义命名 2. 魔法数字统一提取为常量 3. 捕获异常必须打印日志,禁止静默吞异常 ## 深度规则 命名细则与团队历史约定见 reference.md。 统计重复代码块时执行 scripts/count_dup.py,参数为 $ARGUMENTS。再写一个附属文件 reference.md:
# 命名细则 - 布尔变量以 is/has/can 开头 - 常量全大写下划线分隔 - 接口实现类以 Impl 结尾保存后不用重启、不用编译,直接/code-lint就能手动调用,AI 识别到代码评审需求也会自动启用。这里$ARGUMENTS是参数占位符,你输入/code-lint UserService.java,文档里的$ARGUMENTS会自动替换成UserService.java,省去手动复制路径。
4. 验证请求:确认三层加载真的按顺序跑起来
配置写完,得验证它是不是真按渐进式分层加载在跑。光看文档不够,要抓实际行为。
第一步,确认第一层索引常驻。启动 Claude Code 后,随便问一个和技能无关的问题,比如「今天写个快排」,然后观察它有没有把 code-lint 的完整正文拉进来。正常情况是:索引里有 code-lint 这条描述,但正文没载入。你可以通过会话的 token 用量间接判断——如果只问快排却消耗了和代码评审手册相当的 token,说明第二层被误触发了。
第二步,触发第二层。输入一句明确匹配描述的话:
帮我检查一下这段代码的变量命名规范这时模型应该读取完整 SKILL.md,并按清单给出评审意见。如果它只泛泛而谈、没引用你写的三条规则,说明 description 没匹配上,或者 SKILL.md 路径不对。
第三步,验证第三层延迟加载。在 SKILL.md 里我写了「统计重复代码块时执行 scripts/count_dup.py」。先问一个只涉及命名的问题,脚本不该被执行;再问「统计一下这段代码的重复块」,这时才应该触发脚本。你可以给脚本加一行日志来确认:
# scripts/count_dup.py import sys print(f"[script-run] args={sys.argv[1:]}", file=sys.stderr)如果第一次提问就打印了[script-run],说明第三层被提前加载了,检查是不是在 SKILL.md 正文里把脚本内容直接内联了——内联会导致它随第二层一起进上下文。
第四步,验证斜杠命令链路。手动输入/code-lint UserService.java,观察$ARGUMENTS是否被替换。如果模型收到的还是字面量$ARGUMENTS,说明占位符写法有问题,确认是$ARGUMENTS全大写、没有多余空格。
一个完整的成功结果应该长这样:索引常驻约 2000 token,触发评审后临时增加约 3000 token 的正文,脚本执行时再增加少量输出,全程 System Prompt 没变。你可以用这个对比表来核对:
| 阶段 | 常驻 token | 临时载入 | System Prompt 是否改动 |
|---|---|---|---|
| 启动 | 索引约 2000 | 无 | 否 |
| 匹配评审 | 索引约 2000 | SKILL.md 约 3000 | 否 |
| 执行脚本 | 索引约 2000 | 脚本输出 | 否 |
如果哪一列对不上,回到对应层去查。
5. 本篇常见错排查:401、local proxy failed 与加载异常
配 Skill 的过程中,报错基本集中在接入层和加载层。我按真实遇到的顺序列一遍。
401 认证失败。返回体里带authentication_error或invalid x-api-key。原因通常是 Key 没生效或 Base URL 写错。先确认环境变量:
echo $ANTHROPIC_BASE_URL echo $ANTHROPIC_API_KEYBase URL 必须是https://taotoken.net/api,不要带/v1后缀,也不要带结尾斜杠。Key 确认是控制台里复制的那串,没有多余空格。如果用的是 settings.json,检查 JSON 有没有语法错误——一个多余的逗号就会让整个 env 块失效。
local proxy failed。这个报错说明请求根本没发到远端,卡在本地。常见原因是环境变量里同时存在旧的代理配置,或者ANTHROPIC_BASE_URL被其他工具覆盖了。清一下相关变量再试:
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY然后重新 export 三件套。如果你在 settings.json 和 shell 里都配了,以 settings.json 为准,别让两处冲突。
reading choices 报错。这个通常出现在响应解析阶段,提示读取choices字段失败。原因是接口返回格式和客户端预期不一致——多半是 Base URL 指到了非 Anthropic 兼容的端点。确认你用的是https://taotoken.net/api,并且 Model ID 填的是 Claude 系列,不要填成别的厂商模型名。
OAuth 相关报错。如果提示 OAuth token 失效或需要重新授权,说明客户端走了 OAuth 流程而不是 API Key。Claude Code 里要确保ANTHROPIC_API_KEY已设置,它会优先用 Key 而不是 OAuth。检查有没有残留的 OAuth 凭证文件干扰。
Skill 不触发。配置都对但模型就是不调用。九成是 description 写得太泛。把「本工具支持多种代码检查功能」改成「用户要求评审代码、检查变量命名或异常处理规范时自动启用」,匹配率立刻上来。另外确认 SKILL.md 放在~/.claude/skills/或项目内.claude/skills/下,目录名和name字段一致。
脚本不执行。本地技能才开放脚本能力,来自 MCP 远程服务的 Skill 会直接禁用 Shell 执行,这是安全隔离设计。如果你把技能放在远程加载,脚本永远不会跑,这是预期行为,不是 bug。
排查时记住一个原则:先确认请求链路通(用第 2 节的 curl 验证),再查 Skill 加载。链路不通的话,所有 Skill 层面的调试都是白费。
6. 把 Skill 沉淀进仓库:团队协作与后续接入
Skill 真正好用的地方,是项目目录内的技能能跟着 Git 仓库走。你把.claude/skills/提交进去,新同事克隆代码后自动拿到全套评审、部署、报表规范,不用人工传文档、不用反复复制长提示词。
Agent 启动会扫描五个来源,按固定顺序加载:官方内置、用户全局目录~/.claude/skills/、项目目录.claude/skills/、插件配套、MCP 远程服务。同名技能后加载的不会覆盖先加载的,所以项目目录里的技能优先级高于全局目录,适合放团队定制规则。
写 Skill 有三条准则值得记住。描述聚焦使用场景,控制在 250 字符以内,优先写「用户什么场景会用到」而不是堆功能。主文档保持轻量,复杂细节拆到 reference.md,减少第二层载入的体积。重复性操作封装成脚本,别让模型每次重新推演步骤。
如果你还没配好接入,先去 API Keys 页面 https://taotoken.net/api-keys 生成 Key,接入文档在 https://taotoken.net/doc 有完整说明。想先验证模型响应再动手写 Skill,可以到模型对话 https://taotoken.net/models 试几句。长期做编码和 Agent 任务的,Coding Plan 页面 https://taotoken.net/coding-plan 有更划算的订阅方式。
配好之后,从最简单的 code-lint 开始,跑通三层加载的验证步骤,再逐步把团队的规范往里搬。