# Writing Skills

> 用于创建新技能、编辑现有技能，或在部署前验证技能是否有效

- Skill: `vinvcn/writing-skills` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds@latest add vinvcn/writing-skills`
- Raw SKILL.md: https://api.skillmd.com/api/skills/vinvcn/writing-skills/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: vinvcn (https://skillmd.com/u/vinvcn)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/vinvcn/writing-skills

---


# 编写技能

## 概述

**编写技能就是把测试驱动开发应用到流程文档。**

**个人技能位于特定代理的目录中（Claude Code 使用 `~/.claude/skills`，Codex 使用 `~/.agents/skills/`）**

你编写测试用例（带子代理的压力场景），观察它们失败（基线行为），编写技能（文档），观察测试通过（代理遵守），然后重构（堵住漏洞）。

**核心原则：** 如果你没有观察过代理在没有技能时失败，就不知道这个技能是否教对了东西。

**REQUIRED BACKGROUND:** 使用此技能前，你必须理解 superpowers:test-driven-development。该技能定义了基础的 RED-GREEN-REFACTOR 循环。本技能把 TDD 适配到文档。

**官方指南：** Anthropic 官方技能编写最佳实践见 anthropic-best-practices.md。本文档提供额外模式和指南，用来补充本技能中以 TDD 为中心的方法。

## 什么是技能？

**技能**是经过验证的技巧、模式或工具的参考指南。技能帮助未来的 Claude 实例找到并应用有效方法。

**技能是：** 可复用的技巧、模式、工具、参考指南

**技能不是：** 关于你某次如何解决问题的叙事

## 技能的 TDD 映射

| TDD 概念 | 技能创建 |
|-------------|----------------|
| **测试用例** | 带子代理的压力场景 |
| **生产代码** | 技能文档（SKILL.md） |
| **测试失败（RED）** | 没有技能时代理违反规则（基线） |
| **测试通过（GREEN）** | 存在技能时代理遵守规则 |
| **重构** | 在保持遵守的同时堵住漏洞 |
| **先写测试** | 编写技能之前运行基线场景 |
| **观察失败** | 记录代理使用的确切合理化借口 |
| **最小代码** | 编写只处理这些具体违规的技能 |
| **观察通过** | 验证代理现在会遵守 |
| **重构循环** | 找到新的合理化借口 → 堵住 → 重新验证 |

整个技能创建过程都遵循 RED-GREEN-REFACTOR。

## 何时创建技能

**在以下情况创建：**
- 技巧对你来说不是直觉上显而易见的
- 你会在多个项目中再次引用它
- 模式适用范围广（不是项目特定）
- 其他人也会受益

**不要为以下内容创建：**
- 一次性解决方案
- 其他地方已有充分文档的标准实践
- 项目特定约定（放进 CLAUDE.md）
- 机械性约束（如果能用 regex/validation 强制执行，就自动化；把文档留给需要判断的场景）

## 技能类型

### 技巧
带有可执行步骤的具体方法（condition-based-waiting、root-cause-tracing）

### 模式
思考问题的方式（flatten-with-flags、test-invariants）

### 参考
API 文档、语法指南、工具文档（office 文档）

## 目录结构


```
skills/
  skill-name/
    SKILL.md              # Main reference (required)
    supporting-file.*     # Only if needed
```

**扁平命名空间** - 所有技能位于一个可搜索命名空间中

**以下内容单独成文件：**
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 [specific triggering conditions and symptoms]
---

# Skill Name

## 概述
What is this? Core principle in 1-2 sentences.

## When to Use
[Small inline flowchart IF decision non-obvious]

Bullet list with SYMPTOMS and use cases
When NOT to use

## Core Pattern (for techniques/patterns)
Before/after code comparison

## Quick Reference
Table or bullets for scanning common operations

## Implementation
Inline code for simple patterns
Link to file for heavy reference or reusable tools

## Common Mistakes
What goes wrong + fixes

## Real-World Impact (optional)
Concrete results
```


