☰
用官方最佳实践重构Claude Code记忆体系:Skills按需加载上下文
2026/10/14 11:19:33 网站建设 项目流程

最近一个月,我把手头项目的记忆体系做了一次大调整:把那份已经膨胀到三百多行的CLAUDE.md拆掉了大半,流程性的东西全部迁移到“Claude Code 官方 Skills”的推荐结构里。这个决定拖了很久,因为一开始我总觉得 Skills 不过是个“把提示词换个地方放”的功能,直到真正按官方 Best Practices 重构完才发现,它其实是一套上下文管理和能力复用的工程方案。如果你的项目提示词也变得又长又乱、每次对话模型都要先“重读”一遍冗长规则,那这篇东西应该能给你一些可以直接抄的参考。

先给没接触过的朋友说清楚三个基本问题:它是什么,能干什么,适合谁。Claude Code 的 Skills,本质上是一个“按需加载的能力包”:一个目录,里面放一个SKILL.md作为入口,再搭配若干脚本、模板、参考文档,说得直白一点,就是让 Claude Code 在遇到某个具体任务时才把对应的专业流程加载进上下文,而不是所有规则从头到尾常驻。官方的最佳实践围绕的也正是这一点:怎么命名、怎么组织目录、怎么写描述词、怎么在入口文件里克制地表达,最终让技能可发现、可复用、不污染日常对话。适合的人很明确:一是项目CLAUDE.md越来越臃肿、每次交互都在白白消耗上下文的人;二是想把某个团队工作流沉淀成可复用资产的人;三是想把自己常用的代码审查、发布检查、报告生成之类流程固化下来的个人开发者。下面我按自己的理解和实测经验展开说。

1. Skills 到底解决了什么问题

1.1 我的使用痛点:臃肿的 CLAUDE.md

先说我之前的状态。项目里积累了大量的团队规范、命令清单、代码风格要求、发版检查单,我一股脑全塞进了CLAUDE.md。问题很直接:无论这次对话是要改一个函数还是要写一段脚本,模型都必须读一遍这一大堆内容。上下文窗口是有限的,这堆“常驻记忆”挤占了本该用在真实任务上的空间,多轮对话后经常出现早期指令被“冲淡”的情况,模型开始忽略某些你不希望被忽略的规则。

当时我试图靠“精简 CLAUDE.md 文案”来解决,比如把每条规则改短,把说明合并。但治标不治本,问题不在于每一条写得多长,而在于“所有内容常驻”这个模式本身就低效。有些流程一个月才用一次,也天天躺在上下文里。后来我意识到官方推 Skills 的真实意图,就是把“始终生效的静态记忆”和“按需调用的动态能力”分开。

1.2 Skills 的官方定位:按需加载的能力包

官方文档对 Skills 的定位,我更愿意把它理解成“插件化的工作流”。每个 Skill 对应一类具体任务,比如“发布 Python 包”“写代码审查意见”“生成周报”。“按需加载”的意思是:平时它不占上下文,模型只有在判断当前任务与该技能的描述匹配时,才主动把SKILL.md和它引用的资源读进来。

这个设计在工程上有一个很大的好处:上下文利用率提高了,而且能力的边际扩展成本极低。你想让 Claude Code 多会一个专业流程,不需要往全局记忆里堆文字,只需要新增一个目录。这和一个项目里按文件组织模块、而不是把全部逻辑写进一个 main 函数,道理是一样的。带着这个视角再去看官方 Best Practices,你会发现它的一切建议都围绕两个词:可发现、可复用。可发现靠的是“名称目录规范”和“描述词写法”;可复用靠的是“目录内自包含”和“渐进式披露”。下面这两件事,值得单独展开。

2. 目录、元信息与触发机制怎么设计

2.1 官方推荐的目录结构与命名规则

Skills 的存放位置和命名,官方给出了两种标准位置,我自己的理解是它们对应两种复用范围。用户级目录负责跨项目复用,比如你自己沉淀的发布流程,放这里之后任何项目都生效;项目级目录负责项目内自包含,比如某个代码库特有的审查清单,离职交接或换机器时随代码仓库一起带走。

