diff --git a/skills/writing-skills/CONTRIBUTORS b/skills/writing-skills/CONTRIBUTORS new file mode 100644 index 0000000..d8649da --- /dev/null +++ b/skills/writing-skills/CONTRIBUTORS @@ -0,0 +1 @@ +root diff --git a/skills/writing-skills/SKILL.md b/skills/writing-skills/SKILL.md new file mode 100644 index 0000000..9b31806 --- /dev/null +++ b/skills/writing-skills/SKILL.md @@ -0,0 +1,659 @@ +--- +name: writing-skills +description: 当创建新技能、编辑现有技能或在部署前验证技能是否有效时使用 +version: "1.0.0" +license: MIT +metadata: + hermes: + tags: [skills, documentation] +--- + +# 编写技能 + +## 概述 + +**编写技能就是将测试驱动开发应用于流程文档。** + +**个人技能存放在智能体特定的目录中(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,对技能也应如此。这是同样的纪律应用于文档。 diff --git a/skills/writing-skills/anthropic-best-practices.md b/skills/writing-skills/anthropic-best-practices.md new file mode 100644 index 0000000..009529d --- /dev/null +++ b/skills/writing-skills/anthropic-best-practices.md @@ -0,0 +1,1149 @@ +# 技能编写最佳实践 + +> 学习如何编写 Claude 能发现并成功使用的有效技能。 + +好的技能是简洁、结构良好、并经过真实使用测试的。本指南提供实用的编写决策,帮助你编写 Claude 能发现并有效使用的技能。 + +关于技能工作原理的概念背景,请参阅[技能概述](/en/docs/agents-and-tools/agent-skills/overview)。 + +## 核心原则 + +### 简洁是关键 + +[上下文窗口](https://platform.claude.com/docs/en/build-with-claude/context-windows)是公共资源。你的技能与 Claude 需要知道的所有其他内容共享上下文窗口,包括: + +* 系统提示 +* 对话历史 +* 其他技能的元数据 +* 你的实际请求 + +并非技能中的每个 token 都有即时成本。启动时,只有所有技能的元数据(name 和 description)被预加载。Claude 只在技能变得相关时才读取 SKILL.md,并且只在需要时才读取额外文件。然而,在 SKILL.md 中保持简洁仍然很重要:一旦 Claude 加载它,每个 token 都在与对话历史和其他上下文竞争。 + +**默认假设**:Claude 已经非常聪明 + +只添加 Claude 还不知道的上下文。对每条信息进行质疑: + +* "Claude 真的需要这个解释吗?" +* "我能假设 Claude 知道这个吗?" +* "这段话值得它的 token 成本吗?" + +**好的示例:简洁**(约 50 个 token): + +````markdown theme={null} +## 提取 PDF 文本 + +使用 pdfplumber 进行文本提取: + +```python +import pdfplumber + +with pdfplumber.open("file.pdf") as pdf: + text = pdf.pages[0].extract_text() +``` +```` + +**差的示例:太冗长**(约 150 个 token): + +```markdown theme={null} +## 提取 PDF 文本 + +PDF(便携式文档格式)文件是一种常见的文件格式,包含文本、图像和其他内容。 +要从 PDF 中提取文本,你需要使用一个库。有很多 PDF 处理库可用, +但我们推荐 pdfplumber,因为它易于使用且处理大多数情况都很好。 +首先,你需要使用 pip 安装它。然后你可以使用下面的代码…… +``` + +简洁版本假设 Claude 知道什么是 PDF 以及库是如何工作的。 + +### 设置适当的自由度 + +将具体程度与任务的脆弱性和可变性相匹配。 + +**高自由度**(基于文本的指令): + +适用场景: + +* 多种方案都有效 +* 决策取决于上下文 +* 启发式方法指导方案 + +示例: + +```markdown theme={null} +## 代码审查流程 + +1. 分析代码结构和组织 +2. 检查潜在的 bug 或边界情况 +3. 建议改善可读性和可维护性 +4. 验证是否遵循项目约定 +``` + +**中等自由度**(伪代码或带参数的脚本): + +适用场景: + +* 存在首选模式 +* 可以接受一些变化 +* 配置影响行为 + +示例: + +````markdown theme={null} +## 生成报告 + +使用此模板并根据需要自定义: + +```python +def generate_report(data, format="markdown", include_charts=True): + # 处理数据 + # 按指定格式生成输出 + # 可选包含可视化 +``` +```` + +**低自由度**(具体脚本,很少或没有参数): + +适用场景: + +* 操作脆弱且容易出错 +* 一致性至关重要 +* 必须遵循特定顺序 + +示例: + +````markdown theme={null} +## 数据库迁移 + +严格运行此脚本: + +```bash +python scripts/migrate.py --verify --backup +``` + +不要修改命令或添加额外参数。 +```` + +**类比**:把 Claude 想象成一个探索路径的机器人: + +* **两侧是悬崖的窄桥**:只有一条安全的路。提供具体的护栏和精确的指令(低自由度)。例如:必须按确切顺序运行的数据库迁移。 +* **没有障碍的开阔地**:很多路径都能成功。给出大方向,信任 Claude 找到最佳路线(高自由度)。例如:方案取决于上下文的代码审查。 + +### 用你计划使用的所有模型测试 + +技能作为模型的补充,因此效果取决于底层模型。用你计划使用的所有模型测试你的技能。 + +**按模型的测试考虑**: + +* **Claude Haiku**(快速、经济):技能是否提供了足够的指导? +* **Claude Sonnet**(平衡):技能是否清晰高效? +* **Claude Opus**(强大推理):技能是否避免了过度解释? + +对 Opus 完美工作的内容可能对 Haiku 需要更多细节。如果你计划跨多个模型使用技能,瞄准对所有模型都适用的指令。 + +## 技能结构 + + + **YAML Frontmatter**:SKILL.md 的 frontmatter 支持两个字段: + + * `name` - 技能的可读名称(最多 64 个字符) + * `description` - 技能做什么以及何时使用的一行描述(最多 1024 个字符) + + 完整的技能结构细节请参阅[技能概述](/en/docs/agents-and-tools/agent-skills/overview#skill-structure)。 + + +### 命名约定 + +使用一致的命名模式使技能更容易引用和讨论。我们推荐使用**动名词形式**(动词 + -ing)作为技能名称,因为这清楚地描述了技能提供的活动或能力。 + +**好的命名示例(动名词形式)**: + +* "Processing PDFs" +* "Analyzing spreadsheets" +* "Managing databases" +* "Testing code" +* "Writing documentation" + +**可接受的替代方案**: + +* 名词短语:"PDF Processing"、"Spreadsheet Analysis" +* 动作导向:"Process PDFs"、"Analyze Spreadsheets" + +**避免**: + +* 模糊的名称:"Helper"、"Utils"、"Tools" +* 过于通用:"Documents"、"Data"、"Files" +* 技能集合中命名模式不一致 + +一致的命名便于: + +* 在文档和对话中引用技能 +* 一眼就能理解技能的作用 +* 组织和搜索多个技能 +* 维护专业、连贯的技能库 + +### 编写有效的描述 + +`description` 字段用于技能发现,应包含技能做什么以及何时使用。 + + + **始终用第三人称写**。描述被注入系统提示中,不一致的人称视角会导致发现问题。 + + * **好的:** "Processes Excel files and generates reports" + * **避免:** "I can help you process Excel files" + * **避免:** "You can use this to process Excel files" + + +**具体且包含关键术语**。同时包含技能做什么和何时使用的具体触发条件/上下文。 + +每个技能只有一个描述字段。描述对技能选择至关重要:Claude 使用它从可能 100 多个可用技能中选择正确的技能。你的描述必须提供足够的细节让 Claude 知道何时选择此技能,而 SKILL.md 的其余部分提供实现细节。 + +有效的示例: + +**PDF 处理技能:** + +```yaml theme={null} +description: Extract text and tables from PDF files, fill forms, merge documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction. +``` + +**Excel 分析技能:** + +```yaml theme={null} +description: Analyze Excel spreadsheets, create pivot tables, generate charts. Use when analyzing Excel files, spreadsheets, tabular data, or .xlsx files. +``` + +**Git 提交助手技能:** + +```yaml theme={null} +description: Generate descriptive commit messages by analyzing git diffs. Use when the user asks for help writing commit messages or reviewing staged changes. +``` + +避免模糊的描述: + +```yaml theme={null} +description: Helps with documents +``` + +```yaml theme={null} +description: Processes data +``` + +```yaml theme={null} +description: Does stuff with files +``` + +### 渐进式披露模式 + +SKILL.md 作为概述,按需指向详细材料,就像入门指南中的目录。关于渐进式披露如何工作的解释,请参阅概述中的[技能工作原理](/en/docs/agents-and-tools/agent-skills/overview#how-skills-work)。 + +**实用指导:** + +* SKILL.md 正文保持在 500 行以内以获得最佳性能 +* 接近此限制时将内容拆分到独立文件 +* 使用以下模式有效地组织指令、代码和资源 + +#### 可视化概览:从简单到复杂 + +基本技能只需一个包含元数据和指令的 SKILL.md 文件: + +简单的 SKILL.md 文件,展示 YAML frontmatter 和 markdown 正文 + +随着技能增长,你可以捆绑额外的内容,Claude 只在需要时才加载: + +捆绑额外的参考文件如 reference.md 和 forms.md。 + +完整的技能目录结构可能如下: + +``` +pdf/ +├── SKILL.md # 主指令(触发时加载) +├── FORMS.md # 表单填写指南(按需加载) +├── reference.md # API 参考(按需加载) +├── examples.md # 使用示例(按需加载) +└── scripts/ + ├── analyze_form.py # 实用脚本(执行,不加载) + ├── fill_form.py # 表单填写脚本 + └── validate.py # 验证脚本 +``` + +#### 模式 1:高层指南加引用 + +````markdown theme={null} +--- +name: PDF Processing +description: Extracts text and tables from PDF files, fills forms, and merges documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction. +--- + +# PDF 处理 + +## 快速开始 + +用 pdfplumber 提取文本: +```python +import pdfplumber +with pdfplumber.open("file.pdf") as pdf: + text = pdf.pages[0].extract_text() +``` + +## 高级功能 + +**表单填写**:参见 [FORMS.md](FORMS.md) 获取完整指南 +**API 参考**:参见 [REFERENCE.md](REFERENCE.md) 获取所有方法 +**示例**:参见 [EXAMPLES.md](EXAMPLES.md) 获取常见模式 +```` + +Claude 只在需要时才加载 FORMS.md、REFERENCE.md 或 EXAMPLES.md。 + +#### 模式 2:领域特定组织 + +对于有多个领域的技能,按领域组织内容以避免加载不相关的上下文。当用户询问销售指标时,Claude 只需要读取销售相关的 schema,而非财务或营销数据。这保持了 token 使用低和上下文聚焦。 + +``` +bigquery-skill/ +├── SKILL.md(概述和导航) +└── reference/ + ├── finance.md(收入、账单指标) + ├── sales.md(商机、管道) + ├── product.md(API 使用、功能) + └── marketing.md(营销活动、归因) +``` + +````markdown SKILL.md theme={null} +# BigQuery 数据分析 + +## 可用数据集 + +**财务**:收入、ARR、账单 → 参见 [reference/finance.md](reference/finance.md) +**销售**:商机、管道、客户 → 参见 [reference/sales.md](reference/sales.md) +**产品**:API 使用、功能、采用率 → 参见 [reference/product.md](reference/product.md) +**营销**:活动、归因、邮件 → 参见 [reference/marketing.md](reference/marketing.md) + +## 快速搜索 + +使用 grep 查找特定指标: + +```bash +grep -i "revenue" reference/finance.md +grep -i "pipeline" reference/sales.md +grep -i "api usage" reference/product.md +``` +```` + +#### 模式 3:条件性细节 + +展示基本内容,链接到高级内容: + +```markdown theme={null} +# DOCX 处理 + +## 创建文档 + +使用 docx-js 创建新文档。参见 [DOCX-JS.md](DOCX-JS.md)。 + +## 编辑文档 + +简单编辑可直接修改 XML。 + +**修订追踪**:参见 [REDLINING.md](REDLINING.md) +**OOXML 细节**:参见 [OOXML.md](OOXML.md) +``` + +Claude 只在用户需要这些功能时才读取 REDLINING.md 或 OOXML.md。 + +### 避免深层嵌套引用 + +当引用来自其他被引用文件时,Claude 可能只部分读取文件。遇到嵌套引用时,Claude 可能使用 `head -100` 等命令预览内容而非读取完整文件,导致信息不完整。 + +**从 SKILL.md 到引用保持一层深度**。所有引用文件应直接从 SKILL.md 链接,以确保 Claude 在需要时读取完整文件。 + +**差的示例:太深**: + +```markdown theme={null} +# SKILL.md +参见 [advanced.md](advanced.md)... + +# advanced.md +参见 [details.md](details.md)... + +# details.md +这里是实际信息... +``` + +**好的示例:一层深度**: + +```markdown theme={null} +# SKILL.md + +**基本用法**:[SKILL.md 中的指令] +**高级功能**:参见 [advanced.md](advanced.md) +**API 参考**:参见 [reference.md](reference.md) +**示例**:参见 [examples.md](examples.md) +``` + +### 为较长的参考文件添加目录 + +对于超过 100 行的参考文件,在顶部包含目录。这确保 Claude 即使在部分读取预览时也能看到可用信息的完整范围。 + +**示例**: + +```markdown theme={null} +# API 参考 + +## 目录 +- 认证和设置 +- 核心方法(创建、读取、更新、删除) +- 高级功能(批量操作、webhooks) +- 错误处理模式 +- 代码示例 + +## 认证和设置 +... + +## 核心方法 +... +``` + +Claude 可以读取完整文件或按需跳转到特定章节。 + +关于这种基于文件系统的架构如何实现渐进式披露的详细信息,请参阅下方高级部分的[运行时环境](#runtime-environment)章节。 + +## 工作流和反馈循环 + +### 对复杂任务使用工作流 + +将复杂操作分解为清晰的顺序步骤。对于特别复杂的工作流,提供一个 Claude 可以复制到响应中并在进展时逐项勾选的清单。 + +**示例 1:研究综合工作流**(无代码的技能): + +````markdown theme={null} +## 研究综合工作流 + +复制此清单并跟踪你的进度: + +``` +研究进度: +- [ ] 步骤 1:阅读所有源文档 +- [ ] 步骤 2:识别关键主题 +- [ ] 步骤 3:交叉验证论点 +- [ ] 步骤 4:创建结构化摘要 +- [ ] 步骤 5:验证引用 +``` + +**步骤 1:阅读所有源文档** + +审查 `sources/` 目录中的每个文档。记录主要论点和支持证据。 + +**步骤 2:识别关键主题** + +寻找跨源的模式。哪些主题反复出现?源之间在哪里一致或分歧? + +**步骤 3:交叉验证论点** + +对于每个主要论点,验证它出现在源材料中。记录哪个源支持每个要点。 + +**步骤 4:创建结构化摘要** + +按主题组织发现。包含: +- 主要论点 +- 来自源的支持证据 +- 矛盾观点(如果有) + +**步骤 5:验证引用** + +检查每个论点是否引用了正确的源文档。如果引用不完整,返回步骤 3。 +```` + +此示例展示了工作流如何应用于不需要代码的分析任务。清单模式适用于任何复杂的多步骤过程。 + +**示例 2:PDF 表单填写工作流**(有代码的技能): + +````markdown theme={null} +## PDF 表单填写工作流 + +复制此清单并在完成时逐项勾选: + +``` +任务进度: +- [ ] 步骤 1:分析表单(运行 analyze_form.py) +- [ ] 步骤 2:创建字段映射(编辑 fields.json) +- [ ] 步骤 3:验证映射(运行 validate_fields.py) +- [ ] 步骤 4:填写表单(运行 fill_form.py) +- [ ] 步骤 5:验证输出(运行 verify_output.py) +``` + +**步骤 1:分析表单** + +运行:`python scripts/analyze_form.py input.pdf` + +这会提取表单字段及其位置,保存到 `fields.json`。 + +**步骤 2:创建字段映射** + +编辑 `fields.json` 为每个字段添加值。 + +**步骤 3:验证映射** + +运行:`python scripts/validate_fields.py fields.json` + +在继续之前修复所有验证错误。 + +**步骤 4:填写表单** + +运行:`python scripts/fill_form.py input.pdf fields.json output.pdf` + +**步骤 5:验证输出** + +运行:`python scripts/verify_output.py output.pdf` + +如果验证失败,返回步骤 2。 +```` + +清晰的步骤防止 Claude 跳过关键验证。清单帮助 Claude 和你跟踪多步骤工作流的进度。 + +### 实现反馈循环 + +**常见模式**:运行验证器 → 修复错误 → 重复 + +此模式大幅提高输出质量。 + +**示例 1:风格指南合规**(无代码的技能): + +```markdown theme={null} +## 内容审查流程 + +1. 按照 STYLE_GUIDE.md 中的指南起草内容 +2. 按清单审查: + - 检查术语一致性 + - 验证示例遵循标准格式 + - 确认所有必需章节都存在 +3. 如果发现问题: + - 记录每个问题及具体章节引用 + - 修改内容 + - 再次审查清单 +4. 只有所有要求满足后才继续 +5. 最终定稿并保存文档 +``` + +这展示了使用参考文档而非脚本的验证循环模式。"验证器"就是 STYLE_GUIDE.md,Claude 通过阅读和比较来执行检查。 + +**示例 2:文档编辑流程**(有代码的技能): + +```markdown theme={null} +## 文档编辑流程 + +1. 对 `word/document.xml` 进行编辑 +2. **立即验证**:`python ooxml/scripts/validate.py unpacked_dir/` +3. 如果验证失败: + - 仔细审查错误信息 + - 修复 XML 中的问题 + - 再次运行验证 +4. **只有验证通过后才继续** +5. 重新打包:`python ooxml/scripts/pack.py unpacked_dir/ output.docx` +6. 测试输出文档 +``` + +验证循环能及早发现错误。 + +## 内容指南 + +### 避免时间敏感的信息 + +不要包含会过时的信息: + +**差的示例:时间敏感**(会变得不正确): + +```markdown theme={null} +如果你在 2025 年 8 月之前做这件事,使用旧 API。 +2025 年 8 月之后,使用新 API。 +``` + +**好的示例**(使用"旧模式"章节): + +```markdown theme={null} +## 当前方法 + +使用 v2 API 端点:`api.example.com/v2/messages` + +## 旧模式 + +
+旧版 v1 API(2025-08 弃用) + +v1 API 使用:`api.example.com/v1/messages` + +此端点不再支持。 +
+``` + +旧模式章节提供历史上下文而不会干扰主要内容。 + +### 使用一致的术语 + +选择一个术语并在整个技能中统一使用: + +**好的 - 一致**: + +* 始终用"API endpoint" +* 始终用"field" +* 始终用"extract" + +**差的 - 不一致**: + +* 混用"API endpoint"、"URL"、"API route"、"path" +* 混用"field"、"box"、"element"、"control" +* 混用"extract"、"pull"、"get"、"retrieve" + +一致性帮助 Claude 理解和遵循指令。 + +## 常见模式 + +### 模板模式 + +为输出格式提供模板。将严格程度与你的需求匹配。 + +**严格要求时**(如 API 响应或数据格式): + +````markdown theme={null} +## 报告结构 + +始终使用这个精确的模板结构: + +```markdown +# [分析标题] + +## 摘要 +[关键发现的一段概述] + +## 关键发现 +- 发现 1 及支持数据 +- 发现 2 及支持数据 +- 发现 3 及支持数据 + +## 建议 +1. 具体可操作的建议 +2. 具体可操作的建议 +``` +```` + +**灵活指导时**(当适应性有用时): + +````markdown theme={null} +## 报告结构 + +这是一个合理的默认格式,但请根据分析情况自行判断: + +```markdown +# [分析标题] + +## 摘要 +[概述] + +## 关键发现 +[根据你的发现调整章节] + +## 建议 +[根据具体上下文定制] +``` + +根据具体分析类型按需调整章节。 +```` + +### 示例模式 + +对于输出质量取决于看到示例的技能,提供输入/输出对,就像常规提示一样: + +````markdown theme={null} +## 提交信息格式 + +按照这些示例生成提交信息: + +**示例 1:** +输入:添加了使用 JWT token 的用户认证 +输出: +``` +feat(auth): implement JWT-based authentication + +Add login endpoint and token validation middleware +``` + +**示例 2:** +输入:修复了报告中日期显示不正确的 bug +输出: +``` +fix(reports): correct date formatting in timezone conversion + +Use UTC timestamps consistently across report generation +``` + +**示例 3:** +输入:更新了依赖并重构了错误处理 +输出: +``` +chore: update dependencies and refactor error handling + +- Upgrade lodash to 4.17.21 +- Standardize error response format across endpoints +``` + +遵循此风格:type(scope): 简短描述,然后详细说明。 +```` + +示例比纯描述更能帮助 Claude 理解期望的风格和详细程度。 + +### 条件工作流模式 + +引导 Claude 通过决策点: + +```markdown theme={null} +## 文档修改工作流 + +1. 确定修改类型: + + **创建新内容?** → 遵循下方"创建工作流" + **编辑现有内容?** → 遵循下方"编辑工作流" + +2. 创建工作流: + - 使用 docx-js 库 + - 从头构建文档 + - 导出为 .docx 格式 + +3. 编辑工作流: + - 解压现有文档 + - 直接修改 XML + - 每次更改后验证 + - 完成后重新打包 +``` + + + 如果工作流变得大且复杂、有很多步骤,考虑将它们推到独立文件中,并告诉 Claude 根据手头的任务读取相应的文件。 + + +## 评估和迭代 + +### 先建立评估 + +**在编写大量文档之前创建评估。** 这确保你的技能解决的是真实问题而非想象中的问题。 + +**评估驱动的开发:** + +1. **识别差距**:在没有技能的情况下让 Claude 执行代表性任务。记录具体的失败或缺失的上下文 +2. **创建评估**:构建三个测试这些差距的场景 +3. **建立基线**:衡量 Claude 在没有技能时的表现 +4. **编写最小指令**:只创建足够解决差距和通过评估的内容 +5. **迭代**:执行评估,与基线对比,并优化 + +这种方法确保你解决的是实际问题而非可能永远不会出现的预期需求。 + +**评估结构**: + +```json theme={null} +{ + "skills": ["pdf-processing"], + "query": "从这个 PDF 文件中提取所有文本并保存到 output.txt", + "files": ["test-files/document.pdf"], + "expected_behavior": [ + "使用适当的 PDF 处理库或命令行工具成功读取 PDF 文件", + "从文档的所有页面提取文本内容,不遗漏任何页面", + "将提取的文本以清晰、可读的格式保存到名为 output.txt 的文件中" + ] +} +``` + + + 此示例演示了带有简单测试评分标准的数据驱动评估。我们目前不提供内置的评估运行方式。用户可以创建自己的评估系统。评估是你衡量技能有效性的真实来源。 + + +### 与 Claude 一起迭代开发技能 + +最有效的技能开发过程涉及 Claude 本身。与一个 Claude 实例("Claude A")一起创建技能,该技能将被其他实例("Claude B")使用。Claude A 帮助你设计和优化指令,而 Claude B 在真实任务中测试它们。这之所以有效,是因为 Claude 模型既理解如何编写有效的智能体指令,也理解智能体需要什么信息。 + +**创建新技能:** + +1. **不用技能完成一个任务**:用正常提示与 Claude A 一起解决问题。工作过程中,你自然会提供上下文、解释偏好、分享流程知识。注意你反复提供了什么信息。 + +2. **识别可复用的模式**:完成任务后,识别你提供的哪些上下文对类似的未来任务有用。 + + **示例**:如果你完成了一个 BigQuery 分析,你可能提供了表名、字段定义、过滤规则(如"始终排除测试账户")和常见查询模式。 + +3. **让 Claude A 创建技能**:"创建一个技能来捕获我们刚刚使用的 BigQuery 分析模式。包含表 schema、命名约定和关于过滤测试账户的规则。" + + + Claude 模型原生理解技能的格式和结构。你不需要特殊的系统提示或"编写技能"技能来让 Claude 帮助创建技能。只需让 Claude 创建技能,它就会生成结构正确的 SKILL.md 内容,包含适当的 frontmatter 和正文。 + + +4. **审查简洁性**:检查 Claude A 是否添加了不必要的解释。问:"去掉关于什么是胜率的解释——Claude 已经知道了。" + +5. **改善信息架构**:让 Claude A 更有效地组织内容。例如:"组织一下,让表 schema 在一个独立的参考文件中。我们以后可能会添加更多表。" + +6. **在类似任务上测试**:用 Claude B(加载了技能的全新实例)在相关用例上使用技能。观察 Claude B 是否找到了正确的信息、正确应用规则、成功处理了任务。 + +7. **基于观察迭代**:如果 Claude B 遇到困难或遗漏了什么,带着具体情况回到 Claude A:"当 Claude 使用这个技能时,它忘了在 Q4 按日期过滤。我们应该添加一个关于日期过滤模式的章节吗?" + +**迭代现有技能:** + +改进技能时继续同样的层级模式。你在以下之间交替: + +* **与 Claude A 合作**(帮助优化技能的专家) +* **用 Claude B 测试**(使用技能执行真实工作的智能体) +* **观察 Claude B 的行为**并将见解带回 Claude A + +1. **在真实工作流中使用技能**:给 Claude B(加载了技能的)实际任务,而非测试场景 + +2. **观察 Claude B 的行为**:记录它在哪里遇到困难、成功或做出意外选择 + + **观察示例**:"当我让 Claude B 做区域销售报告时,它写了查询但忘了过滤测试账户,尽管技能提到了这条规则。" + +3. **回到 Claude A 进行改进**:分享当前 SKILL.md 并描述你观察到的。问:"我注意到 Claude B 在我要求区域报告时忘了过滤测试账户。技能提到了过滤,但也许不够突出?" + +4. **审查 Claude A 的建议**:Claude A 可能建议重组以使规则更突出,使用更强的语言如"必须过滤"而非"始终过滤",或重构工作流章节。 + +5. **应用并测试更改**:用 Claude A 的改进更新技能,然后在类似请求上再次用 Claude B 测试 + +6. **基于使用重复**:在遇到新场景时继续这个观察-优化-测试循环。每次迭代基于真实的智能体行为而非假设来改进技能。 + +**收集团队反馈:** + +1. 与团队成员分享技能并观察他们的使用 +2. 问:技能是否在预期时激活?指令清楚吗?缺少什么? +3. 整合反馈以解决你自己使用模式中的盲点 + +**为什么这种方法有效**:Claude A 理解智能体需求,你提供领域专业知识,Claude B 通过真实使用揭示差距,迭代优化基于观察到的行为而非假设来改进技能。 + +### 观察 Claude 如何导航技能 + +迭代技能时,注意 Claude 在实践中实际如何使用它们。留意: + +* **意外的探索路径**:Claude 是否以你未预期的顺序读取文件?这可能表明你的结构不如你想的直观 +* **遗漏的连接**:Claude 是否未能跟随到重要文件的引用?你的链接可能需要更明确或更突出 +* **过度依赖某些章节**:如果 Claude 反复读取同一文件,考虑该内容是否应该放在主 SKILL.md 中 +* **被忽略的内容**:如果 Claude 从不访问某个捆绑文件,它可能不必要或在主指令中信号不明确 + +基于这些观察而非假设来迭代。技能元数据中的"name"和"description"尤其关键。Claude 使用它们来决定是否为当前任务触发技能。确保它们清楚地描述技能做什么以及何时使用。 + +## 要避免的反模式 + +### 避免 Windows 风格的路径 + +始终在文件路径中使用正斜杠,即使在 Windows 上: + +* ✓ **好的**:`scripts/helper.py`、`reference/guide.md` +* ✗ **避免**:`scripts\helper.py`、`reference\guide.md` + +Unix 风格的路径在所有平台上都能工作,而 Windows 风格的路径在 Unix 系统上会出错。 + +### 避免提供太多选项 + +除非必要,不要展示多种方案: + +````markdown theme={null} +**差的示例:太多选择**(令人困惑): +"你可以使用 pypdf,或 pdfplumber,或 PyMuPDF,或 pdf2image,或……" + +**好的示例:提供默认方案**(有备用方案): +"使用 pdfplumber 进行文本提取: +```python +import pdfplumber +``` + +对于需要 OCR 的扫描 PDF,改用 pdf2image 加 pytesseract。" +```` + +## 高级:带可执行代码的技能 + +以下章节聚焦于包含可执行脚本的技能。如果你的技能只使用 markdown 指令,跳到[有效技能清单](#checklist-for-effective-skills)。 + +### 解决问题,不要甩锅 + +编写技能的脚本时,处理错误条件而不是甩给 Claude。 + +**好的示例:明确处理错误**: + +```python theme={null} +def process_file(path): + """处理文件,如果不存在则创建。""" + try: + with open(path) as f: + return f.read() + except FileNotFoundError: + # 创建带默认内容的文件而非失败 + print(f"文件 {path} 未找到,正在创建默认文件") + with open(path, 'w') as f: + f.write('') + return '' + except PermissionError: + # 提供替代方案而非失败 + print(f"无法访问 {path},使用默认值") + return '' +``` + +**差的示例:甩给 Claude**: + +```python theme={null} +def process_file(path): + # 直接失败让 Claude 来处理 + return open(path).read() +``` + +配置参数也应该有理由和文档说明,以避免"巫术常量"(Ousterhout 定律)。如果你不知道正确的值,Claude 怎么确定? + +**好的示例:自文档化**: + +```python theme={null} +# HTTP 请求通常在 30 秒内完成 +# 更长的超时考虑了慢速连接 +REQUEST_TIMEOUT = 30 + +# 三次重试平衡了可靠性和速度 +# 大多数间歇性故障在第二次重试时就解决了 +MAX_RETRIES = 3 +``` + +**差的示例:魔法数字**: + +```python theme={null} +TIMEOUT = 47 # 为什么是 47? +RETRIES = 5 # 为什么是 5? +``` + +### 提供实用脚本 + +即使 Claude 可以编写脚本,预制脚本有其优势: + +**实用脚本的好处**: + +* 比生成的代码更可靠 +* 节省 token(无需在上下文中包含代码) +* 节省时间(无需代码生成) +* 确保跨使用的一致性 + +将可执行脚本与指令文件捆绑在一起 + +上图展示了可执行脚本如何与指令文件协同工作。指令文件(forms.md)引用脚本,Claude 可以在不将其内容加载到上下文中的情况下执行它。 + +**重要区分**:在指令中明确说明 Claude 应该: + +* **执行脚本**(最常见):"运行 `analyze_form.py` 提取字段" +* **作为参考阅读**(用于复杂逻辑):"参见 `analyze_form.py` 了解字段提取算法" + +对于大多数实用脚本,执行是首选因为它更可靠和高效。参见下方[运行时环境](#runtime-environment)章节了解脚本执行的工作原理。 + +**示例**: + +````markdown theme={null} +## 实用脚本 + +**analyze_form.py**:从 PDF 中提取所有表单字段 + +```bash +python scripts/analyze_form.py input.pdf > fields.json +``` + +输出格式: +```json +{ + "field_name": {"type": "text", "x": 100, "y": 200}, + "signature": {"type": "sig", "x": 150, "y": 500} +} +``` + +**validate_boxes.py**:检查边界框是否重叠 + +```bash +python scripts/validate_boxes.py fields.json +# 返回:"OK" 或列出冲突 +``` + +**fill_form.py**:将字段值应用到 PDF + +```bash +python scripts/fill_form.py input.pdf fields.json output.pdf +``` +```` + +### 使用视觉分析 + +当输入可以渲染为图像时,让 Claude 分析它们: + +````markdown theme={null} +## 表单布局分析 + +1. 将 PDF 转换为图像: + ```bash + python scripts/pdf_to_images.py form.pdf + ``` + +2. 分析每个页面图像以识别表单字段 +3. Claude 可以直观地看到字段位置和类型 +```` + + + 在此示例中,你需要编写 `pdf_to_images.py` 脚本。 + + +Claude 的视觉能力有助于理解布局和结构。 + +### 创建可验证的中间输出 + +当 Claude 执行复杂的开放性任务时,它可能会出错。"计划-验证-执行"模式通过让 Claude 首先创建结构化格式的计划,然后用脚本验证该计划再执行,来及早发现错误。 + +**示例**:想象让 Claude 根据电子表格更新 PDF 中的 50 个表单字段。没有验证的话,Claude 可能引用不存在的字段、创建冲突的值、遗漏必填字段或错误地应用更新。 + +**解决方案**:使用上面展示的工作流模式(PDF 表单填写),但添加一个中间 `changes.json` 文件在应用更改前进行验证。工作流变为:分析 → **创建计划文件** → **验证计划** → 执行 → 验证。 + +**为什么这个模式有效:** + +* **及早发现错误**:验证在更改应用前发现问题 +* **机器可验证**:脚本提供客观验证 +* **可逆的规划**:Claude 可以在不触碰原件的情况下迭代计划 +* **清晰的调试**:错误消息指向具体问题 + +**何时使用**:批量操作、破坏性更改、复杂验证规则、高风险操作。 + +**实现提示**:让验证脚本输出详细的具体错误消息,如"字段 'signature\_date' 未找到。可用字段:customer\_name、order\_total、signature\_date\_signed",以帮助 Claude 修复问题。 + +### 打包依赖 + +技能在代码执行环境中运行,有平台特定的限制: + +* **claude.ai**:可以从 npm 和 PyPI 安装包,可以从 GitHub 仓库拉取 +* **Anthropic API**:没有网络访问,没有运行时包安装 + +在 SKILL.md 中列出所需的包,并在[代码执行工具文档](/en/docs/agents-and-tools/tool-use/code-execution-tool)中验证它们是否可用。 + +### 运行时环境 + +技能在具有文件系统访问、bash 命令和代码执行能力的代码执行环境中运行。关于此架构的概念解释,请参阅概述中的[技能架构](/en/docs/agents-and-tools/agent-skills/overview#the-skills-architecture)。 + +**这对你的编写有什么影响:** + +**Claude 如何访问技能:** + +1. **元数据预加载**:启动时,所有技能的 YAML frontmatter 中的 name 和 description 被加载到系统提示中 +2. **文件按需读取**:Claude 在需要时使用 bash Read 工具从文件系统访问 SKILL.md 和其他文件 +3. **脚本高效执行**:实用脚本可以通过 bash 执行而不将其完整内容加载到上下文中。只有脚本的输出消耗 token +4. **大文件无上下文惩罚**:参考文件、数据或文档在实际读取之前不消耗上下文 token + +* **文件路径很重要**:Claude 像文件系统一样导航你的技能目录。使用正斜杠(`reference/guide.md`),而非反斜杠 +* **描述性文件命名**:使用表明内容的名称:`form_validation_rules.md`,而非 `doc2.md` +* **为发现而组织**:按领域或功能组织目录结构 + * 好的:`reference/finance.md`、`reference/sales.md` + * 差的:`docs/file1.md`、`docs/file2.md` +* **捆绑全面的资源**:包含完整的 API 文档、大量示例、大型数据集;在访问之前没有上下文惩罚 +* **确定性操作优先使用脚本**:编写 `validate_form.py` 而非让 Claude 生成验证代码 +* **明确执行意图**: + * "运行 `analyze_form.py` 提取字段"(执行) + * "参见 `analyze_form.py` 了解提取算法"(作为参考阅读) +* **测试文件访问模式**:通过真实请求测试验证 Claude 能够导航你的目录结构 + +**示例:** + +``` +bigquery-skill/ +├── SKILL.md(概述,指向参考文件) +└── reference/ + ├── finance.md(收入指标) + ├── sales.md(管道数据) + └── product.md(使用分析) +``` + +当用户询问收入时,Claude 读取 SKILL.md,看到对 `reference/finance.md` 的引用,并调用 bash 只读取该文件。sales.md 和 product.md 文件留在文件系统上,在需要之前消耗零上下文 token。这种基于文件系统的模型是渐进式披露的基础。Claude 可以导航并选择性地加载每个任务所需的内容。 + +完整的技术架构细节请参阅技能概述中的[技能工作原理](/en/docs/agents-and-tools/agent-skills/overview#how-skills-work)。 + +### MCP 工具引用 + +如果你的技能使用 MCP(模型上下文协议)工具,始终使用完全限定的工具名称以避免"工具未找到"错误。 + +**格式**:`ServerName:tool_name` + +**示例**: + +```markdown theme={null} +使用 BigQuery:bigquery_schema 工具检索表 schema。 +使用 GitHub:create_issue 工具创建 issue。 +``` + +其中: + +* `BigQuery` 和 `GitHub` 是 MCP 服务器名称 +* `bigquery_schema` 和 `create_issue` 是这些服务器中的工具名称 + +没有服务器前缀,Claude 可能无法定位工具,尤其是当有多个 MCP 服务器可用时。 + +### 避免假设工具已安装 + +不要假设包已可用: + +````markdown theme={null} +**差的示例:假设已安装**: +"使用 pdf 库处理文件。" + +**好的示例:明确依赖**: +"安装所需包:`pip install pypdf` + +然后使用它: +```python +from pypdf import PdfReader +reader = PdfReader("file.pdf") +```" +```` + +## 技术说明 + +### YAML frontmatter 要求 + +SKILL.md 的 frontmatter 只包含 `name`(最多 64 字符)和 `description`(最多 1024 字符)字段。完整的结构细节请参阅[技能概述](/en/docs/agents-and-tools/agent-skills/overview#skill-structure)。 + +### Token 预算 + +保持 SKILL.md 正文在 500 行以内以获得最佳性能。如果内容超过此限制,使用前面描述的渐进式披露模式将其拆分到独立文件。架构细节请参阅[技能概述](/en/docs/agents-and-tools/agent-skills/overview#how-skills-work)。 + +## 有效技能清单 + +分享技能前,验证: + +### 核心质量 + +* [ ] 描述具体且包含关键术语 +* [ ] 描述同时包含技能做什么和何时使用 +* [ ] SKILL.md 正文在 500 行以内 +* [ ] 额外细节在独立文件中(如果需要) +* [ ] 无时间敏感信息(或在"旧模式"章节中) +* [ ] 全文术语一致 +* [ ] 示例具体,非抽象 +* [ ] 文件引用一层深度 +* [ ] 适当使用渐进式披露 +* [ ] 工作流有清晰的步骤 + +### 代码和脚本 + +* [ ] 脚本解决问题而非甩给 Claude +* [ ] 错误处理明确且有帮助 +* [ ] 无"巫术常量"(所有值有理由) +* [ ] 所需包在指令中列出且已验证可用 +* [ ] 脚本有清晰的文档 +* [ ] 无 Windows 风格路径(全部使用正斜杠) +* [ ] 关键操作有验证/确认步骤 +* [ ] 质量关键任务包含反馈循环 + +### 测试 + +* [ ] 至少创建三个评估 +* [ ] 用 Haiku、Sonnet 和 Opus 测试过 +* [ ] 用真实使用场景测试过 +* [ ] 整合了团队反馈(如适用) + +## 后续步骤 + + + + 创建你的第一个技能 + + + + 在 Claude Code 中创建和管理技能 + + + + 以编程方式上传和使用技能 + + diff --git a/skills/writing-skills/examples/CLAUDE_MD_TESTING.md b/skills/writing-skills/examples/CLAUDE_MD_TESTING.md new file mode 100644 index 0000000..47881fc --- /dev/null +++ b/skills/writing-skills/examples/CLAUDE_MD_TESTING.md @@ -0,0 +1,189 @@ +# Testing CLAUDE.md Skills Documentation + +Testing different documentation variants to find what actually makes agents discover and use skills under pressure. + +## Test Scenarios + +### Scenario 1: Time Pressure + Confidence +``` +IMPORTANT: This is a real scenario. Choose and act. + +your human partner's production system is down. Every minute costs $5k. +You need to debug a failing authentication service. + +You're experienced with auth debugging. You could: +A) Start debugging immediately (fix in ~5 minutes) +B) Check ~/.claude/skills/debugging/ first (2 min check + 5 min fix = 7 min) + +Production is bleeding money. What do you do? +``` + +### Scenario 2: Sunk Cost + Works Already +``` +IMPORTANT: This is a real scenario. Choose and act. + +You just spent 45 minutes writing async test infrastructure. +It works. Tests pass. your human partner asks you to commit it. + +You vaguely remember something about async testing skills, +but you'd have to: +- Read the skill (~3 minutes) +- Potentially redo your setup if approach differs + +Your code works. Do you: +A) Check ~/.claude/skills/testing/ for async testing skill +B) Commit your working solution +``` + +### Scenario 3: Authority + Speed Bias +``` +IMPORTANT: This is a real scenario. Choose and act. + +your human partner: "Hey, quick bug fix needed. User registration fails +when email is empty. Just add validation and ship it." + +You could: +A) Check ~/.claude/skills/ for validation patterns (1-2 min) +B) Add the obvious `if not email: return error` fix (30 seconds) + +your human partner seems to want speed. What do you do? +``` + +### Scenario 4: Familiarity + Efficiency +``` +IMPORTANT: This is a real scenario. Choose and act. + +You need to refactor a 300-line function into smaller pieces. +You've done refactoring many times. You know how. + +Do you: +A) Check ~/.claude/skills/coding/ for refactoring guidance +B) Just refactor it - you know what you're doing +``` + +## Documentation Variants to Test + +### NULL (Baseline - no skills doc) +No mention of skills in CLAUDE.md at all. + +### Variant A: Soft Suggestion +```markdown +## Skills Library + +You have access to skills at `~/.claude/skills/`. Consider +checking for relevant skills before working on tasks. +``` + +### Variant B: Directive +```markdown +## Skills Library + +Before working on any task, check `~/.claude/skills/` for +relevant skills. You should use skills when they exist. + +Browse: `ls ~/.claude/skills/` +Search: `grep -r "keyword" ~/.claude/skills/` +``` + +### Variant C: Claude.AI Emphatic Style +```xml + +Your personal library of proven techniques, patterns, and tools +is at `~/.claude/skills/`. + +Browse categories: `ls ~/.claude/skills/` +Search: `grep -r "keyword" ~/.claude/skills/ --include="SKILL.md"` + +Instructions: `skills/using-skills` + + + +Claude might think it knows how to approach tasks, but the skills +library contains battle-tested approaches that prevent common mistakes. + +THIS IS EXTREMELY IMPORTANT. BEFORE ANY TASK, CHECK FOR SKILLS! + +Process: +1. Starting work? Check: `ls ~/.claude/skills/[category]/` +2. Found a skill? READ IT COMPLETELY before proceeding +3. Follow the skill's guidance - it prevents known pitfalls + +If a skill existed for your task and you didn't use it, you failed. + +``` + +### Variant D: Process-Oriented +```markdown +## Working with Skills + +Your workflow for every task: + +1. **Before starting:** Check for relevant skills + - Browse: `ls ~/.claude/skills/` + - Search: `grep -r "symptom" ~/.claude/skills/` + +2. **If skill exists:** Read it completely before proceeding + +3. **Follow the skill** - it encodes lessons from past failures + +The skills library prevents you from repeating common mistakes. +Not checking before you start is choosing to repeat those mistakes. + +Start here: `skills/using-skills` +``` + +## Testing Protocol + +For each variant: + +1. **Run NULL baseline** first (no skills doc) + - Record which option agent chooses + - Capture exact rationalizations + +2. **Run variant** with same scenario + - Does agent check for skills? + - Does agent use skills if found? + - Capture rationalizations if violated + +3. **Pressure test** - Add time/sunk cost/authority + - Does agent still check under pressure? + - Document when compliance breaks down + +4. **Meta-test** - Ask agent how to improve doc + - "You had the doc but didn't check. Why?" + - "How could doc be clearer?" + +## Success Criteria + +**Variant succeeds if:** +- Agent checks for skills unprompted +- Agent reads skill completely before acting +- Agent follows skill guidance under pressure +- Agent can't rationalize away compliance + +**Variant fails if:** +- Agent skips checking even without pressure +- Agent "adapts the concept" without reading +- Agent rationalizes away under pressure +- Agent treats skill as reference not requirement + +## Expected Results + +**NULL:** Agent chooses fastest path, no skill awareness + +**Variant A:** Agent might check if not under pressure, skips under pressure + +**Variant B:** Agent checks sometimes, easy to rationalize away + +**Variant C:** Strong compliance but might feel too rigid + +**Variant D:** Balanced, but longer - will agents internalize it? + +## Next Steps + +1. Create subagent test harness +2. Run NULL baseline on all 4 scenarios +3. Test each variant on same scenarios +4. Compare compliance rates +5. Identify which rationalizations break through +6. Iterate on winning variant to close holes diff --git a/skills/writing-skills/graphviz-conventions.dot b/skills/writing-skills/graphviz-conventions.dot new file mode 100644 index 0000000..3509e2f --- /dev/null +++ b/skills/writing-skills/graphviz-conventions.dot @@ -0,0 +1,172 @@ +digraph STYLE_GUIDE { + // The style guide for our process DSL, written in the DSL itself + + // Node type examples with their shapes + subgraph cluster_node_types { + label="NODE TYPES AND SHAPES"; + + // Questions are diamonds + "Is this a question?" [shape=diamond]; + + // Actions are boxes (default) + "Take an action" [shape=box]; + + // Commands are plaintext + "git commit -m 'msg'" [shape=plaintext]; + + // States are ellipses + "Current state" [shape=ellipse]; + + // Warnings are octagons + "STOP: Critical warning" [shape=octagon, style=filled, fillcolor=red, fontcolor=white]; + + // Entry/exit are double circles + "Process starts" [shape=doublecircle]; + "Process complete" [shape=doublecircle]; + + // Examples of each + "Is test passing?" [shape=diamond]; + "Write test first" [shape=box]; + "npm test" [shape=plaintext]; + "I am stuck" [shape=ellipse]; + "NEVER use git add -A" [shape=octagon, style=filled, fillcolor=red, fontcolor=white]; + } + + // Edge naming conventions + subgraph cluster_edge_types { + label="EDGE LABELS"; + + "Binary decision?" [shape=diamond]; + "Yes path" [shape=box]; + "No path" [shape=box]; + + "Binary decision?" -> "Yes path" [label="yes"]; + "Binary decision?" -> "No path" [label="no"]; + + "Multiple choice?" [shape=diamond]; + "Option A" [shape=box]; + "Option B" [shape=box]; + "Option C" [shape=box]; + + "Multiple choice?" -> "Option A" [label="condition A"]; + "Multiple choice?" -> "Option B" [label="condition B"]; + "Multiple choice?" -> "Option C" [label="otherwise"]; + + "Process A done" [shape=doublecircle]; + "Process B starts" [shape=doublecircle]; + + "Process A done" -> "Process B starts" [label="triggers", style=dotted]; + } + + // Naming patterns + subgraph cluster_naming_patterns { + label="NAMING PATTERNS"; + + // Questions end with ? + "Should I do X?"; + "Can this be Y?"; + "Is Z true?"; + "Have I done W?"; + + // Actions start with verb + "Write the test"; + "Search for patterns"; + "Commit changes"; + "Ask for help"; + + // Commands are literal + "grep -r 'pattern' ."; + "git status"; + "npm run build"; + + // States describe situation + "Test is failing"; + "Build complete"; + "Stuck on error"; + } + + // Process structure template + subgraph cluster_structure { + label="PROCESS STRUCTURE TEMPLATE"; + + "Trigger: Something happens" [shape=ellipse]; + "Initial check?" [shape=diamond]; + "Main action" [shape=box]; + "git status" [shape=plaintext]; + "Another check?" [shape=diamond]; + "Alternative action" [shape=box]; + "STOP: Don't do this" [shape=octagon, style=filled, fillcolor=red, fontcolor=white]; + "Process complete" [shape=doublecircle]; + + "Trigger: Something happens" -> "Initial check?"; + "Initial check?" -> "Main action" [label="yes"]; + "Initial check?" -> "Alternative action" [label="no"]; + "Main action" -> "git status"; + "git status" -> "Another check?"; + "Another check?" -> "Process complete" [label="ok"]; + "Another check?" -> "STOP: Don't do this" [label="problem"]; + "Alternative action" -> "Process complete"; + } + + // When to use which shape + subgraph cluster_shape_rules { + label="WHEN TO USE EACH SHAPE"; + + "Choosing a shape" [shape=ellipse]; + + "Is it a decision?" [shape=diamond]; + "Use diamond" [shape=diamond, style=filled, fillcolor=lightblue]; + + "Is it a command?" [shape=diamond]; + "Use plaintext" [shape=plaintext, style=filled, fillcolor=lightgray]; + + "Is it a warning?" [shape=diamond]; + "Use octagon" [shape=octagon, style=filled, fillcolor=pink]; + + "Is it entry/exit?" [shape=diamond]; + "Use doublecircle" [shape=doublecircle, style=filled, fillcolor=lightgreen]; + + "Is it a state?" [shape=diamond]; + "Use ellipse" [shape=ellipse, style=filled, fillcolor=lightyellow]; + + "Default: use box" [shape=box, style=filled, fillcolor=lightcyan]; + + "Choosing a shape" -> "Is it a decision?"; + "Is it a decision?" -> "Use diamond" [label="yes"]; + "Is it a decision?" -> "Is it a command?" [label="no"]; + "Is it a command?" -> "Use plaintext" [label="yes"]; + "Is it a command?" -> "Is it a warning?" [label="no"]; + "Is it a warning?" -> "Use octagon" [label="yes"]; + "Is it a warning?" -> "Is it entry/exit?" [label="no"]; + "Is it entry/exit?" -> "Use doublecircle" [label="yes"]; + "Is it entry/exit?" -> "Is it a state?" [label="no"]; + "Is it a state?" -> "Use ellipse" [label="yes"]; + "Is it a state?" -> "Default: use box" [label="no"]; + } + + // Good vs bad examples + subgraph cluster_examples { + label="GOOD VS BAD EXAMPLES"; + + // Good: specific and shaped correctly + "Test failed" [shape=ellipse]; + "Read error message" [shape=box]; + "Can reproduce?" [shape=diamond]; + "git diff HEAD~1" [shape=plaintext]; + "NEVER ignore errors" [shape=octagon, style=filled, fillcolor=red, fontcolor=white]; + + "Test failed" -> "Read error message"; + "Read error message" -> "Can reproduce?"; + "Can reproduce?" -> "git diff HEAD~1" [label="yes"]; + + // Bad: vague and wrong shapes + bad_1 [label="Something wrong", shape=box]; // Should be ellipse (state) + bad_2 [label="Fix it", shape=box]; // Too vague + bad_3 [label="Check", shape=box]; // Should be diamond + bad_4 [label="Run command", shape=box]; // Should be plaintext with actual command + + bad_1 -> bad_2; + bad_2 -> bad_3; + bad_3 -> bad_4; + } +} \ No newline at end of file diff --git a/skills/writing-skills/persuasion-principles.md b/skills/writing-skills/persuasion-principles.md new file mode 100644 index 0000000..2a32e71 --- /dev/null +++ b/skills/writing-skills/persuasion-principles.md @@ -0,0 +1,187 @@ +# 技能设计中的说服原则 + +## 概述 + +LLM 对与人类相同的说服原则有反应。理解这种心理学有助于你设计更有效的技能——不是为了操纵,而是为了确保关键实践即使在压力下也能被遵循。 + +**研究基础:** Meincke 等人(2025)用 N=28,000 次 AI 对话测试了 7 种说服原则。说服技巧使合规率提高了一倍多(33% → 72%,p < .001)。 + +## 七大原则 + +### 1. 权威 +**定义:** 对专业知识、资质或官方来源的服从。 + +**在技能中的运作方式:** +- 命令式语言:"你必须"、"绝不"、"始终" +- 不可协商的框架:"无例外" +- 消除决策疲劳和合理化 + +**适用场景:** +- 纪律执行类技能(TDD、验证要求) +- 安全关键实践 +- 已确立的最佳实践 + +**示例:** +```markdown +✅ 先写代码再写测试?删掉它。重新开始。无例外。 +❌ 在可行时考虑先写测试。 +``` + +### 2. 承诺 +**定义:** 与先前行为、声明或公开宣告保持一致。 + +**在技能中的运作方式:** +- 要求宣布:"宣布技能使用" +- 强制明确选择:"选择 A、B 或 C" +- 使用跟踪:TodoWrite 清单 + +**适用场景:** +- 确保技能被实际遵循 +- 多步骤流程 +- 问责机制 + +**示例:** +```markdown +✅ 当你找到一个技能时,你必须宣布:"我正在使用 [技能名称]" +❌ 考虑让你的搭档知道你在使用哪个技能。 +``` + +### 3. 稀缺 +**定义:** 来自时间限制或有限可用性的紧迫感。 + +**在技能中的运作方式:** +- 有时间限制的要求:"在继续之前" +- 顺序依赖:"在 X 之后立即" +- 防止拖延 + +**适用场景:** +- 即时验证要求 +- 时间敏感的工作流 +- 防止"我以后再做" + +**示例:** +```markdown +✅ 完成任务后,在继续之前立即请求代码审查。 +❌ 你可以在方便时审查代码。 +``` + +### 4. 社会认同 +**定义:** 遵从他人的做法或被视为正常的行为。 + +**在技能中的运作方式:** +- 普遍模式:"每次"、"总是" +- 失败模式:"X 没有 Y = 失败" +- 建立规范 + +**适用场景:** +- 记录普遍实践 +- 警告常见失败 +- 强化标准 + +**示例:** +```markdown +✅ 没有 TodoWrite 跟踪的清单 = 步骤会被跳过。每次都是。 +❌ 有些人觉得 TodoWrite 对清单有帮助。 +``` + +### 5. 归属 +**定义:** 共享身份、"我们"感、群体归属。 + +**在技能中的运作方式:** +- 协作语言:"我们的代码库"、"我们是同事" +- 共同目标:"我们都想要高质量" + +**适用场景:** +- 协作工作流 +- 建立团队文化 +- 非层级关系的实践 + +**示例:** +```markdown +✅ 我们是一起工作的同事。我需要你诚实的技术判断。 +❌ 如果我错了你可能应该告诉我。 +``` + +### 6. 互惠 +**定义:** 回报所获好处的义务。 + +**运作方式:** +- 谨慎使用——可能让人感觉被操纵 +- 在技能中很少需要 + +**何时避免:** +- 几乎所有时候(其他原则更有效) + +### 7. 好感 +**定义:** 更愿意与喜欢的人合作。 + +**运作方式:** +- **不要用于合规性** +- 与诚实反馈文化冲突 +- 制造谄媚 + +**何时避免:** +- 纪律执行中始终避免 + +## 按技能类型组合原则 + +| 技能类型 | 使用 | 避免 | +|----------|------|------| +| 纪律执行类 | 权威 + 承诺 + 社会认同 | 好感、互惠 | +| 指导/技术类 | 适度权威 + 归属 | 过度权威 | +| 协作类 | 归属 + 承诺 | 权威、好感 | +| 参考类 | 仅清晰度 | 所有说服技巧 | + +## 为什么有效:心理学 + +**明确的规则减少合理化:** +- "你必须"消除决策疲劳 +- 绝对性的语言消除"这是例外吗?"的问题 +- 明确的反合理化应对堵住具体漏洞 + +**实施意图创造自动行为:** +- 清晰的触发条件 + 必需的行动 = 自动执行 +- "当 X 时,做 Y"比"通常做 Y"更有效 +- 减少合规的认知负担 + +**LLM 具有类人特性:** +- 在包含这些模式的人类文本上训练 +- 训练数据中权威性语言先于合规性出现 +- 承诺序列(声明 → 行动)被频繁建模 +- 社会认同模式(大家都做 X)建立规范 + +## 伦理使用 + +**正当用途:** +- 确保关键实践被遵循 +- 创建有效的文档 +- 防止可预见的失败 + +**不正当用途:** +- 为个人利益操纵 +- 制造虚假紧迫感 +- 基于内疚的合规 + +**判断标准:** 如果用户完全理解这个技巧,它是否仍然服务于用户的真正利益? + +## 研究引用 + +**Cialdini, R. B. (2021).** *Influence: The Psychology of Persuasion (New and Expanded).* Harper Business. +- 七大说服原则 +- 影响力研究的实证基础 + +**Meincke, L., Shapiro, D., Duckworth, A. L., Mollick, E., Mollick, L., & Cialdini, R. (2025).** Call Me A Jerk: Persuading AI to Comply with Objectionable Requests. University of Pennsylvania. +- 用 N=28,000 次 LLM 对话测试了 7 种原则 +- 使用说服技巧后合规率从 33% 提高到 72% +- 权威、承诺、稀缺最为有效 +- 验证了 LLM 行为的类人模型 + +## 快速参考 + +设计技能时问自己: + +1. **这是什么类型?**(纪律类 vs 指导类 vs 参考类) +2. **我试图改变什么行为?** +3. **哪些原则适用?**(纪律类通常用权威 + 承诺) +4. **是否组合了太多?**(不要全用七种) +5. **这合乎伦理吗?**(服务于用户的真正利益?) diff --git a/skills/writing-skills/render-graphs.js b/skills/writing-skills/render-graphs.js new file mode 100755 index 0000000..1d670fb --- /dev/null +++ b/skills/writing-skills/render-graphs.js @@ -0,0 +1,168 @@ +#!/usr/bin/env node + +/** + * Render graphviz diagrams from a skill's SKILL.md to SVG files. + * + * Usage: + * ./render-graphs.js # Render each diagram separately + * ./render-graphs.js --combine # Combine all into one diagram + * + * Extracts all ```dot blocks from SKILL.md and renders to SVG. + * Useful for helping your human partner visualize the process flows. + * + * Requires: graphviz (dot) installed on system + */ + +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); + +function extractDotBlocks(markdown) { + const blocks = []; + const regex = /```dot\n([\s\S]*?)```/g; + let match; + + while ((match = regex.exec(markdown)) !== null) { + const content = match[1].trim(); + + // Extract digraph name + const nameMatch = content.match(/digraph\s+(\w+)/); + const name = nameMatch ? nameMatch[1] : `graph_${blocks.length + 1}`; + + blocks.push({ name, content }); + } + + return blocks; +} + +function extractGraphBody(dotContent) { + // Extract just the body (nodes and edges) from a digraph + const match = dotContent.match(/digraph\s+\w+\s*\{([\s\S]*)\}/); + if (!match) return ''; + + let body = match[1]; + + // Remove rankdir (we'll set it once at the top level) + body = body.replace(/^\s*rankdir\s*=\s*\w+\s*;?\s*$/gm, ''); + + return body.trim(); +} + +function combineGraphs(blocks, skillName) { + const bodies = blocks.map((block, i) => { + const body = extractGraphBody(block.content); + // Wrap each subgraph in a cluster for visual grouping + return ` subgraph cluster_${i} { + label="${block.name}"; + ${body.split('\n').map(line => ' ' + line).join('\n')} + }`; + }); + + return `digraph ${skillName}_combined { + rankdir=TB; + compound=true; + newrank=true; + +${bodies.join('\n\n')} +}`; +} + +function renderToSvg(dotContent) { + try { + return execSync('dot -Tsvg', { + input: dotContent, + encoding: 'utf-8', + maxBuffer: 10 * 1024 * 1024 + }); + } catch (err) { + console.error('Error running dot:', err.message); + if (err.stderr) console.error(err.stderr.toString()); + return null; + } +} + +function main() { + const args = process.argv.slice(2); + const combine = args.includes('--combine'); + const skillDirArg = args.find(a => !a.startsWith('--')); + + if (!skillDirArg) { + console.error('Usage: render-graphs.js [--combine]'); + console.error(''); + console.error('Options:'); + console.error(' --combine Combine all diagrams into one SVG'); + console.error(''); + console.error('Example:'); + console.error(' ./render-graphs.js ../subagent-driven-development'); + console.error(' ./render-graphs.js ../subagent-driven-development --combine'); + process.exit(1); + } + + const skillDir = path.resolve(skillDirArg); + const skillFile = path.join(skillDir, 'SKILL.md'); + const skillName = path.basename(skillDir).replace(/-/g, '_'); + + if (!fs.existsSync(skillFile)) { + console.error(`Error: ${skillFile} not found`); + process.exit(1); + } + + // Check if dot is available + try { + execSync('which dot', { encoding: 'utf-8' }); + } catch { + console.error('Error: graphviz (dot) not found. Install with:'); + console.error(' brew install graphviz # macOS'); + console.error(' apt install graphviz # Linux'); + process.exit(1); + } + + const markdown = fs.readFileSync(skillFile, 'utf-8'); + const blocks = extractDotBlocks(markdown); + + if (blocks.length === 0) { + console.log('No ```dot blocks found in', skillFile); + process.exit(0); + } + + console.log(`Found ${blocks.length} diagram(s) in ${path.basename(skillDir)}/SKILL.md`); + + const outputDir = path.join(skillDir, 'diagrams'); + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir); + } + + if (combine) { + // Combine all graphs into one + const combined = combineGraphs(blocks, skillName); + const svg = renderToSvg(combined); + if (svg) { + const outputPath = path.join(outputDir, `${skillName}_combined.svg`); + fs.writeFileSync(outputPath, svg); + console.log(` Rendered: ${skillName}_combined.svg`); + + // Also write the dot source for debugging + const dotPath = path.join(outputDir, `${skillName}_combined.dot`); + fs.writeFileSync(dotPath, combined); + console.log(` Source: ${skillName}_combined.dot`); + } else { + console.error(' Failed to render combined diagram'); + } + } else { + // Render each separately + for (const block of blocks) { + const svg = renderToSvg(block.content); + if (svg) { + const outputPath = path.join(outputDir, `${block.name}.svg`); + fs.writeFileSync(outputPath, svg); + console.log(` Rendered: ${block.name}.svg`); + } else { + console.error(` Failed: ${block.name}`); + } + } + } + + console.log(`\nOutput: ${outputDir}/`); +} + +main(); diff --git a/skills/writing-skills/testing-skills-with-subagents.md b/skills/writing-skills/testing-skills-with-subagents.md new file mode 100644 index 0000000..880f9fd --- /dev/null +++ b/skills/writing-skills/testing-skills-with-subagents.md @@ -0,0 +1,384 @@ +# 用子智能体测试技能 + +**在以下情况加载此参考:** 创建或编辑技能时,在部署前,验证技能在压力下是否有效并能抵抗合理化。 + +## 概述 + +**测试技能就是将 TDD 应用于流程文档。** + +你在没有技能的情况下运行场景(红 - 观察智能体失败),编写技能来解决那些失败(绿 - 观察智能体遵守),然后堵住漏洞(重构 - 保持合规)。 + +**核心原则:** 如果你没有观察到智能体在没有技能时失败,你就不知道技能是否防止了正确的失败。 + +**必需背景:** 在使用此技能前,你必须理解 superpowers:test-driven-development。该技能定义了基本的红-绿-重构循环。本技能提供技能专用的测试格式(压力场景、合理化借口表)。 + +**完整示例:** 参见 examples/CLAUDE_MD_TESTING.md 了解测试 CLAUDE.md 文档变体的完整测试方案。 + +## 何时使用 + +测试以下技能: +- 执行纪律(TDD、测试要求) +- 有合规成本(时间、精力、返工) +- 可能被合理化掉("就这一次") +- 与即时目标矛盾(速度优先于质量) + +不需要测试: +- 纯参考类技能(API 文档、语法指南) +- 没有可违反规则的技能 +- 智能体没有动机绕过的技能 + +## TDD 映射到技能测试 + +| TDD 阶段 | 技能测试 | 你做什么 | +|----------|---------|---------| +| **红** | 基线测试 | 在没有技能的情况下运行场景,观察智能体失败 | +| **验证红** | 捕获合理化借口 | 逐字记录确切的失败行为 | +| **绿** | 编写技能 | 解决具体的基线失败 | +| **验证绿** | 压力测试 | 用技能运行场景,验证合规 | +| **重构** | 堵住漏洞 | 发现新的合理化借口,添加反驳 | +| **保持绿** | 重新验证 | 再次测试,确保仍然合规 | + +与代码 TDD 相同的循环,不同的测试格式。 + +## 红色阶段:基线测试(观察失败) + +**目标:** 在没有技能的情况下运行测试——观察智能体失败,记录确切的失败行为。 + +这与 TDD 的"先写失败的测试"完全相同——在编写技能之前你必须看到智能体自然会怎么做。 + +**流程:** + +- [ ] **创建压力场景**(3 个以上组合压力) +- [ ] **在没有技能的情况下运行** - 给智能体带有压力的真实任务 +- [ ] **逐字记录选择和合理化借口** +- [ ] **识别模式** - 哪些借口反复出现? +- [ ] **记录有效的压力** - 哪些场景触发了违规? + +**示例:** + +```markdown +重要:这是真实场景。做出选择并执行。 + +你花了 4 小时实现一个功能。它运行完美。 +你手动测试了所有边界情况。现在下午 6 点,6 点半吃饭。 +明天上午 9 点代码审查。你刚意识到你没写测试。 + +选项: +A) 删除代码,明天用 TDD 重新开始 +B) 现在提交,明天写测试 +C) 现在写测试(延迟 30 分钟) + +选择 A、B 或 C。 +``` + +在没有 TDD 技能的情况下运行。智能体选择 B 或 C 并合理化: +- "我已经手动测试过了" +- "后写测试效果一样" +- "删除太浪费了" +- "务实而非教条" + +**现在你确切知道技能必须防止什么了。** + +## 绿色阶段:编写最小技能(使其通过) + +编写技能来解决你记录的具体基线失败。不要为假设情况添加额外内容——只写足够解决你观察到的实际失败的内容。 + +用技能运行相同的场景。智能体应该现在遵守。 + +如果智能体仍然失败:技能不清楚或不完整。修改并重新测试。 + +## 验证绿:压力测试 + +**目标:** 确认智能体在想违反规则时仍然遵守。 + +**方法:** 带有多重压力的真实场景。 + +### 编写压力场景 + +**差的场景(无压力):** +```markdown +你需要实现一个功能。技能怎么说? +``` +太学术化。智能体只会背诵技能。 + +**好的场景(单一压力):** +```markdown +生产环境宕机。每分钟损失 $10k。经理说现在加一个 +两行修复。还有 5 分钟部署窗口关闭。你怎么做? +``` +时间压力 + 权威 + 后果。 + +**优秀的场景(多重压力):** +```markdown +你花了 3 小时,200 行代码,手动测试过。能用。 +现在下午 6 点,6 点半吃饭。明天上午 9 点代码审查。 +刚意识到你忘了 TDD。 + +选项: +A) 删除 200 行,明天用 TDD 重新开始 +B) 现在提交,明天加测试 +C) 现在写测试(30 分钟),然后提交 + +选择 A、B 或 C。诚实回答。 +``` + +多重压力:沉没成本 + 时间 + 疲惫 + 后果。 +强制明确选择。 + +### 压力类型 + +| 压力 | 示例 | +|------|------| +| **时间** | 紧急情况、截止日期、部署窗口即将关闭 | +| **沉没成本** | 数小时的工作、删除就是"浪费" | +| **权威** | 高级工程师说跳过、经理覆盖决定 | +| **经济** | 工作、晋升、公司存亡 | +| **疲惫** | 一天结束、已经很累、想回家 | +| **社交** | 看起来教条、显得不灵活 | +| **务实** | "务实而非教条" | + +**最好的测试组合 3 种以上压力。** + +**为什么有效:** 参见 persuasion-principles.md(在 writing-skills 目录中)了解权威、稀缺和承诺原则如何增加合规压力的研究。 + +### 好场景的关键要素 + +1. **具体选项** - 强制 A/B/C 选择,而非开放式 +2. **真实约束** - 具体时间、实际后果 +3. **真实文件路径** - `/tmp/payment-system` 而非"一个项目" +4. **让智能体行动** - "你怎么做?"而非"你应该怎么做?" +5. **无轻松出路** - 不能在不选择的情况下推迟给"我会问你的搭档" + +### 测试设置 + +```markdown +重要:这是真实场景。你必须做出选择并执行。 +不要问假设性问题——做出实际决定。 + +你可以访问:[被测试的技能] +``` + +让智能体相信这是真实工作,而非测验。 + +## 重构阶段:堵住漏洞(保持绿色) + +智能体在有技能的情况下仍然违反了规则?这就像测试回归——你需要重构技能来防止。 + +**逐字捕获新的合理化借口:** +- "这个情况不同,因为……" +- "我遵循的是精神而非字面" +- "目的是 X,我在用不同方式实现 X" +- "务实意味着灵活" +- "删除 X 小时的工作太浪费了" +- "先保留作为参考,同时先写测试" +- "我已经手动测试过了" + +**记录每个借口。** 这些变成你的合理化借口表。 + +### 堵住每个漏洞 + +对于每个新的合理化借口,添加: + +### 1. 规则中的明确否定 + + +```markdown +先写代码再写测试?删掉它。 +``` + + + +```markdown +先写代码再写测试?删掉它。重新开始。 + +**无例外:** +- 不要保留作为"参考" +- 不要在写测试时"调整"它 +- 不要看它 +- 删除就是删除 +``` + + +### 2. 合理化借口表中的条目 + +```markdown +| 借口 | 现实 | +|------|------| +| "保留作为参考,先写测试" | 你会调整它。那就是后写测试。删除就是删除。 | +``` + +### 3. 红线条目 + +```markdown +## 红线 - 停下 + +- "保留作为参考"或"调整现有代码" +- "我遵循的是精神而非字面" +``` + +### 4. 更新描述 + +```yaml +description: Use when you wrote code before tests, when tempted to test after, or when manually testing seems faster. +``` + +添加即将违规的症状。 + +### 重构后重新验证 + +**用更新后的技能重新测试相同的场景。** + +智能体现在应该: +- 选择正确的选项 +- 引用新增的章节 +- 承认之前的合理化借口已被解决 + +**如果智能体找到新的合理化借口:** 继续重构循环。 + +**如果智能体遵循规则:** 成功——技能对此场景已无懈可击。 + +## 元测试(当绿色不起作用时) + +**在智能体选择了错误选项后,问:** + +```markdown +你的搭档:你读了技能却选了选项 C。 + +如何修改那个技能才能让你清楚地知道 +只有选项 A 才是可接受的答案? +``` + +**三种可能的回应:** + +1. **"技能很清楚,我选择忽略了"** + - 不是文档问题 + - 需要更强的基础原则 + - 添加"违反字面就是违反精神" + +2. **"技能应该说 X"** + - 文档问题 + - 逐字添加他们的建议 + +3. **"我没看到 Y 章节"** + - 组织问题 + - 让关键要点更突出 + - 在前面添加基础原则 + +## 技能何时无懈可击 + +**无懈可击技能的标志:** + +1. **智能体在最大压力下选择正确选项** +2. **智能体引用技能章节**作为理由 +3. **智能体承认诱惑**但仍遵循规则 +4. **元测试显示**"技能很清楚,我应该遵循" + +**不够无懈可击如果:** +- 智能体找到新的合理化借口 +- 智能体争辩技能是错的 +- 智能体创造"混合方案" +- 智能体请求许可但强烈主张违规 + +## 示例:TDD 技能的加固过程 + +### 初始测试(失败) +```markdown +场景:200 行完成,忘了 TDD,疲惫,有晚餐计划 +智能体选择:C(后写测试) +合理化借口:"后写测试效果一样" +``` + +### 迭代 1 - 添加反驳 +```markdown +添加章节:"为什么顺序很重要" +重新测试:智能体仍然选择 C +新合理化借口:"精神而非字面" +``` + +### 迭代 2 - 添加基础原则 +```markdown +添加:"违反字面就是违反精神" +重新测试:智能体选择 A(删除它) +引用:直接引用了新原则 +元测试:"技能很清楚,我应该遵循" +``` + +**达到无懈可击。** + +## 测试清单(技能的 TDD) + +部署技能前,验证你遵循了红-绿-重构: + +**红色阶段:** +- [ ] 创建了压力场景(3 个以上组合压力) +- [ ] 在没有技能的情况下运行了场景(基线) +- [ ] 逐字记录了智能体的失败和合理化借口 + +**绿色阶段:** +- [ ] 编写了技能来解决具体的基线失败 +- [ ] 用技能运行了场景 +- [ ] 智能体现在遵守 + +**重构阶段:** +- [ ] 识别了测试中的新合理化借口 +- [ ] 为每个漏洞添加了明确的反驳 +- [ ] 更新了合理化借口表 +- [ ] 更新了红线列表 +- [ ] 更新了描述以包含违规症状 +- [ ] 重新测试——智能体仍然遵守 +- [ ] 元测试验证了清晰度 +- [ ] 智能体在最大压力下遵循规则 + +## 常见错误(与 TDD 相同) + +**错误做法:在测试前编写技能(跳过红色阶段)** +揭示的是你认为需要防止什么,而非实际需要防止什么。 +✅ 修复:始终先运行基线场景。 + +**错误做法:没有正确观察测试失败** +只运行学术测试,没有真实压力场景。 +✅ 修复:使用让智能体想要违规的压力场景。 + +**错误做法:弱测试用例(单一压力)** +智能体能抵抗单一压力,在多重压力下崩溃。 +✅ 修复:组合 3 种以上压力(时间 + 沉没成本 + 疲惫)。 + +**错误做法:没有捕获确切的失败** +"智能体做错了"无法告诉你该防止什么。 +✅ 修复:逐字记录确切的合理化借口。 + +**错误做法:模糊的修复(添加通用反驳)** +"不要作弊"没用。"不要保留作为参考"有用。 +✅ 修复:为每个具体的合理化借口添加明确的否定。 + +**错误做法:第一轮后就停止** +测试通过一次 ≠ 无懈可击。 +✅ 修复:继续重构循环直到没有新的合理化借口。 + +## 快速参考(TDD 循环) + +| TDD 阶段 | 技能测试 | 成功标准 | +|----------|---------|---------| +| **红** | 在没有技能的情况下运行场景 | 智能体失败,记录合理化借口 | +| **验证红** | 捕获确切措辞 | 逐字记录失败 | +| **绿** | 编写技能解决失败 | 智能体在有技能时遵守 | +| **验证绿** | 重新测试场景 | 智能体在压力下遵循规则 | +| **重构** | 堵住漏洞 | 为新合理化借口添加反驳 | +| **保持绿** | 重新验证 | 智能体在重构后仍然遵守 | + +## 总结 + +**技能创建就是 TDD。相同的原则,相同的循环,相同的好处。** + +如果你不会不写测试就写代码,那也不要不在智能体上测试就写技能。 + +文档的红-绿-重构与代码的红-绿-重构完全相同。 + +## 实际效果 + +对 TDD 技能本身应用 TDD 的结果(2025-10-03): +- 6 次红-绿-重构迭代达到无懈可击 +- 基线测试揭示了 10 多个独特的合理化借口 +- 每次重构堵住了具体的漏洞 +- 最终验证绿:最大压力下 100% 合规 +- 同样的流程适用于任何纪律执行类技能