## Claude 搜索优化（CSO）

**对发现至关重要：** 未来的 Claude 需要找到你的技能

### 1. 丰富的 Description 字段

**目的：** Claude 读取 description 来决定为给定任务加载哪些技能。让它回答：“我现在应该读取这个技能吗？”

**格式：** 以 "Use when..." 开头，聚焦触发条件

**关键：Description = 何时使用，而不是技能做什么**

description 应该只描述触发条件。不要在 description 中概括技能的过程或工作流。

**为什么这很重要：** 测试发现，当 description 概括技能工作流时，Claude 可能会遵循 description，而不是读取完整技能内容。一个写着 "code review between tasks" 的 description 导致 Claude 只做了一次评审，尽管技能流程图清楚显示需要两次评审（先检查规范符合性，再检查代码质量）。

当 description 改成仅写 "Use when executing implementation plans with independent tasks"（没有工作流摘要）后，Claude 正确读取了流程图，并遵循两阶段评审流程。

**陷阱：** 概括工作流的 description 会创建 Claude 会采用的捷径。技能正文会变成 Claude 跳过的文档。

```yaml
# ❌ BAD: Summarizes workflow - Claude may follow this instead of reading skill
description: Use when executing plans - dispatches subagent per task with code review between tasks

# ❌ BAD: Too much process detail
description: Use for TDD - write test first, watch it fail, write minimal code, refactor

# ✅ GOOD: Just triggering conditions, no workflow summary
description: Use when executing implementation plans with independent tasks in the current session

# ✅ GOOD: Triggering conditions only
description: Use when implementing any feature or bugfix, before writing implementation code
```

**内容：**
- 使用具体触发器、症状和情境来表明此技能适用
- 描述*问题*（race conditions、inconsistent behavior），而不是*语言特定症状*（setTimeout、sleep）
- 除非技能本身是技术特定的，否则保持触发条件技术无关
- 如果技能是技术特定的，要在触发条件中明确说明
- 使用第三人称（会注入系统提示）
- **绝不要概括技能的过程或工作流**

```yaml
# ❌ BAD: Too abstract, vague, doesn't include when to use
description: For async testing

# ❌ BAD: First person
description: I can help you with async tests when they're flaky

# ❌ BAD: Mentions technology but skill isn't specific to it
description: Use when tests use setTimeout/sleep and are flaky

# ✅ GOOD: Starts with "Use when", describes problem, no workflow
description: Use when tests have race conditions, timing dependencies, or pass/fail inconsistently

# ✅ GOOD: Technology-specific skill with explicit trigger
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
# ❌ BAD: Document all flags in SKILL.md
search-conversations supports --text, --both, --after DATE, --before DATE, --limit N

# ✅ GOOD: Reference --help
search-conversations supports multiple modes and filters. Run --help for details.
```

**使用交叉引用：**
```markdown
# ❌ BAD: Repeat workflow details
When searching, dispatch subagent with template...
[20 lines of repeated instructions]

# ✅ GOOD: Reference other skill
Always use subagents (50-100x context savings). REQUIRED: Use [other-skill-name] for workflow.
```

**压缩示例：**
```markdown
# ❌ BAD: Verbose example (42 words)
your human partner: "How did we handle authentication errors in React Router before?"
You: I'll search past conversations for React Router authentication patterns.
[Dispatch subagent with search query: "React Router authentication error handling 401"]

# ✅ GOOD: Minimal example (20 words)
Partner: "How did we handle auth errors in React Router?"
You: Searching...
[Dispatch subagent → synthesis]
```

**消除冗余：**
- 不要重复交叉引用技能中的内容
- 不要解释命令本身显而易见的内容
- 不要为同一模式包含多个示例

**验证：**
```bash
wc -w skills/path/SKILL.md
# getting-started workflows: aim for <150 each
# Other frequently-loaded: aim for <200 total
```