名字方面,官方建议用小写字母加连字符的短名称,例如code-review、weekly-report,这一点和 Unix 工具命名习惯一致。我见过有些人给技能起名叫Python Package Release Best Practice v2 Final,空格、大写、版本号全上,这会给模型“发现”技能制造噪音,也会在文件系统层面带来一些不必要的麻烦。官方推荐的简洁风格是有道理的。目录内部结构也追求简单自包含:SKILL.md是唯一入口,必要时放scripts、resources、templates这些辅助目录,入口文件用相对路径引用它们。一个技能的全部资产都收拢在一个目录内,迁移到另一个项目时整体拷走即可。

这里要注意一点,官方刻意让“Skills 目录”和“CLAUDE.md 的存放位置”形成了制度性的分工:CLAUDE.md是记忆,是所有对话都该知道的事实和偏好;skills目录是工具箱,是特定任务才需要翻开的过程性知识。Skill 目录里可以直接放脚本文件而不是把脚本内容写进 Markdown,Wilco 的官方 demo 更愿意让你“写文件、读文件、跑命令”,而不是把大段命令的预期输出黏贴进提示词。

2.2 description 是触发的关键,不是写给别人看的

这是我踩坑最深的一块。很多新手写SKILL.md时,把 80% 的精力放在正文流程上,对 YAML 头部的description敷衍了事,写一句“用于代码审查”就完了。实际正好反过来,我是花了三四个技能之后才意识到:描述词决定了技能能不能“被发现”。

触发过程是这样的:模型在对话中理解用户意图后,拿这个意图去比对各个技能头部的description,如果匹配度够高,它就会把对应技能的正文加载进上下文并执行。所以description本质上不是给人看的注释,而是一个检索用的索引。官方 Best Practices 在这块给出了非常明确的方向:要写明“何时使用”和“何时不要使用”,最好带上触发相关的关键词、任务类型和反向边界。我后来按照这套思路重写了一个之前长期沉睡的技能:

  • 之前:“处理项目周报。”
  • 之后:“当用户要求生成、汇总或发送周报,或需要从 git 提交记录中整理工作内容时使用。不用于日常的代码调试或需求讨论。”

效果差距几乎是立竿见影。后一种写法还主动排除了不适用场景,降低了乱触发概率。

提示:description 是触发的关键,不是写给别人看的。反向边界至少贡献了一半的价值。

3. 官方最佳实践逐条拆解

3.1 只写“做什么”,不要写“你是谁”

官方反复强调的一点是,SKILL.md的正文应该聚焦于任务本身:输入是什么、输出是什么、中间经历哪些步骤、遵循什么标准。它不需要自我介绍,不需要写“你是一个专业的 Python 发布工程师”,不需要渲染语气或人格。

刚开始我不太理解为什么要特别强调这个。后来试过一次在技能开头加了一大段“角色设定”之后明白了:这类内容会污染指令优先级。Claude Code 本身已经有系统级的智能体设定,技能里再叠一套角色描述就可能出现两套指令打架,或者模型把注意力放在“扮演角色”而不是“完成任务”上。技能应该像一份标准作业程序,平铺直叙写流程和验收标准,效果最好。

实操层面的一个直观对比。我早期写过一个发布检查技能,开头是“你是一名严谨的 SRE 工程师,请以专业的态度检查以下事项,注意每一个细节并且要非常耐心”。后来删掉这些,直接写“发布前依次检查:版本号已更新、变更日志已补、依赖锁定文件已刷新、测试已全量通过。全部通过后再执行推送”。输出质量不降反升,因为模型更清楚该做什么而不是该是什么。

注意:SKILL.md 正文不是营销文案,写“做什么”永远比写“你是谁”有用。

3.2 渐进式披露:入口极简,细节下沉

渐进式披露(Progressive Disclosure)是官方最佳实践里我认为最有工程价值的一条。核心思想是:SKILL.md只承担“入口”和“流程骨架”的角色,详细到可以直接执行,但不要在入口文件里堆砌大量模板、长命令输出、代码规范全集。更详细的参考资料应该作为独立文件放进resources或scripts子目录,在流程进行到具体步骤时再打开读取。

