
1. 从技能货架说起Codex 的 skill 机制到底解决了什么问题第一次接触 Codex 的 skill 体系时我脑子里冒出来的画面是超市货架——上面摆满了各种包装好的能力模块每个模块都贴着一张 SKILL.md 的说明书你拿下来就能用不用自己从零调教。这个比喻其实挺贴切的因为 skill 的本质就是把某类任务该怎么干这件事从散落在对话历史里的临时指令固化成一个可复用、可版本管理、可分享的独立单元。在没有 skill 之前我用 Codex 处理重复性任务的体验是这样的每次开新会话都得把同一套背景、同一套约束、同一套输出格式重新贴一遍。今天让它帮我写 Playwright 测试用例我得解释项目用的是什么框架、断言风格是什么、要不要用 Page Object 模式明天再写又得从头来一遍。这种重复劳动不仅烦更要命的是每次表述的细微差异会导致输出质量飘忽不定——有时候它给你生成一堆page.waitForTimeout有时候又老老实实用expect(locator).toBeVisible()。skill 机制把这个问题从根上切掉了。一个写好的 skill本质上是一份结构化的任务契约它告诉 Codex 这类任务的目标是什么、有哪些约束、按什么步骤走、输出成什么形态。你把它挂上去之后每次触发相关任务Codex 都会按这份契约来执行稳定性直接上了一个台阶。1.1 SKILL.md 不是普通的说明文档很多人第一次看到 SKILL.md会下意识把它当成 README 来写——堆一堆背景介绍、功能列表、注意事项。这是个典型的误区。SKILL.md 的核心读者不是人是模型。它的写法要服务于让模型准确理解并执行任务而不是让人快速了解这个项目。我自己的经验是一份好用的 SKILL.md 通常包含这么几块触发条件什么情况下该用这个 skill、输入约定用户会提供什么、格式是什么、执行步骤分几步、每步做什么、有什么判断分支、输出规范格式、粒度、要不要带解释、边界与禁忌什么不能做、什么情况要停下来问。这五块里最容易被忽略但最重要的是最后一块。模型天然倾向于把事做完如果你不明确告诉它边界在哪它就会自作主张地补全你没要求的东西。举个具体的例子。我写过一个专门生成 Playwright 测试用例的 skill早期版本没写边界结果 Codex 经常在生成的测试文件里顺手加上test.only或者自作聪明地 mock 掉一些网络请求。后来我在 SKILL.md 里加了一段明确的禁忌清单禁止使用test.only、禁止在未明确要求时 mock 网络、禁止使用固定waitForTimeout超过 500ms。加上之后输出立刻规矩了。1.2 为什么货架上大部分 skill 你其实用不上Codex 的 skill 生态现在挺热闹社区里各种 skill 层出不穷从代码审查到文档生成从数据分析到自动化测试看着琳琅满目。但我翻了一圈之后的真实感受是大部分 skill 解决的是别人的问题不是你的问题。这话听起来像废话但背后有个很实际的判断逻辑。一个 skill 值不值得留下取决于三个条件是否同时成立你高频做这类任务、这类任务的输出有明确的稳定性要求、这类任务的上下文足够复杂以至于每次重新描述成本很高。三个条件缺一个这个 skill 对你来说就是货架上的装饰品。拿代码格式化这类 skill 来说它满足高频但输出稳定性要求其实用工具链prettier、eslint就能保证上下文也不复杂所以 skill 的价值很低。反过来生成一套完整的 Playwright 端到端测试这种任务高频、输出质量波动大、上下文涉及项目结构和技术栈约定skill 的价值就非常高。我最后留在自己货架上的 skill 不多但每一个都是经过实际项目反复验证的。下面几节我会把筛选逻辑、留下的几个 skill 的具体设计、以及踩过的坑都摊开讲。2. 筛选标准我用什么尺子量一个 skill 的去留翻货架这件事最怕的是看着都好用起来都鸡肋。我一开始也犯过贪多的毛病装了一堆 skill结果真正调用的就那么两三个剩下的不仅占地方还会在触发时互相干扰——比如两个 skill 都对写测试这个意图有响应Codex 有时候会挑错那个输出就偏了。2.1 触发精度比功能丰富度更重要一个 skill 好不好第一看它的触发是否精准。所谓触发精准是指该用的时候一定用上不该用的时候绝不乱入。这背后其实是 SKILL.md 里触发条件描述的质量问题。我见过不少 skill 的触发条件写得极其宽泛比如当用户需要处理代码时使用。这种描述等于没描述因为几乎所有编程对话都符合。结果就是它会在各种不相关的场景里被激活然后输出一堆你不需要的东西。好的触发条件应该是窄而明确的。比如我那个 Playwright skill 的触发条件写的是当用户明确要求为某个页面或流程生成端到端测试且项目已配置 Playwright 时使用。这里明确要求端到端测试已配置 Playwright三个限定词把范围收得很紧误触发率极低。提示判断触发条件写得好不好有个简单的自测方法——把这段描述单独拿出来问自己有没有哪类明显不该用这个 skill 的任务也符合这段描述如果有就得继续收窄。2.2 输出稳定性是 skill 的命根子skill 存在的最大理由就是稳定。如果一个 skill 每次输出都风格迥异、质量参差那它还不如不用——至少不用的时候你还能靠详细 prompt 临时控制。输出稳定性来自哪里来自 SKILL.md 里对输出形态的强约束。我总结下来约束要落到三个层面结构层面输出分几部分、每部分是什么、风格层面用什么语气、要不要解释、解释到什么程度、细节层面命名规范、注释密度、错误处理方式。以测试用例生成为例我在 skill 里明确规定每个测试文件必须以test.describe分组、每个用例名用应该预期行为的中文描述、断言必须用 web-first assertion如toBeVisible而非手动等待、每个用例末尾不加多余注释。这些约束一旦写死输出就变得可预期了我甚至可以直接把生成的文件丢进 CI 而不用逐行 review。2.3 维护成本被低估的隐性支出skill 不是写完就完事的。项目技术栈会变、团队约定会变、Codex 本身的能力也在迭代skill 需要跟着维护。一个需要频繁维护的 skill实际成本可能比它节省的还高。所以我在筛选时会额外考虑一点这个 skill 依赖的外部约定多不多如果一个 skill 深度绑定了某个特定版本的库、某套特定的目录结构、某个特定的团队规范那它的维护成本就会很高。相反那些只依赖通用编程概念、不绑定具体实现的 skill生命周期会长得多。我最后留下的 skill基本都是轻绑定的——它们依赖的是任务本身的逻辑比如生成测试要先分析页面结构再写断言而不是某个具体工具的 API 细节。这样即使项目换了测试框架skill 的主体逻辑依然成立只需要微调少量细节。3. 我留下的几个 skill逐个拆解设计思路说了这么多筛选逻辑该上干货了。下面这几个是我实际留在货架上、并且在真实项目里反复用过的 skill。我会把每个 skill 解决什么问题、SKILL.md 的关键设计、以及实际使用中的注意事项都讲清楚。3.1 create-plan把想清楚这件事前置create-plan这个 skill 是我用得最频繁的一个它的作用是在动手写代码之前先让 Codex 产出一份结构化的执行计划。听起来简单但它解决的是一个非常普遍的痛点模型倾向于直接给答案而不是先想清楚再给答案。没有这个 skill 的时候我让 Codex 做一个稍复杂的任务它经常上来就写代码写到一半发现方向不对又回头改来回折腾。有了create-plan之后流程变成先触发它生成计划我 review 计划、调整方向确认无误后再让它按计划执行。这个先计划后执行的两段式流程把返工率降了一大截。SKILL.md 里我重点约束了计划的粒度。太粗的计划比如第一步分析需求第二步实现功能没有指导意义太细的计划又等于把代码写了一遍。我定的标准是每个步骤应该是一个可以在 5 到 15 分钟内完成的独立动作且步骤之间有明确的依赖关系。同时要求计划里必须标注每步的验证方式——做完这步怎么知道它对了。注意create-plan生成的计划不要无脑接受。我踩过的坑是模型有时会把计划排得很理想化忽略了实际项目里的历史包袱。所以 review 计划这一步不能省尤其是涉及改动现有代码的任务。3.2 Playwright 测试生成从页面结构到可运行用例这个 skill 是我花时间最多的一个也是收益最明显的。它的完整流程是接收一个页面 URL 或组件描述先分析页面结构有哪些交互元素、有哪些状态变化然后生成一套覆盖主要路径的端到端测试。设计这个 skill 时我特意把分析和生成拆成了两个阶段。第一阶段让 Codex 输出一份页面结构分析包括主要元素、交互流程、边界情况第二阶段才基于这份分析生成测试代码。为什么要拆因为如果直接让它生成代码它往往会漏掉一些边界情况而先做分析能强迫它把页面想全。生成阶段的约束我写得很细。断言必须用 Playwright 的 web-first assertion禁止用waitForTimeout做同步选择器优先用getByRole和getByLabel这类语义化定位实在不行才用># Skill 名称 ## 触发条件 什么情况下使用要窄而明确 ## 输入约定 用户会提供什么格式要求 ## 执行步骤 分步骤描述每步的目标和验证方式 ## 输出规范 结构、风格、细节约束用强语气 ## 边界与禁忌 不能做什么什么情况要停下来确认 ## 示例 一到两个输入输出示例帮助模型对齐这个骨架里边界与禁忌和示例是最容易被省略但最有价值的两块。禁忌清单能防止模型自作主张示例能让模型快速对齐输出风格。5.3 测试 skill 的三个维度skill 写完之后怎么测我从三个维度测触发测试给它各种相关和不相关的输入看触发是否精准、稳定性测试同一个输入跑五次看输出是否一致、边界测试给它一些刁钻的输入看它是否按禁忌清单处理。稳定性测试特别重要。我的标准是同一个输入跑五次核心结构必须完全一致细节可以有微小差异。如果结构都不一致说明 SKILL.md 的约束还不够硬得回去改。5.4 迭代节奏小步快跑skill 不要一次写完就完事要小步迭代。我的做法是先用一个最小可用版本跑一周记录每次使用中不满意的地方一周后集中改一次。这样迭代出来的 skill比一次性憋大招写出来的更贴合实际需求。6. 关于 skill 生态的一些个人观察最后聊点偏感想的东西但都是我在实际使用中观察到的不是空话。skill 这个机制最妙的地方是它把提示词工程从一次性的技巧变成了可积累的资产。以前你调好一个 prompt用完就散了现在你把它固化成 skill它就一直在那儿还能分享给别人、还能版本管理。这个转变的意义我觉得比 skill 本身的功能更重要。但我也观察到一些不太健康的现象。比如有人把 skill 当成炫技的工具写一堆花哨但实际用不上的 skill还有人把 skill 写成了万能模板试图用一个 skill 解决所有问题。这些做法最后都会反噬——货架上堆满用不上的东西真正需要的时候反而找不到。我自己的原则很简单货架上只留真正高频使用、且输出稳定性有要求的 skill。其他的要么删掉要么等真的需要了再写。货架清爽了找东西才快用起来才顺。另外skill 之间是可以组合的。比如我经常先用create-plan生成计划再用 Playwright skill 按计划生成测试。这种组合用法比单个 skill 更强大但也要求每个 skill 的输入输出格式设计得足够规范能对接得上。这一点在设计 skill 时就要考虑到——你的 skill 输出能不能作为另一个 skill 的输入如果能整个货架的价值就翻倍了。关于 Codex 的 skill 机制我目前还在持续摸索。有些想法还没验证成熟比如 skill 的自动化测试、skill 之间的依赖管理这些等我有更确定的结论了再分享。但有一点我现在就很确定skill 的价值不在于多而在于精。翻完整个货架留下几个真正趁手的比装满一整个货架却不知道用哪个要强得多。