**按你做什么或核心洞察命名：**
- ✅ `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. 交叉引用其他技能

**编写引用其他技能的文档时：**

只使用技能名称，并加上明确的要求标记：
- ✅ 好：`**REQUIRED SUB-SKILL:** Use superpowers:test-driven-development`
- ✅ 好：`**REQUIRED BACKGROUND:** You MUST understand superpowers:systematic-debugging`
- ❌ 差：`See skills/testing/test-driven-development`（不清楚是否必需）
- ❌ 差：`@skills/testing/test-driven-development/SKILL.md`（强制加载，消耗上下文）

**为什么不要 @ 链接：** `@` 语法会立即强制加载文件，在你真正需要之前就消耗 200k+ 上下文。

## 流程图用法

```dot
digraph when_flowchart {
    "Need to show information?" [shape=diamond];
    "Decision where I might go wrong?" [shape=diamond];
    "Use markdown" [shape=box];
    "Small inline flowchart" [shape=box];

    "Need to show information?" -> "Decision where I might go wrong?" [label="yes"];
    "Decision where I might go wrong?" -> "Small inline flowchart" [label="yes"];
    "Decision where I might go wrong?" -> "Use markdown" [label="no"];
}
```

**只在以下情况使用流程图：**
- 不明显的决策点
- 你可能过早停止的流程循环
- “何时使用 A vs B”的决策

**绝不要为以下内容使用流程图：**
- 参考资料 → 表格、列表
- 代码示例 → Markdown 代码块
- 线性说明 → 编号列表
- 没有语义意义的标签（step1、helper2）

graphviz 样式规则见 @graphviz-conventions.dot。

**为你的人类伙伴可视化：** 使用本目录中的 `render-graphs.js` 将技能流程图渲染为 SVG：
```bash
./render-graphs.js ../some-skill           # Each diagram separately
./render-graphs.js ../some-skill --combine # All diagrams in one SVG
```

## 代码示例

**一个优秀示例胜过许多平庸示例**

选择最相关的语言：
- 测试技巧 → TypeScript/JavaScript
- 系统调试 → Shell/Python
- 数据处理 → Python

**好示例：**
- 完整且可运行
- 注释良好，解释原因
- 来自真实场景
- 清楚展示模式
- 可直接改造（不是通用模板）

**不要：**
- 用 5+ 种语言实现
- 创建填空式模板
- 编写牵强示例

你擅长移植，一个优秀示例就足够。

## 文件组织

### 自包含技能
```
defense-in-depth/
  SKILL.md    # Everything inline
```
何时使用：所有内容都能放下，不需要大型参考资料

### 带可复用工具的技能
```
condition-based-waiting/
  SKILL.md    # Overview + patterns
  example.ts  # Working helpers to adapt
```
何时使用：工具是可复用代码，而不仅是叙事

### 带大型参考资料的技能
```
pptx/
  SKILL.md       # Overview + workflows
  pptxgenjs.md   # 600 lines API reference
  ooxml.md       # 500 lines XML structure
  scripts/       # Executable tools