这里有一个度的把握需要实测体会。入口文件太薄只剩一个索引,模型可能误以为信息不足而拒绝执行;入口文件太厚,渐进式披露的意义就消失了。我的经验是:SKILL.md 写工作步骤、检查项、验证方法,也就是模型必须一步步推进的“主干”;而完整的风格指南、字段对照表、几百行命令示例这些“枝叶”,放到子目录里。用生活类比来说,SKILL.md是导游手里的路线图,只标出关键节点;景点深度讲解留到走到对应位置再翻书。

从上下文开销的角度看,这个做法的收益是累积性的。假设一个技能有十个可能用到的参考资源,但某一次任务实际只需要两个,渐进式披露能把这次调用省下的八个资源固定下来,长此以往节省的 token 相当可观。

3.3 不重复造轮子,不和既有能力打架

另一条很容易被忽略的最佳实践是:技能里不要写 Claude Code“本来就会”的东西。官方文档明确警告过,不要在技能里堆砌“通用对话规则”或“基础编码规范”,那既不能显著改变模型行为,又会白白占用上下文。

说得直白一点,你不需要写“请使用有意义的变量名”“请在动手前给用户一个计划”,这些已经在系统层得到处理。技能要写的是“这个具体流程特有的知识”:比如发布前必须跑哪个测试套件,版本号统一在哪个文件里维护,回滚时先执行哪条命令。

同样要避免的是技能和技能之间的规则冲突。我在项目里同时放了“代码审查”和“提交前检查”两个技能,一开始没注意,前者要求“所有改动必须拆分成小提交”,后者写着“一次把所有改动一并提交”,模型加载后直接行为分裂。后来我把所有有交集的操作项拉出来统一口径,才解决了这个问题。建立技能目录的同时其实也在建立一套规则之间的一致性管理,这个意识比任何具体写法都重要。

3.4 警惕“禁止清单”带来的反效果

官方最佳实践里提到的“不要使用否定指令”这个建议,我一开始将信将疑,后来在实测中逐渐认同了。反面教材是这样的:某个技能里我写了十几条“不要”,比如“不要忽略版本号”“不要跳过测试”“不要在没确认前推送”,理由是上次模型犯过错,我想用禁止项把漏洞堵上。运行下来发现问题更严重:模型像戴了紧箍咒一样畏首畏尾,有些正常操作也因为和某条“不要”沾边而被跳过,反而产生了新错误。

不是说不能写禁止项,而是建议少用、慎用,并且尽量把否定表述改成正向动作。比如“不要跳过测试”改成“推送前必须运行完整测试套件且全部通过”;“不要在没确认前推送”改成“推送操作必须等到用户明确确认后执行”。正向指令给出了具体行为标准,模型更容易遵循,上下文表达效率也更高。

4. 实操:从一个可用的发布 Skill 看完整流程

4.1 场景定义与目录初始化

理论讲了不少,这里用一个我实际在用的例子走一遍完整创建流程。场景是一个 Python 项目的发版流程,涉及修改版本号、刷新依赖锁定、跑测试、打标签、推送这组动作。我准备把它沉淀成一个名为py-release的 Skill。

目录方面,我选择放在项目级.claude/skills/py-release/下,因为这个流程只对这个项目有意义。初始结构如下:

.claude/skills/py-release/ ├── SKILL.md ├── scripts/ │ └── check_version.py └── resources/ └── CHANGELOG_TEMPLATE.md

scripts/check_version.py的作用是抽取出“检查版本号是否合法且未发布”这个逻辑,放进脚本里之后,模型不必靠猜测判断版本号规则,直接运行脚本拿结果即可。resources/CHANGELOG_TEMPLATE.md则是用来规范变更日志格式的模板文件。

4.2 SKILL.md 全文示例

下面是这个SKILL.md的完整内容,结构上严格按照官方推荐的最佳实践来:YAML 头部定义名称和精确描述,正文聚焦流程步骤,引用资源文件而不是粘贴大段内容。

