Case Studies · Parhum Khoshbakht

技能分层:让我们 80+ 个技能远离上下文的四桶模型

渐进式披露意味着 80 个技能可以是 3,200 token 的元数据,也可以是零。这是我们如何把 Statnive 仓库里的每一个技能分类为始终开启、自动可调、仅手动或 fork — 以及我们用来做决定的那一道问句测试。

为什么更多技能不必意味着更少上下文

Statnive 的 Claude Code 配置加载了 80 多个技能,覆盖产品管理、后端脚手架、QA、安全审计、WordPress 特定模式、发布打包等等。我们所基于的框架(jaan.to)交付了 141 个。一种天真的理解是:技能更多,上下文开销更多,留给真正工作的空间更少。

实际的算术更有趣。80 个技能可以耗 3,200 token 的永久元数据,也可以是零 — 取决于每一个的配置方式。差别在于 Claude Code 技能系统定义的四桶分层模型,以及挑选合适桶的那一道问句测试。

本文走一遍全部四个桶,给出 Statnive 真实的技能分布、我们用来决策的测试,以及我们在做对之前做错的三件事。

渐进式披露:底层机制

在分层模型说得通之前,加载机制必须先说得通。Claude Code 对技能使用三层渐进式披露

加载内容何时成本
1 — 元数据YAML 前置元数据 name + description启动时始终加载每个技能约 30–50 token
2 — 正文完整的 SKILL.md 内容当技能被调用时Anthropic 建议 ≤ 500 行 / 约 5K token
3 — 打包资源引用的脚本、模板、参考文件仅在被访问时零基线成本

这就是分层模型用的杠杆。元数据层是唯一始终在上下文里的部分。其他都是按需。

对一个 141 个技能的框架来说,仅元数据就有4,200–14,100 token 的永久开销,与技能数量呈线性关系。如果描述冗长,会更大。如果您让某些技能完全跳过元数据注册表,会更小 — 甚至为零。