```
何时使用：参考资料太大，不适合内联

## 铁律（与 TDD 相同）

```
NO SKILL WITHOUT A FAILING TEST FIRST
```

这同时适用于新技能和对现有技能的编辑。

测试前先写技能？删除它，重新开始。
未测试就编辑技能？同样违规。

**没有例外：**
- “简单添加”也不例外
- “只是添加一个小节”也不例外
- “文档更新”也不例外
- 不要把未经测试的改动保留作“参考”
- 不要在运行测试时“改造”它
- 删除就是删除

**REQUIRED BACKGROUND:** superpowers:test-driven-development 技能解释了为什么这很重要。同样原则适用于文档。

## 测试所有技能类型

不同技能类型需要不同测试方法：

### 强制纪律型技能（规则/要求）

**示例：** TDD、verification-before-completion、designing-before-coding

**测试方式：**
- 学术问题：它们是否理解规则？
- 压力场景：它们是否在压力下遵守？
- 多重压力组合：时间 + 沉没成本 + 疲惫
- 识别合理化借口并添加明确反制

**成功标准：** 代理在最大压力下遵循规则

### 技巧型技能（操作指南）

**示例：** condition-based-waiting、root-cause-tracing、defensive-programming

**测试方式：**
- 应用场景：它们能否正确应用技巧？
- 变化场景：它们能否处理边界情况？
- 缺失信息测试：说明是否存在缺口？

**成功标准：** 代理能把技巧成功应用到新场景

### 模式型技能（思维模型）

**示例：** reducing-complexity、information-hiding 概念

**测试方式：**
- 识别场景：它们能否识别模式何时适用？
- 应用场景：它们能否使用该心智模型？
- 反例：它们是否知道何时不该应用？

**成功标准：** 代理能正确识别何时以及如何应用模式

### 参考型技能（文档/APIs）

**示例：** API 文档、命令参考、库指南

**测试方式：**
- 检索场景：它们能否找到正确信息？
- 应用场景：它们能否正确使用找到的信息？
- 缺口测试：是否覆盖常见用例？

**成功标准：** 代理能找到并正确应用参考信息

## 跳过测试的常见合理化借口

| 借口 | 现实 |
|--------|---------|
| “技能显然很清楚” | 对你清楚 ≠ 对其他代理清楚。测试它。 |
| “它只是参考资料” | 参考资料可能有缺口或不清楚的小节。测试检索。 |
| “测试太过了” | 未测试技能一定有问题。15 分钟测试能节省数小时。 |
| “如果出现问题我再测试” | 出问题 = 代理不能使用技能。部署前测试。 |
| “测试太繁琐” | 测试比调试生产中的坏技能更不繁琐。 |
| “我确信它很好” | 过度自信必然带来问题。无论如何都要测试。 |
| “学术评审就够了” | 阅读 ≠ 使用。测试应用场景。 |
| “没时间测试” | 部署未测试技能会浪费更多后续修复时间。 |

**所有这些都意味着：部署前测试。没有例外。**

## 让技能抵抗合理化借口

强制纪律的技能（如 TDD）需要抵抗合理化借口。代理很聪明，在压力下会找到漏洞。

**心理学说明：** 理解说服技巧为什么有效，有助于系统性应用它们。关于权威、承诺、稀缺、社会认同和一致性原则的研究基础（Cialdini, 2021；Meincke et al., 2025），见 persuasion-principles.md。

### 明确堵住每个漏洞

不要只陈述规则，还要禁止具体绕路方式：

<Bad>
```markdown
Write code before test? Delete it.
```
</Bad>

<Good>
```markdown
Write code before test? Delete it. Start over.

**No exceptions:**
- Don't keep it as "reference"
- Don't "adapt" it while writing tests
- Don't look at it
- Delete means delete
```
</Good>

### 处理“精神 vs 字面”论点

尽早加入基础原则：

```markdown
**Violating the letter of the rules is violating the spirit of the rules.**
```

这会切断整类“我遵循的是精神”的合理化借口。

### 建立合理化借口表

从基线测试中捕获合理化借口（见下方测试小节）。代理提出的每个借口都放进表格：

```markdown
| Excuse | Reality |
|--------|---------|
| "Too simple to test" | Simple code breaks. Test takes 30 seconds. |
| "I'll test after" | Tests passing immediately prove nothing. |
| "Tests after achieve same goals" | Tests-after = "what does this do?" Tests-first = "what should this do?" |
```

### 创建危险信号列表

让代理在合理化时容易自检：

```markdown
## Red Flags - STOP and Start Over

- Code before test
- "I already manually tested it"
- "Tests after achieve the same purpose"
- "It's about spirit not ritual"
- "This is different because..."