--- name: py-release description: 用于执行 Python 包的发布前检查与发布流程。当用户要求“发布”“打版本”“执行 release”“推送新版本”时使用此技能。不用于日常依赖安装、单测调试或需求开发。 --- # Python 包发布流程 按照以下步骤执行发布。每一步完成后再进入下一步。 1. 检查发布环境 - 运行 `git status` 确认工作区干净。 - 运行 `scripts/check_version.py` 检查当前版本号是否合法、是否尚未被占用。 2. 更新元信息 - 按 `resources/CHANGELOG_TEMPLATE.md` 格式补充变更日志。 - 在版本元信息文件中递增版本号,遵循语义化版本规范。 3. 验证 - 运行完整测试套件,要求全部通过。 - 生成并检查依赖锁定文件,确认没有意外漂移。 4. 发布确认 - 向用户展示本次发布的版本号与变更摘要。 - 获得明确确认后,创建 git 标签并推送,然后构建并上传产物到私有源。 5. 收尾 - 将新版本号输出给用户,并提示后续可执行的操作。

这份正文的长度控制在几百字内,不包含任何角色设定和冗余的原则性废话。每条指令都对应一个可执行动作,不会出现“请认真对待每一步”这种无法被执行的空洞要求。

4.3 测试触发与迭代优化

创建完成后,测试触发是我每次必做的事。我的做法是先直接用自然语言请求触发它,说“帮我走一遍发布流程”,确认技能被正确加载、步骤能完整执行。然后再测试描述词里的边界条件,比如“帮我把依赖更新一下”,这时候不应该触发py-release。

一个常见的问题是模型加载了技能但只执行了其中一部分步骤。这通常说明入口文件对“每一步完成后才能进入下一步”的强调不够。我后来在步骤之间加入了“上一步未通过则停止”的明确表述,问题才缓解。还有一个有效手段是让脚本把检查结果输出成结构化的信息,这样模型得到一个可靠的中间输入,而不是自己去解读原始文件。

技能不是一次写对的,我建议每次实际使用后花两分钟回看一遍:这次执行中哪些指令被忽略了,哪些描述造成了歧义,然后在SKILL.md里做增量修改。迭代是常态,官方 Best Practices 更像是在不断修正中发现的原则,而不是初稿就能完全满足的条条框框。

5. Skills 与其他机制的分工与配合

5.1 四类机制的边界

Claude Code 里存在几种容易混淆的扩展机制,它们的边界我花了不少时间才真正厘清。整理成表格会更直观:

机制核心作用加载方式典型用途
CLAUDE.md常驻记忆每次对话始终存在项目约定、代码风格、用户偏好
Skills可复用能力包任务匹配时按需加载发布流程、审查流程、报告生成
Commands斜杠快捷指令用户主动键入触发高频交互动作的入口封装
Agents独立子代理按需委派任务需要独立上下文和工具集的任务

理解这张表的关键在于“加载时机”这列。CLAUDE.md是线性存在于每个请求里的,Skills 则像函数调用,只有被调用才压栈。Commands 需要用户显式触发,它更适合做“菜单项”而不是“自动能力”;Agents 则是另一种更重量级的封装,适合做独立的子任务单元。刚开始可以不接触 Agents 和 Commands,先把 CLAUDE.md 与 Skills 的边界划清楚,收益就已经很大了。

5.2 组合使用的推荐姿势

我目前在实际项目中采用了一套组合方式。CLAUDE.md里只放三类东西:项目事实(技术栈、目录结构)、用户偏好(使用中文回答,风格倾向)、以及“哪些场景有哪些 Skills 可用”的一行索引。例如:

当需要执行发布流程时,使用 py-release 技能。

这行索引本身不在技能里,而是在记忆里,相当于告诉模型“遇到这事可以去找那个技能”。真正的流程完全下沉到技能目录。这个组合的好处是:CLAUDE.md 短,上下文开销小;规则不会腐蚀技能,技能也不会让记忆膨胀。

Commands 我用于一些纯交互型的操作,比如/review直接触发一次代码评审对话,这个场景不需要完整技能目录,交给斜杠命令更轻量。遇到边界情况时,我的判断逻辑是:机制是否只在特定任务才需要,是则 Skills;是否始终需要存在于每次对话,是则 CLAUDE.md;是否只是为了高频输入时的快捷方式,是则 Commands。

6. 高频问题与排查技巧实录

