--- name: writing-skills description: 当创建新技能、编辑现有技能或在部署前验证技能是否有效时使用 --- # 编写技能 ## 概述 **编写技能就是将测试驱动开发应用于流程文档。** **个人技能存放在智能体特定的目录中(Claude Code 用 `~/.claude/skills`,Codex 用 `~/.agents/skills/`)** 你编写测试用例(带子智能体的压力场景),观察它们失败(基线行为),编写技能(文档),观察测试通过(智能体遵守规则),然后重构(堵住漏洞)。 **核心原则:** 如果你没有观察到智能体在没有该技能时失败,你就不知道这个技能是否教了正确的东西。 **必需背景:** 在使用此技能前,你必须理解 superpowers:test-driven-development。该技能定义了基本的红-绿-重构循环。本技能将 TDD 适配到文档编写中。 **官方指南:** Anthropic 官方的技能编写最佳实践请参见 anthropic-best-practices.md。该文档提供了补充本技能 TDD 导向方法的额外模式和指南。 ## 什么是技能? **技能**是经过验证的技术、模式或工具的参考指南。技能帮助未来的 Claude 实例找到并应用有效的方法。 **技能是:** 可复用的技术、模式、工具、参考指南 **技能不是:** 关于你某次如何解决问题的叙事 ## TDD 映射到技能 | TDD 概念 | 技能创建 | |----------|---------| | **测试用例** | 带子智能体的压力场景 | | **生产代码** | 技能文档(SKILL.md) | | **测试失败(红)** | 智能体在没有技能时违反规则(基线) | | **测试通过(绿)** | 智能体在有技能时遵守规则 | | **重构** | 在保持合规的同时堵住漏洞 | | **先写测试** | 在编写技能之前先运行基线场景 | | **观察失败** | 记录智能体使用的确切合理化借口 | | **最小代码** | 编写针对那些具体违规行为的技能 | | **观察通过** | 验证智能体现在遵守规则 | | **重构循环** | 发现新的合理化借口 → 堵住 → 重新验证 | 整个技能创建过程遵循红-绿-重构。 ## 何时创建技能 **创建条件:** - 技术对你来说不是直觉上显而易见的 - 你会在不同项目中反复引用 - 模式具有广泛适用性(非项目特定) - 其他人也会受益 **不要创建:** - 一次性解决方案 - 其他地方有充分文档的标准实践 - 项目特定的约定(放在 CLAUDE.md 中) - 机械性约束(如果可以用正则/验证强制执行,就自动化——文档留给需要判断的场景) ## 技能类型 ### 技术类 有具体步骤的方法(condition-based-waiting、root-cause-tracing) ### 模式类 思考问题的方式(flatten-with-flags、test-invariants) ### 参考类 API 文档、语法指南、工具文档(office docs) ## 目录结构 ``` skills/ skill-name/ SKILL.md # 主参考文档(必需) supporting-file.* # 仅在需要时 ``` **扁平命名空间** - 所有技能在一个可搜索的命名空间中 **分离文件的情况:** 1. **大量参考内容**(100+ 行)- API 文档、全面的语法说明 2. **可复用工具** - 脚本、实用程序、模板 **保持内联:** - 原则和概念 - 代码模式(< 50 行) - 其他所有内容 ## SKILL.md 结构 **Frontmatter(YAML):** - 两个必需字段:`name` 和 `description`(完整支持字段参见 [agentskills.io/specification](https://agentskills.io/specification)) - 总计最多 1024 字符 - `name`:只使用字母、数字和连字符(不要用括号、特殊字符) - `description`:第三人称,仅描述何时使用(不是做什么) - 以"Use when..."开头,聚焦于触发条件 - 包含具体的症状、场景和上下文 - **绝不总结技能的流程或工作流**(参见 CSO 章节了解原因) - 尽量控制在 500 字符以内 ```markdown --- name: Skill-Name-With-Hyphens description: Use when [具体的触发条件和症状] --- # 技能名称 ## 概述 这是什么?用 1-2 句话说明核心原则。 ## 何时使用 [如果决策不明显,使用小型内联流程图] 症状和用例的要点列表 不适用的场景 ## 核心模式(技术/模式类) 前后代码对比 ## 快速参考 用于快速浏览常见操作的表格或要点 ## 实现 简单模式内联代码 大量参考或可复用工具链接到文件 ## 常见错误 常见问题 + 修复方法 ## 实际效果(可选) 具体结果 ``` ## Claude 搜索优化(CSO) **发现至关重要:** 未来的 Claude 需要找到你的技能 ### 1. 丰富的描述字段 **目的:** Claude 读取描述来决定为当前任务加载哪些技能。让它能回答:"我现在应该读这个技能吗?" **格式:** 以"Use when..."开头,聚焦于触发条件 **关键:描述 = 何时使用,不是技能做什么** 描述应该只描述触发条件。不要在描述中总结技能的流程或工作流。 **为什么这很重要:** 测试表明,当描述总结了技能的工作流时,Claude 可能会跟随描述而非阅读完整的技能内容。一个写着"任务间进行代码审查"的描述导致 Claude 只做了一次审查,尽管技能的流程图清楚地展示了两次审查(先规格合规再代码质量)。 当描述改为仅"在当前会话中执行包含独立任务的实现计划时使用"(无工作流摘要)时,Claude 正确地阅读了流程图并遵循了两阶段审查流程。 **陷阱:** 总结工作流的描述创建了 Claude 会走的捷径。技能正文变成了 Claude 跳过的文档。 ```yaml # 错误:总结了工作流 - Claude 可能会跟随描述而非阅读技能 description: Use when executing plans - dispatches subagent per task with code review between tasks # 错误:流程细节太多 description: Use for TDD - write test first, watch it fail, write minimal code, refactor # 正确:只有触发条件,无工作流摘要 description: Use when executing implementation plans with independent tasks in the current session # 正确:仅触发条件 description: Use when implementing any feature or bugfix, before writing implementation code ``` **内容:** - 使用具体的触发条件、症状和场景来表明此技能适用 - 描述问题(竞态条件、行为不一致)而非语言特定的症状(setTimeout、sleep) - 保持触发条件技术无关,除非技能本身是技术特定的 - 如果技能是技术特定的,在触发条件中明确说明 - 用第三人称写(注入到系统提示中) - **绝不总结技能的流程或工作流** ```yaml # 错误:太抽象、模糊,未包含何时使用 description: For async testing # 错误:第一人称 description: I can help you with async tests when they're flaky # 错误:提到了技术但技能并非该技术特定的 description: Use when tests use setTimeout/sleep and are flaky # 正确:以"Use when"开头,描述问题,无工作流 description: Use when tests have race conditions, timing dependencies, or pass/fail inconsistently # 正确:技术特定的技能带有明确的触发条件 description: Use when using React Router and handling authentication redirects ``` ### 2. 关键词覆盖 使用 Claude 会搜索的词语: - 错误信息:"Hook timed out"、"ENOTEMPTY"、"race condition" - 症状:"flaky"、"hanging"、"zombie"、"pollution" - 同义词:"timeout/hang/freeze"、"cleanup/teardown/afterEach" - 工具:实际命令、库名称、文件类型 ### 3. 描述性命名 **使用主动语态,动词优先:** - ✅ `creating-skills` 而非 `skill-creation` - ✅ `condition-based-waiting` 而非 `async-test-helpers` ### 4. Token 效率(关键) **问题:** getting-started 和频繁引用的技能会加载到每个对话中。每个 token 都很重要。 **目标字数:** - getting-started 工作流:每个 <150 词 - 频繁加载的技能:总计 <200 词 - 其他技能:<500 词(仍要简洁) **技巧:** **将细节移到工具帮助中:** ```bash # 错误:在 SKILL.md 中列出所有参数 search-conversations supports --text, --both, --after DATE, --before DATE, --limit N # 正确:引用 --help search-conversations 支持多种模式和过滤器。运行 --help 查看详情。 ``` **使用交叉引用:** ```markdown # 错误:重复工作流细节 搜索时,用模板分派子智能体…… [20 行重复的说明] # 正确:引用其他技能 始终使用子智能体(节省 50-100 倍上下文)。必需:使用 [other-skill-name] 工作流。 ``` **压缩示例:** ```markdown # 错误:冗长的示例(42 词) 你的搭档:"我们之前是怎么处理 React Router 中的认证错误的?" 你:我来搜索过去对话中的 React Router 认证模式。 [用搜索查询分派子智能体:"React Router authentication error handling 401"] # 正确:精简的示例(20 词) 搭档:"我们之前是怎么处理 React Router 中的认证错误的?" 你:正在搜索…… [分派子智能体 → 整合] ``` **消除冗余:** - 不要重复交叉引用的技能中已有的内容 - 不要解释从命令中就能看出的东西 - 不要为同一模式提供多个示例 **验证:** ```bash wc -w skills/path/SKILL.md # getting-started 工作流:目标 <150 每个 # 其他频繁加载的:目标总计 <200 ``` **用你做的事或核心洞察来命名:** - ✅ `condition-based-waiting` > `async-test-helpers` - ✅ `using-skills` 而非 `skill-usage` - ✅ `flatten-with-flags` > `data-structure-refactoring` - ✅ `root-cause-tracing` > `debugging-techniques` **动名词(-ing)适合描述流程:** - `creating-skills`、`testing-skills`、`debugging-with-logs` - 主动的,描述你正在进行的操作 ### 4. 交叉引用其他技能 **编写引用其他技能的文档时:** 仅使用技能名称,带有明确的必需标记: - ✅ 好的:`**必需子技能:** 使用 superpowers:test-driven-development` - ✅ 好的:`**必需背景:** 你必须理解 superpowers:systematic-debugging` - ❌ 差的:`参见 skills/testing/test-driven-development`(不清楚是否必需) - ❌ 差的:`@skills/testing/test-driven-development/SKILL.md`(强制加载,浪费上下文) **为什么不用 @ 链接:** `@` 语法会立即强制加载文件,在你需要之前就消耗 200k+ 的上下文。 ## 流程图使用 ```dot digraph when_flowchart { "需要展示信息?" [shape=diamond]; "我可能在决策中犯错?" [shape=diamond]; "使用 markdown" [shape=box]; "小型内联流程图" [shape=box]; "需要展示信息?" -> "我可能在决策中犯错?" [label="是"]; "我可能在决策中犯错?" -> "小型内联流程图" [label="是"]; "我可能在决策中犯错?" -> "使用 markdown" [label="否"]; } ``` **仅在以下情况使用流程图:** - 非显而易见的决策点 - 你可能过早停止的流程循环 - "何时使用 A vs B"的决策 **绝不使用流程图用于:** - 参考资料 → 表格、列表 - 代码示例 → Markdown 代码块 - 线性指令 → 编号列表 - 无语义意义的标签(step1、helper2) 参见 @graphviz-conventions.dot 了解 graphviz 样式规则。 **为你的搭档可视化:** 使用此目录中的 `render-graphs.js` 将技能的流程图渲染为 SVG: ```bash ./render-graphs.js ../some-skill # 每个图表分别渲染 ./render-graphs.js ../some-skill --combine # 所有图表合并为一个 SVG ``` ## 代码示例 **一个优秀的示例胜过多个平庸的** 选择最相关的语言: - 测试技术 → TypeScript/JavaScript - 系统调试 → Shell/Python - 数据处理 → Python **好的示例:** - 完整可运行 - 注释良好,解释为什么 - 来自真实场景 - 清晰展示模式 - 可以直接适配(不是通用模板) **不要:** - 用 5 种以上语言实现 - 创建填空模板 - 写人为构造的示例 你擅长语言移植——一个优秀的示例就够了。 ## 文件组织 ### 自包含技能 ``` defense-in-depth/ SKILL.md # 所有内容内联 ``` 适用场景:所有内容都能放下,无需大量参考 ### 带可复用工具的技能 ``` condition-based-waiting/ SKILL.md # 概述 + 模式 example.ts # 可适配的工作代码 ``` 适用场景:工具是可复用的代码,不只是叙述 ### 带大量参考的技能 ``` pptx/ SKILL.md # 概述 + 工作流 pptxgenjs.md # 600 行 API 参考 ooxml.md # 500 行 XML 结构 scripts/ # 可执行工具 ``` 适用场景:参考资料太多无法内联 ## 铁律(与 TDD 相同) ``` 没有失败的测试就不写技能 ``` 这适用于新技能和对现有技能的编辑。 先写技能再测试?删掉它。重新开始。 编辑技能不测试?同样违规。 **无例外:** - 不适用于"简单的添加" - 不适用于"只是加一个章节" - 不适用于"文档更新" - 不要保留未测试的更改作为"参考" - 不要在运行测试时"调整" - 删除就是删除 **必需背景:** superpowers:test-driven-development 技能解释了为什么这很重要。相同的原则适用于文档。 ## 测试所有技能类型 不同类型的技能需要不同的测试方法: ### 纪律执行类技能(规则/要求) **例如:** TDD、完成前验证、编码前设计 **测试方式:** - 学术性问题:它们理解规则吗? - 压力场景:它们在压力下遵守吗? - 多重压力组合:时间 + 沉没成本 + 疲惫 - 识别合理化借口并添加明确的反驳 **成功标准:** 智能体在最大压力下遵循规则 ### 技术类技能(操作指南) **例如:** condition-based-waiting、root-cause-tracing、defensive-programming **测试方式:** - 应用场景:它们能正确应用技术吗? - 变体场景:它们能处理边界情况吗? - 缺失信息测试:说明是否有遗漏? **成功标准:** 智能体成功将技术应用于新场景 ### 模式类技能(心智模型) **例如:** reducing-complexity、information-hiding 概念 **测试方式:** - 识别场景:它们能识别模式何时适用吗? - 应用场景:它们能使用心智模型吗? - 反例:它们知道何时不应用吗? **成功标准:** 智能体正确识别何时/如何应用模式 ### 参考类技能(文档/API) **例如:** API 文档、命令参考、库指南 **测试方式:** - 检索场景:它们能找到正确的信息吗? - 应用场景:它们能正确使用找到的内容吗? - 覆盖测试:常见用例是否都涵盖了? **成功标准:** 智能体找到并正确应用参考信息 ## 跳过测试的常见合理化借口 | 借口 | 现实 | |------|------| | "技能显然很清晰" | 对你清晰 ≠ 对其他智能体清晰。测试它。 | | "这只是参考资料" | 参考资料可能有遗漏、不清楚的地方。测试检索。 | | "测试太过了" | 未测试的技能总有问题。15 分钟测试省下数小时。 | | "有问题再测试" | 问题 = 智能体无法使用技能。在部署前测试。 | | "测试太繁琐" | 测试比在生产中调试坏技能少繁琐得多。 | | "我有信心它很好" | 过度自信保证出问题。无论如何都要测试。 | | "学术审查就够了" | 阅读 ≠ 使用。测试应用场景。 | | "没时间测试" | 部署未测试的技能比后面修复浪费更多时间。 | **以上所有都意味着:部署前测试。无例外。** ## 让技能经受住合理化的考验 执行纪律的技能(如 TDD)需要抵抗合理化。智能体很聪明,在压力下会找到漏洞。 **心理学说明:** 理解说服技巧为什么有效有助于你系统性地应用它们。参见 persuasion-principles.md 了解研究基础(Cialdini, 2021; Meincke et al., 2025),涵盖权威、承诺、稀缺、社会认同和归属原则。 ### 明确堵住每个漏洞 不要只是陈述规则——禁止具体的变通方法: ```markdown 先写代码再写测试?删掉它。 ``` ```markdown 先写代码再写测试?删掉它。重新开始。 **无例外:** - 不要保留作为"参考" - 不要在写测试时"调整"它 - 不要看它 - 删除就是删除 ``` ### 应对"精神 vs 字面"的辩论 在前面加入基础原则: ```markdown **违反规则的字面意思就是违反规则的精神。** ``` 这切断了整类"我遵循的是精神"的合理化借口。 ### 构建合理化借口表 从基线测试中捕获合理化借口(参见下方测试章节)。智能体使用的每个借口都进入表中: ```markdown | 借口 | 现实 | |------|------| | "太简单不值得测试" | 简单的代码也会出错。测试只需 30 秒。 | | "我后面再测试" | 测试立即通过什么也证明不了。 | | "后写测试效果一样" | 后写测试 = "这做了什么?" 先写测试 = "这应该做什么?" | ``` ### 创建红线列表 让智能体容易自查是否在合理化: ```markdown ## 红线 - 停下来重新开始 - 先写代码再写测试 - "我已经手动测试过了" - "后写测试效果一样" - "重要的是精神不是仪式" - "这个情况不同,因为……" **以上所有都意味着:删除代码。用 TDD 重新开始。** ``` ### 更新 CSO 以包含违规症状 在描述中添加:你即将违反规则时的症状: ```yaml description: use when implementing any feature or bugfix, before writing implementation code ``` ## 技能的红-绿-重构 遵循 TDD 循环: ### 红:编写失败的测试(基线) 在没有技能的情况下运行压力场景。逐字记录行为: - 它们做了什么选择? - 它们使用了什么合理化借口(原文)? - 哪些压力触发了违规? 这就是"观察测试失败"——在编写技能之前你必须看到智能体自然会怎么做。 ### 绿:编写最小技能 编写针对那些具体合理化借口的技能。不要为假设情况添加额外内容。 用技能运行相同的场景。智能体应该现在遵守。 ### 重构:堵住漏洞 智能体找到了新的合理化借口?添加明确的反驳。重新测试直到无懈可击。 **测试方法论:** 参见 @testing-skills-with-subagents.md 了解完整的测试方法: - 如何编写压力场景 - 压力类型(时间、沉没成本、权威、疲惫) - 系统地堵住漏洞 - 元测试技巧 ## 反模式 ### 叙事式示例 "在 2025-10-03 的会话中,我们发现空的 projectDir 导致了……" **为什么不好:** 太具体,不可复用 ### 多语言稀释 example-js.js、example-py.py、example-go.go **为什么不好:** 质量平庸,维护负担重 ### 流程图中的代码 ```dot step1 [label="import fs"]; step2 [label="read file"]; ``` **为什么不好:** 无法复制粘贴,难以阅读 ### 通用标签 helper1、helper2、step3、pattern4 **为什么不好:** 标签应有语义意义 ## 停下:进入下一个技能之前 **编写任何技能后,你必须停下来完成部署流程。** **不要:** - 批量创建多个技能而不逐个测试 - 在当前技能验证前就进入下一个 - 因为"批量处理更高效"就跳过测试 **下面的部署清单对每个技能都是强制性的。** 部署未测试的技能 = 部署未测试的代码。这是对质量标准的违反。 ## 技能创建清单(TDD 适配版) **重要:使用 TodoWrite 为下面的每个清单项创建待办。** **红色阶段 - 编写失败的测试:** - [ ] 创建压力场景(纪律类技能需 3 个以上组合压力) - [ ] 在没有技能的情况下运行场景 - 逐字记录基线行为 - [ ] 识别合理化借口中的模式 **绿色阶段 - 编写最小技能:** - [ ] 名称只使用字母、数字、连字符(无括号/特殊字符) - [ ] YAML frontmatter 包含必需的 `name` 和 `description` 字段(最多 1024 字符;参见 [spec](https://agentskills.io/specification)) - [ ] 描述以"Use when..."开头并包含具体的触发条件/症状 - [ ] 描述用第三人称 - [ ] 全文包含搜索关键词(错误、症状、工具) - [ ] 带有核心原则的清晰概述 - [ ] 解决红色阶段识别出的具体基线失败 - [ ] 代码内联或链接到独立文件 - [ ] 一个优秀的示例(非多语言) - [ ] 用技能运行场景 - 验证智能体现在遵守 **重构阶段 - 堵住漏洞:** - [ ] 从测试中识别新的合理化借口 - [ ] 添加明确的反驳(纪律类技能) - [ ] 从所有测试迭代中构建合理化借口表 - [ ] 创建红线列表 - [ ] 重新测试直到无懈可击 **质量检查:** - [ ] 仅在决策不明显时使用小流程图 - [ ] 快速参考表 - [ ] 常见错误章节 - [ ] 无叙事性故事 - [ ] 支持文件仅用于工具或大量参考 **部署:** - [ ] 将技能提交到 git 并推送到你的 fork(如果已配置) - [ ] 考虑通过 PR 贡献回去(如果具有广泛用途) ## 发现工作流 未来的 Claude 如何找到你的技能: 1. **遇到问题**("测试不稳定") 3. **找到技能**(描述匹配) 4. **浏览概述**(这相关吗?) 5. **阅读模式**(快速参考表) 6. **加载示例**(仅在实现时) **为此流程优化** - 把可搜索的术语放在前面和各处。 ## 总结 **创建技能就是流程文档的 TDD。** 同样的铁律:没有失败的测试就不写技能。 同样的循环:红(基线)→ 绿(写技能)→ 重构(堵漏洞)。 同样的好处:更高的质量、更少的意外、无懈可击的结果。 如果你对代码遵循 TDD,对技能也应如此。这是同样的纪律应用于文档。