**所有这些都意味着：删除代码。用 TDD 重新开始。**
```

### 针对违规症状更新 CSO

添加到 description：你即将违反规则时的症状：

```yaml
description: use when implementing any feature or bugfix, before writing implementation code
```

## 技能的 RED-GREEN-REFACTOR

遵循 TDD 循环：

### RED：编写失败测试（基线）

在没有技能的情况下，用子代理运行压力场景。记录确切行为：
- 它们做了哪些选择？
- 它们使用了哪些合理化借口（逐字记录）？
- 哪些压力触发了违规？

这就是“观察测试失败” - 编写技能前，你必须看到代理自然会做什么。

### GREEN：编写最小技能

编写处理这些具体合理化借口的技能。不要为假设情况添加额外内容。

在有技能的情况下运行相同场景。代理现在应该遵守。

### REFACTOR：堵住漏洞

代理找到了新的合理化借口？添加明确反制。重新测试，直到牢固。

**测试方法：** 完整测试方法见 @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
**为什么不好：** 标签应该有语义意义

## STOP：进入下一个技能前

**写完任何技能后，你必须停下并完成部署流程。**

**不要：**
- 不逐个测试就批量创建多个技能
- 当前技能验证前就进入下一个技能
- 因为“批处理更高效”而跳过测试

**下面的部署清单对每个技能都是强制性的。**

部署未测试技能 = 部署未测试代码。这违反质量标准。

## 技能创建清单（TDD 改编版）

**重要：使用 TodoWrite 为下面每个清单项创建 todo。**

**RED 阶段 - 编写失败测试：**
- [ ] 创建压力场景（纪律型技能需要 3+ 种组合压力）
- [ ] 在没有技能的情况下运行场景 - 逐字记录基线行为
- [ ] 识别合理化借口/失败中的模式

**GREEN 阶段 - 编写最小技能：**
- [ ] 名称只使用字母、数字、连字符（不要括号/特殊字符）
- [ ] YAML frontmatter 包含必需的 `name` 和 `description` 字段（最多 1024 字符；见 [spec](https://agentskills.io/specification)）
- [ ] Description 以 "Use when..." 开头，并包含具体触发器/症状
- [ ] Description 使用第三人称编写
- [ ] 全文包含用于搜索的关键词（错误、症状、工具）
- [ ] 有清晰概述和核心原则
- [ ] 处理 RED 中识别的具体基线失败
- [ ] 代码内联或链接到单独文件
- [ ] 一个优秀示例（不是多语言）
- [ ] 在有技能的情况下运行场景 - 验证代理现在会遵守

**REFACTOR 阶段 - 堵住漏洞：**
- [ ] 识别测试中出现的新合理化借口
- [ ] 添加明确反制（如果是纪律型技能）
- [ ] 从所有测试迭代构建合理化借口表
- [ ] 创建危险信号列表
- [ ] 重新测试直到牢固

**质量检查：**
- [ ] 只有在决策不明显时才使用小流程图
- [ ] 快速参考表
- [ ] 常见错误小节
- [ ] 没有叙事故事
- [ ] 支持文件只用于工具或大型参考资料

**部署：**
- [ ] 将技能提交到 git 并推送到你的 fork（如果已配置）
- [ ] 考虑通过 PR 回馈（如果广泛有用）

## 发现工作流

未来的 Claude 如何找到你的技能：

1. **遇到问题**（"tests are flaky"）
3. **找到 SKILL**（description 匹配）
4. **扫描概述**（这相关吗？）
5. **读取模式**（快速参考表）
6. **加载示例**（仅在实现时）

**为这个流程优化** - 尽早并经常放入可搜索术语。

## 底线

**创建技能就是面向流程文档的 TDD。**

同一条铁律：没有先失败的测试，就没有技能。
同一个循环：RED（基线）→ GREEN（编写技能）→ REFACTOR（堵住漏洞）。
同样的收益：更高质量、更少意外、更牢固的结果。

如果你对代码遵循 TDD，就也对技能遵循它。这是同一种纪律在文档上的应用。