6.1 技能不触发或乱触发

这是讨论度最高的一个问题:技能建好了,但模型像没看见一样。按照我的排查经验,第一步先检查description,它是不是写得太模糊了。描述里只写“用于发布”却不写“当用户要求发布时使用”,模型在意图匹配时权重会低很多。建议明确写明触发场景关键词和“不用于”场景。

第二步检查是否有同名技能。用户级和项目级存在同名技能时,行为可能不符合直觉:项目级会遮蔽用户级。这时候需要看加载日志,确认实际加载的是哪一个。第三步看 SKILL.md 的 YAML 头部格式是否正确,字段名是否拼错,缩进是否符合 YAML 规范。一个不小心把description写成了discription,整个元信息解析就会失败,但这个失败不一定是报错的,技能只会“无声地失踪”。

6.2 上下文不降反升

有人试过 Skills 后抱怨上下文反而变大。我检查过这类案例,原因高度一致:在SKILL.md里贴了大量代码块和模板全文。当技能被触发时,这一大坨全文都会进上下文,如果这个技能又经常被误触发,开销自然暴增。

解决方案就是回到渐进式披露原则:把大段模板和代码样例放到resources子目录,在SKILL.md正文里只保留一句“步骤二中读取resources/xxx.md”。这既保证流程正常,又把进上下文的量控制在真正需要的范围内。另外一个偶尔碰到的情况是技能触发后模型把SKILL.md反复读取了多次,这通常是因为正文里没有明确告诉模型“这些步骤是一次性执行完的”,增加一句整体性的流程说明可以缓解。

6.3 同名冲突与路径问题

路径问题主要出现在脚本引用上。用相对路径引用技能内部文件是官方推荐的写法,这样整个技能目录可以整体移动。有些人图省事写了绝对路径或把资源写在技能目录之外,技能一旦换项目或换机器就失效。另一个和系统相关的问题是权限:放到scripts里的脚本如果没有可执行权限,Claude Code 执行时会直接失败,而且报错信息不一定会明确指到这里。

同名冲突再补充一点:官方在设计上同时支持用户级和项目级的存储位置,但这里存在优先级差异,我的排查经验是优先检查项目级目录,再看用户级。如果你发现改动用户级的技能“不生效”,八成是被项目级同名目录遮挡了,及时重命名或合并才是正解。

6.4 一个日常排错顺序建议

很多人在技能不工作的时候喜欢反复改description的措辞,这其实低效了。我建议按下面的顺序来:

  1. 目录是否存在、SKILL.md 文件名和拼写是否正确。
  2. YAML 头部是否能被正确解析,字段名是否合法。
  3. description 是否明确包含触发场景和反例边界。
  4. SKILL.md 正文是否存在逻辑矛盾或无法执行的指令。
  5. 引用的资源路径是否全部有效、脚本是否有运行权限。
  6. 是否有同名技能冲突,加载的是不是你最近改动的那一个。

这样一套查下来,绝大多数问题都能定位。排在后面的“描述措辞”实际上是最常见但也最容易被误判为原因的因素,真正的问题往往更基础。

7. 一些只有上手之后才明白的体会

Skills 这个东西,光看文档和不亲手写一个,理解深度完全是两回事。我做第一个技能的时候一心想着把能想到的东西都写进去,觉得写得越全越专业,结果模型执行起来既笨重又刻板。后来删掉那些模板化的长篇大论、仪式感十足的角色设定,保留真正可操作的流程和检查点时,效果反而立刻变好了。这大概就是官方从“提示词工程”走向“技能工程”这条思路的一个缩影。

另外,技能也是一个需要养护的东西。项目流程变了,发布步骤多了,如果技能不及时更新,它就会像一份过期的文档一样悄悄失去了价值。我自己现在是每两周花一点时间回看一遍技能目录,把使用过程中发现的问题顺手修掉。这个习惯带来的收益非常实在。如果你正在为 CLAUDE.md 越写越臃肿而头疼,建议从一个很小的、自己每天都在用的流程开始,试着把它变成一个 Skill,走完一遍之后你基本就能理解官方这份最佳实践里每一条建议背后的真实动机了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询