
1. 为什么 AI 编码助手总在关键时刻“失忆”用 Claude Code 写代码的人大概率都经历过这种场景上午刚跟它讲清楚项目用的是 pnpm 而不是 npm、测试跑 vitest 不跑 jest、组件目录在src/features而不是src/components下午开个新会话它又开始一本正经地给你npm install。更离谱的是同一个会话里聊到第三轮它已经忘了你前面强调过的“别动数据库迁移文件”手一抖就给你改了个字段类型。这不是模型变笨了而是上下文窗口的物理限制加上会话隔离机制共同造成的。Claude Code 这类 AI 编码助手本质上是无状态的每次对话都是把历史消息重新塞进上下文里。一旦对话轮次变多、文件读取变多、工具调用变多早期信息就会被挤出去或者被压缩得面目全非。你感觉它“失忆”其实是它从来没真正“记住”过。ponytail skill这个项目就是冲着这个痛点来的。它不是一个插件市场里的花哨工具而是一套用 skill 机制做上下文持久化管理的实践方案。核心思路很朴素既然模型记不住那就把该记的东西写成文件让它在需要的时候主动去读。听起来简单但怎么组织这些文件、什么时候触发读取、怎么避免把上下文撑爆里面全是细节。这篇文章适合三类人看一是已经在用 Claude Code 但被“失忆”折磨过的开发者二是想搞清楚 skill 机制到底能干什么、和 agent 有什么区别的人三是准备给自己的团队搭一套 AI 编码规范、但不知道从哪下手的技术负责人。我会从设计思路讲到具体配置再到实际踩过的坑尽量把每个决策背后的“为什么”说清楚。2. ponytail skill 的整体设计思路拆解2.1 核心问题定位不是模型不行是信息组织方式不对很多人遇到 AI 助手“失忆”第一反应是换个更强的模型或者把上下文窗口调大。但实测下来窗口从 200K 调到 1M该忘的还是忘。原因在于注意力稀释上下文里塞的东西越多每个 token 分到的注意力权重就越低关键信息反而更容易被淹没。ponytail skill 的设计出发点不是“塞更多”而是“在对的时候塞对的东西”。它把项目里那些稳定不变但每次都需要知道的信息从对话流里剥离出来变成独立的 skill 文件。模型在需要的时候通过工具调用去读取读完就用用完就释放不占用常驻上下文。这个思路和传统 RAG 有点像但区别在于RAG 是向量检索靠相似度匹配skill 是显式触发靠文件名和描述让模型自己判断该不该读。前者适合海量非结构化知识后者适合少量高确定性的操作规范。2.2 为什么选 skill 而不是 CLAUDE.md 或 system promptClaude Code 本身支持CLAUDE.md可以在项目根目录放一份全局说明。很多人第一反应是那我全写CLAUDE.md里不就行了问题在于CLAUDE.md是常驻上下文的。你写 500 字还行写 5000 字试试每次对话开头就吃掉一大块窗口而且里面大部分内容在当前任务里根本用不上。比如你写了一段“数据库迁移规范”但当前只是在改一个 CSS 样式这段规范就是纯浪费。skill 机制的优势在于按需加载。每个 skill 是一个独立目录里面有一个SKILL.md描述文件模型看到描述后判断“这个任务需不需要读它”。需要就读不需要就跳过。这样常驻上下文只保留 skill 的索引通常几十个 token实际内容在触发时才展开。提示skill 的触发依赖模型对描述的理解所以SKILL.md里的 description 字段写得越具体、越贴近实际任务场景触发准确率越高。写“项目规范”这种模糊描述模型基本不会主动读。2.3 ponytail skill 的目录结构设计ponytail skill 本身不是一个单一 skill而是一套skill 集合的组织范式。它的目录结构大致长这样.claude/ skills/ ponytail-project-context/ SKILL.md context/ tech-stack.md directory-layout.md coding-conventions.md ponytail-db-migration/ SKILL.md rules.md ponytail-testing/ SKILL.md test-patterns.md每个 skill 目录下必须有一个SKILL.md这是 Claude Code 识别 skill 的入口。其他文件是 skill 的“载荷”在SKILL.md里通过引用路径告诉模型去哪读。这种结构的核心考量是关注点分离技术栈、目录结构、编码规范放在一个 skill 里因为这三者通常一起被需要数据库迁移规范单独一个 skill因为只在特定任务触发测试模式单独一个因为写测试和写业务代码的上下文需求完全不同。2.4 和 agent 的区别skill 是知识agent 是行为热词里很多人搜“skill 和 agent 的区别”这里顺带说清楚。agent 是一个能自主决策、调用工具、执行多步任务的实体它有目标、有循环、有终止条件。skill 是一份结构化的知识或操作指南它本身不执行任何东西只是被 agent 读取后影响 agent 的行为。打个比方agent 是一个新来的员工skill 是员工手册里的某一章。员工遇到具体问题时去翻对应章节翻完照着做。手册本身不会主动干活但没有手册员工就得靠猜。ponytail skill 的定位就是“员工手册”而且是分章节、按需翻阅的手册。它不替代 agent 的决策能力而是给决策提供确定性的依据。3. 核心细节解析与实操要点3.1 SKILL.md 的写法description 决定生死SKILL.md的格式通常是 YAML frontmatter 加正文。frontmatter 里最关键的是name和description--- name: ponytail-project-context description: 当需要了解本项目的技术栈、目录结构、编码规范时读取。适用于新建文件、重构代码、回答项目相关问题时。不适用于纯样式调整或文档修改。 ---description 的写法有几个要点。第一说清楚什么时候该读用“当……时读取”这种句式。第二说清楚什么时候不该读避免模型过度触发。第三用具体场景词比如“新建文件”“重构代码”而不是“项目相关”这种万能词。正文部分不要写太长控制在 200 行以内。太长了模型读起来也费劲而且容易触发截断。如果内容确实多拆成多个文件在正文里用相对路径引用。3.2 上下文文件的组织分层比平铺好ponytail skill 里最容易被忽视的是上下文文件本身的结构。很多人把所有规范堆在一个rules.md里结果模型读的时候还是抓不住重点。推荐的做法是分层组织。以技术栈为例# 技术栈 ## 运行时 - Node.js 20 LTS - pnpm 9.x禁止使用 npm 或 yarn ## 框架 - React 18 TypeScript 5.4 - 状态管理用 Zustand禁止引入 Redux ## 测试 - 单元测试用 Vitest - E2E 用 Playwright每一层用二级标题分隔关键约束用加粗。模型读的时候会优先抓加粗内容这样即使只扫一眼也能拿到核心信息。注意不要在上下文文件里写“建议”“可以考虑”这类模糊表述。AI 助手对模糊指令的处理方式是“随机选一个”而不是“谨慎对待”。要写就写“必须”“禁止”“统一用”。3.3 触发时机的控制避免“读了个寂寞”skill 被触发的时机直接决定了它的价值。触发太早读了用不上浪费上下文触发太晚已经写错代码了才读得返工。ponytail skill 的做法是在SKILL.md的 description 里绑定具体动作。比如数据库迁移 skill 的 description 写成当需要修改数据库 schema、新增迁移文件、调整字段类型时读取。适用于涉及 prisma/schema.prisma 或 migrations 目录的任务。这样模型在接到“给用户表加个字段”的任务时会先判断这涉及 schema 修改然后主动去读这个 skill。而不是等它已经写完迁移文件了才想起来读规范。实测下来绑定文件路径的触发准确率最高。因为模型对路径的敏感度远高于对抽象描述的敏感度。3.4 版本管理skill 也要进 Git这一点很多人会忽略。skill 文件是项目规范的一部分必须和代码一起进版本控制。否则今天改了规范明天换台机器就丢了。ponytail skill 的实践是把.claude/skills/整个目录提交到仓库。团队里每个人拉下来就有一致的 skill 配置。新人入职第一天AI 助手就已经知道项目规范了不需要口口相传。如果团队有多个项目可以把通用的 skill 抽出来做成一个独立的 Git 仓库通过 submodule 或者软链接引入。但要注意跨项目的 skill 描述要写得更通用不能绑定具体路径。4. 实操过程与核心环节实现4.1 环境准备Claude Code 的安装与基础配置先确认 Claude Code 已经装好。不同系统的安装方式不一样Ubuntu 下通常用 npm 全局安装npm install -g anthropic-ai/claude-code装完后在项目根目录运行claude首次会引导你完成认证。认证方式这里不展开按官方提示走就行。装好后先跑一个claude --version确认版本。建议用较新的版本因为 skill 机制在早期版本里支持不完整。如果版本太老skill 目录可能根本不被识别。提示如果你在 VS Code 里用 Claude Code 插件注意插件版本和 CLI 版本要匹配。实测遇到过插件读不到 skill 的情况最后发现是插件内置的 CLI 版本太旧。4.2 创建第一个 ponytail skill在项目根目录建目录mkdir -p .claude/skills/ponytail-project-context/context然后创建SKILL.md--- name: ponytail-project-context description: 当需要了解本项目的技术栈、目录结构、编码规范时读取。适用于新建文件、重构代码、回答项目架构相关问题时。 --- # 项目上下文 本 skill 提供项目的核心技术约定。读取后请严格遵循不要凭经验猜测。 ## 技术栈 详见 context/tech-stack.md ## 目录结构 详见 context/directory-layout.md ## 编码规范 详见 context/coding-conventions.md再创建三个上下文文件。以tech-stack.md为例# 技术栈 ## 包管理 - **必须使用 pnpm**禁止 npm 和 yarn - 安装依赖用 pnpm add不要用 pnpm install pkg ## 构建 - 构建工具 Vite 5.x - 禁止引入 webpack 相关配置 ## 代码质量 - ESLint Prettier提交前必须通过 lint - TypeScript 严格模式开启禁止 any写完保存重启 Claude Code 会话。然后问它“这个项目用什么包管理器”如果它回答 pnpm说明 skill 被正确读取了。4.3 验证 skill 是否生效的三种方法第一种直接问。像上面那样问一个只有读了 skill 才能答对的问题。如果答错说明没触发。第二种看日志。Claude Code 在读取 skill 时会在输出里显示“Reading skill: xxx”。如果没看到这行就是没触发。第三种故意诱导。问一个 skill 里明确禁止的操作比如“帮我用 npm 装个 lodash”。如果它拒绝并说“项目规定用 pnpm”说明 skill 生效了。如果三种方法都失败检查三件事skill 目录路径对不对、SKILL.md的 frontmatter 格式对不对、description 是不是写得太模糊。4.4 参数计算上下文预算怎么分配上下文窗口是有限资源skill 不能无限膨胀。假设窗口是 200K token常驻部分system prompt 对话历史大概占 30K工具调用结果占 50K留给 skill 读取的预算大概 20K 到 30K。按这个预算倒推单个 skill 的SKILL.md加被引用文件的总 token 数最好控制在 3000 以内。中文大概 1 字 1.5 token也就是 2000 字左右。超过这个量要么拆成多个 skill要么精简内容。实测下来一个 skill 读 3000 token模型能记住 80% 以上读到 8000 token记住的不到一半。所以宁可拆细不要堆大。4.5 多 skill 协同避免互相打架项目大了会有多个 skill比如项目上下文、数据库规范、测试规范、API 规范。它们之间可能冲突比如项目上下文说“统一用 camelCase”API 规范说“接口字段用 snake_case”。ponytail skill 的处理方式是在项目上下文 skill 里声明优先级## skill 优先级 当多个 skill 规则冲突时按以下优先级 1. 数据库迁移规范 2. API 规范 3. 项目上下文 4. 测试规范这样模型在遇到冲突时有明确的裁决依据不会随机选一个。5. 常见问题与排查技巧实录5.1 skill 不触发九成是 description 的问题这是最高频的问题。表现是skill 文件明明在那模型就是不读。排查顺序先看 description 里有没有“当……时读取”这种触发条件句。没有的话加上。再看 description 里有没有具体场景词比如“新建文件”“修改 schema”。如果全是“项目相关”“开发时”这种词模型判断不了该不该读。还有一个隐蔽原因description 太长。超过 200 字模型可能只读前半段就下判断了。控制在 100 字以内最稳。5.2 skill 触发太频繁加否定条件反过来有些 skill 被过度触发。比如项目上下文 skill 在改一个纯文案的时候也被读了纯浪费。解决办法是在 description 里加否定条件“不适用于纯样式调整、文档修改、文案变更。”模型看到否定条件会主动排除这些场景。5.3 读了 skill 但没遵守内容太抽象有时候 skill 确实被读了但模型还是按自己的习惯来。原因通常是 skill 内容写得太抽象比如“代码要整洁”“命名要规范”。这种话模型读了等于没读。改成具体规则“函数名用动词开头如fetchUser而不是userFetch”“单个函数不超过 50 行”。越具体遵守率越高。5.4 常见问题速查表问题现象最可能原因解决动作skill 完全不触发description 缺触发条件加“当……时读取”句式skill 偶尔触发description 场景词太泛换成具体动作词触发太频繁缺否定条件加“不适用于……”读了不遵守规则太抽象改成可验证的具体规则读一半截断单 skill 太大拆成多个 skill多 skill 冲突没声明优先级在项目上下文里定优先级换机器后失效skill 没进 Git提交.claude/skills/目录VS Code 里不生效插件 CLI 版本旧升级插件或改用 CLI5.5 独家避坑别把 skill 当文档写我踩过最大的坑是把 skill 当项目文档写。洋洋洒洒几千字把架构设计、历史决策、未来规划全塞进去。结果模型读完之后注意力全被历史决策吸引反而忽略了当前任务需要的编码规范。skill 的本质是操作指令不是知识库。写的时候时刻问自己这条信息在当前任务里会被用到吗用不到就删。宁可少写不要多写。少写顶多是模型不知道多写是模型被干扰。另一个坑是skill 之间内容重复。比如项目上下文里写了“用 pnpm”测试规范里又写一遍。重复内容会让模型困惑到底以哪个为准解决办法是单一事实来源同一个规则只在一个 skill 里出现其他地方用引用。6. 从 ponytail skill 延伸出的上下文管理思路6.1 把“失忆”问题转化成“检索”问题ponytail skill 给我的最大启发是不要试图让模型记住而是让它知道去哪找。这和人脑的工作方式其实很像你不需要记住所有细节只需要记住“遇到这类问题该翻哪本书”。沿着这个思路可以把更多东西 skill 化。比如代码审查清单、部署流程、故障排查手册、甚至会议纪要模板。凡是“每次都需要知道但又不常变”的信息都适合做成 skill。6.2 和 CLAUDE.md 的分工CLAUDE.md适合放每次对话都必须知道的极简信息比如“这是一个 monorepo”“主分支是 main”。超过 200 字的内容就应该考虑挪到 skill 里。我的实践是CLAUDE.md只留三样东西项目一句话简介、skill 索引、紧急注意事项。其他全部下沉到 skill。这样常驻上下文占用最小模型启动最快。6.3 团队协作中的 skill 维护skill 是团队资产需要有人维护。建议指定一个人负责 skill 的更新其他人通过 PR 提修改。每次代码规范变更同步更新对应 skill。否则 skill 和实际规范脱节比没有 skill 还糟糕。可以定期做一次 skill 审计把每个 skill 读一遍问三个问题——还在用吗内容还准确吗有没有和其他 skill 重复三个月审计一次比较合适。6.4 后续可以怎么扩展ponytail skill 目前主要解决的是“项目规范记忆”问题。往下走可以扩展到任务模板把常见的开发任务新增 API、新增页面、修 bug做成 skill里面写清楚每个步骤该做什么、该检查什么。这样模型接到任务后不只是知道规范还知道流程。再往下可以结合 hook 机制做自动触发。比如检测到文件路径包含migrations自动加载数据库 skill不依赖模型自己判断。这个需要更深的配置但方向是明确的让上下文管理从“模型主动”变成“系统自动”。我个人在实际操作中的体会是skill 这套东西的价值不在于技术多先进而在于它逼着你把脑子里那些“默认大家都知道”的规范显式写出来。写的过程本身就是一次团队知识的梳理。很多时候写着写着就发现原来大家对同一个规范的理解根本不一致。这个发现比 skill 本身更有价值。