一个有据可查的 bug(Claude Code GitHub issue #14882)报告称某些插件技能在启动时可能会消耗其完整正文,而不仅是前置元数据。我们在自己的 /context 输出中留意这种情况。如果您的技能元数据行显示出远高于「约 50 token × 您的自动可调技能数」的数字,您正在踩到它。

四个桶

Statnive 仓库中的每一个技能都属于这四个桶之一。决定每一个桶的关键前置元数据字段:

桶 1 — 始终开启(默认前置元数据)

---
name: simplify
description: Review changed code for reuse, quality, efficiency. Auto-fixes issues.
---

这些是模型应自动路由到的核心工作流技能。标准前置元数据 — 没有特殊标记。元数据在启动时加载;正文在调用时加载。

Statnive 示例: simplifystatnive-releasestatnive-release-zip。它们在大多数与发布相关的工作上触发。

每个技能成本: 上下文中永久约 40 token 元数据。

桶 2 — 自动可调(默认前置元数据,简洁描述)

从 Claude Code 的角度看,配置与「始终开启」相同。区别是编辑层面的:这些是仅在触发关键词匹配时才触发的领域技能。纪律在于让描述以触发为导向并简短。

---
name: wp-rest-api
description: Use when building REST endpoints in WordPress plugins.
---

不好的描述(仍能工作,成本更高):

description: A comprehensive skill for working with the WordPress REST API,
  including endpoint registration, controller patterns, schema validation,
  authentication, response shaping, and CPT/taxonomy exposure...

好的描述(上面那条):13 token。坏的描述:38 token。在 60+ 个自动可调技能上,差距大约是 1,500 token 的永久元数据节省。

Statnive 示例: wp-rest-apiwp-plugin-developmentwp-performancereact-best-practiceswp-block-development,以及所有 jaan-to:* 规划技能。

每个技能成本: 上下文中永久约 30–50 token 元数据。

桶 3 — 仅手动(disable-model-invocation: true

---
name: statnive-emergency-rollback
description: Emergency-only rollback procedure for a botched deploy.
disable-model-invocation: true
---

技能存在,斜杠命令也能用(/statnive-emergency-rollback),但元数据从不进入 <available_skills> 注册表。除非用户显式调用,否则 Claude 不知道它存在。

每个技能成本:0 token。 这是魔法桶。

何时使用它:罕见工作流、破坏性操作、任何您不希望模型自动路由到的内容。如果把某个技能标为仅手动会阻止工作流完成,那么它应该属于桶 1 或桶 2。

Statnive 示例: 紧急回滚、手动数据库手术、一次性迁移脚本,以及任何「以防万一」存在但不应机会主义触发的内容。

我们把大约一半的技能标为 disable-model-invocation: true。在 80+ 个技能上,这是约 1,800 token 的基线元数据被收回 — 而剩下的自动可调技能上路由质量反而提升,因为 Claude 不再需要在近似重复之间做选择。

桶 4 — Fork / Subagent(context: fork

---
name: simplify
description: Review changed code for reuse, quality, efficiency. Auto-fixes issues.
context: fork
---

Fork 模式在隔离的 subagent 上下文中运行技能,它有自己的对话历史和自己的 200K token 窗口。工作输出留在主上下文窗口之外。仅有摘要返回。

对于代码评审、安全审计和多步研究等自包含工作流,这是变革性的。Anthropic 记录的 subagent 表现是从 10,000+ token 的内部工作中返回约 500–1,000 token — 在 subagent 进行了大量阅读和处理的复杂任务上对主上下文减少约 37%

Statnive 示例: simplify(三个并行评审 agent,返回摘要)、jaan-to:backend-pr-reviewjaan-to:sec-audit-remediatejaan-to:detect-dev。任何读取很多文件并返回结论的内容。

每个技能成本: 约 40 token 元数据,但工作本身在隔离环境中发生。

那道问句测试

四个桶听起来像四个决定。其实它们只是一个:主对话需要看到该技能的中间工作吗?

答案
是 — 该技能写的代码主会话还会继续编辑始终开启 或 自动可调
否 — 该技能返回结论、摘要或报告Fork / subagent
也许 — 但它绝不应自动触发(罕见、破坏性、奇怪)仅手动

如果是「否」,设 context: fork。您的主上下文保持清洁,并且您可以让 subagent 重读取的工作使用 Haiku 4.5($1/$5 每 MTok),同时主会话使用 Sonnet 或 Opus。这是上下文胜利之外再叠加一个 3× 的成本胜利。

如果是「是」,它进入桶 1 或 2。在「始终开启」和「自动可调」之间的选择是编辑层面的:Claude 能多有信心地从自然语言线索中触发它?强烈、毫不含糊的触发进入「自动可调」。模型应在大多数会话中考虑的工作流进入「始终开启」。

如果该技能存在但不应自动触发,把它标为「仅手动」并收回它的元数据成本。

Statnive 的真实技能分布

下面是我们当前在约 85 个技能上的拆分:

数量总元数据成本备注
始终开启8约 320 token发布、simplify、Sprint 规划、PR 评审
自动可调38约 1,520 token触发关键词强的领域技能
仅手动320 token仅斜杠命令
Fork / subagent7约 280 token评审、审计、检测
总元数据成本85约 2,120 token约占上下文 1%

如果不分层 — 如果全部 85 个都用默认设置 — 我们会付大约 3,400 token 的永久元数据。仅 32 个仅手动技能就省下约 1,280 token。单独看显得很小;与 CLAUDE.md 精简MCP Tool Search叠加时就重要了。

正文上限:为什么 500 行是合适的数字

元数据这边是永久开销。正文那边是按调用开销 — 同样重要要去控制。

Anthropic 建议把每个 SKILL.md 保持在 500 行(约 5K token)以下。关于激进优化的研究把这条推到了每个技能正文 600 行的硬上限,超过的需要参考提取:把模板、长清单、多技术栈对比、反模式目录从 SKILL.md 中拉出来,放到通过清晰指针引用的独立文件里。

模式看起来像:

.claude/skills/wp-plugin-development/
├── SKILL.md                          # 380 lines — execution core only
└── references/
    ├── activation-deactivation-patterns.md   # Loaded only when needed
    ├── settings-api-patterns.md
    ├── nonce-and-capability-checklist.md
    └── release-packaging-checklist.md

执行核心保持紧凑且确定。参考文件按需加载,在被访问之前不耗 token。我们这样重建了我们最重的三个技能,把典型调用的预算砍掉了约 12,000 token。

值得使用的另一个正文控制字段:

allowed-tools: ["Read", "Grep", "Glob"]

这限制该技能能访问哪些工具,既减少 token 开销,也减少执行面。一个只读代码的技能不应有 Write、Bash 或 MCP 工具访问权限 — 收窄工具集会收窄技能触发时注入的 schema,并消除一整类意外行为。

我们前三次做错的事情

诚实的注意事项,与本系列其他文章一致:

  1. 我们一开始用了冗长的描述。 我们第一波技能的描述有 60+ token,是为人类读者优化的。它们能用,但成本是它们应有的 2 倍。第一轮修剪从自动可调桶里砍掉了约 1,400 token 的元数据。
  2. 我们有三个做相似事情的技能。 自动可调桶里有 pm-roadmap-addpm-roadmap-updatepm-sprint-plan,触发重叠。路由变得像抛硬币。我们做了合并并澄清了触发。路由准确度上升;元数据成本下降。
  3. 我们有重技能没有用 fork 模式。 simplify 最初是内联运行的。它会读 30+ 个文件,跑三轮评审,返回 2,000 token 的报告 — 全部内部工作都污染了主上下文。切换到 context: fork 后,每次发布会话的典型主上下文使用减少了约 9,000 token。

测量步骤

与本系列其他文章一致:/context 是诊断。给技能分层时您要看的那一行是显示技能元数据 token 数的那一行。我们使用的目标值:

来源目标硬上限
技能元数据≤ 2,500 token5,000
自动可调技能数≤ 60
任何单个 SKILL.md 正文≤ 500 行 / 约 5K token600 行 / 约 8K token

如果您的技能元数据行远超 5K token 而您的技能少于 100 个,您可能要么有冗长描述(桶 2 问题),要么命中了我们之前提到的加载 bug(桶 1 问题)。

这与 Statnive 其他部分的联系

我们每次提交都跑 141 项 PHP 单元测试。任何版本交付前都要通过31 项合规检查。编排所有这些的技能 — statnive-releasesimplifywp-plugin-development、QA 生成器 — 加起来大约 2,100 token 的永久元数据。工作发生了,上下文保持清洁,团队保持小规模。

四桶模型不是学术练习。它就是我们能在没有五人团队的前提下,交付一个在 5KB tracker 预算下的 WordPress 分析插件的原因。

试试 Statnive

由一支跑 /context 比跑 /help 还多的团队打造的隐私优先 WordPress 分析。从 WordPress.org 免费安装 Statnive — 您的数据留在您的服务器上,我们的技能库则远低于其 token 预算。

免费获取 Statnive