
1. 从“能用”到“好用”为什么40个Skill是分水岭我大概是在去年年底开始把 Claude Code 当作日常主力工具的。刚开始那两个月我的用法特别朴素打开终端敲claude然后一句一句地跟它聊让它帮我改改脚本、写写正则、解释一段看不懂的代码。那时候我觉得这东西挺好用但也就那样——本质上还是个“更聪明的命令行问答框”。转折点出现在我一次性往~/.claude/skills/目录里塞进四十来个 Skill 之后。那天我本来只是想试试看能不能把一些重复性的操作固化下来结果配完重启我盯着终端愣了好一会儿原来我之前那些“手动喂上下文、反复纠正格式、每次都要重新解释项目规范”的操作全都可以被 Skill 接管。换句话说我之前不是在用 Claude Code我是在用一个被我自己阉割过的 Claude Code。这篇东西我想聊的就是这件事Skill 到底是什么、它和子 agent 有什么区别、SKILL.md 里的 frontmatter 怎么写、四十个 Skill 怎么组织才不乱、以及我在这个过程中踩过的那些坑。如果你现在还在“每次开新会话都要重新交代一遍背景”的阶段那这篇应该能帮你省下不少时间。不管你是刚在 Ubuntu 或者 Windows 上装好 Claude Code 的新手还是已经在 VS Code 里配好了插件的老用户Skill 这一层都值得你认真对待。先说结论免得你看到一半觉得我在绕Skill 是把“领域知识 操作流程 输出规范”打包成一个可被自动调用的模块。它不是提示词模板那么简单因为它带元数据、能被模型自己判断该不该用、还能引用外部脚本和资源文件。四十个 Skill 之所以是个分水岭是因为当数量上到一定程度你才会被迫去思考分类、命名、触发条件和优先级——而正是这套组织方式决定了你的 Claude Code 到底是“一个助手”还是“一支团队”。2. Skill 与子 agent先把概念理清楚再动手2.1 Skill 到底解决了什么问题在没有 Skill 之前我处理一个“写单元测试”的任务是这样的先告诉它我们用的是 pytest 不是 unittest再告诉它 mock 的写法偏好再告诉它断言风格再告诉它文件放哪个目录。每次新开会话这套话都得重来一遍。烦不烦烦。更烦的是有时候我漏说了一条它就会按自己的默认习惯来然后我还得回头改。Skill 的本质是把这套“每次都要交代的背景”变成一份常驻的、可被检索的说明书。你把SKILL.md放进指定目录Claude Code 在启动时会扫描这些文件读取里面的name和description然后在对话过程中根据你的请求判断这个任务要不要调用某个 Skill如果要它就把那个 Skill 的完整内容加载进上下文。这里有个关键点很多人没意识到Skill 是渐进式加载的。启动时只读元数据frontmatter不读正文。只有当模型判断需要用到某个 Skill 时才会把SKILL.md的正文读进来。这个设计非常聪明因为它意味着你就算装了一百个 Skill也不会一上来就把上下文塞爆。我实测下来四十个 Skill 的元数据加起来也就占几百个 token对上下文的影响几乎可以忽略。那它和“提示词模板”的区别在哪区别在于触发是自动的。提示词模板需要你手动粘贴或者用快捷键插入而 Skill 是模型自己决定要不要用的。你只需要正常描述任务它自己会去匹配。这个体验上的差别用过就回不去了。2.2 子 agent 和主 agent 的分工逻辑热词里有个问题被反复提到“skill 和 agent 的区别是什么”。这个问题我在配置初期也纠结过后来想明白了。主 agent 就是你直接对话的那个 Claude Code 实例它负责理解你的意图、决定调用哪些工具、组织最终回复。子 agent 则是主 agent 派生出来的“分身”用来处理那些需要独立上下文、或者需要并行处理的子任务。比如你让它“同时检查前端和后端的代码规范”它可能会派两个子 agent 分别去读两边的文件各自汇总后再由主 agent 合并结果。那 Skill 和子 agent 的关系是什么我的理解是Skill 是知识子 agent 是劳动力。Skill 告诉模型“这件事该怎么做”子 agent 负责“实际去做”。一个子 agent 在执行任务时同样可以调用 Skill。所以这两者不是替代关系而是配合关系。在 Cursor 或者 VS Code 里配置的时候这个区别会更明显。VS Code 的 Claude Code 插件里你能看到主 agent 的对话流但子 agent 的执行过程往往是折叠起来的。我一开始还以为是卡住了后来才发现是子 agent 在后台跑。理解了这层你就不会对着一个“没反应”的界面干着急了。2.3 为什么“装了很多 Skill 却感觉没用”这是我最想吐槽的一点。我见过不少人说“我装了一堆 Skill感觉没啥变化”。原因通常有三个第一description 写得太烂。模型判断要不要调用某个 Skill几乎完全依赖 frontmatter 里的description。如果你写的是“一个用于处理数据的 Skill”那模型根本不知道什么时候该用它。好的 description 应该写清楚“什么时候用”和“用来干什么”比如“当用户需要把 CSV 转换成带类型推断的 Parquet 文件时使用”。第二Skill 之间职责重叠。我一开始装了两个都跟“代码审查”相关的 Skill结果模型每次都要纠结用哪个有时候还用错了。后来我把它们合并成一个问题就没了。第三没有重启会话。Skill 是在会话启动时扫描的你新加了一个 Skill 文件当前会话是不会感知到的。这个坑我踩过不止一次改完文件发现没生效折腾半天才想起来要重开。3. SKILL.md 与 frontmatter把说明书写给模型看3.1 frontmatter 的字段到底怎么填SKILL.md的结构其实很简单顶部是一段 YAML 格式的 frontmatter用---包起来下面就是 Markdown 正文。frontmatter 里最核心的两个字段是name和description。--- name: csv-to-parquet description: 当用户需要把 CSV 文件转换为 Parquet 格式或需要做数据类型推断和压缩优化时使用。支持自定义分隔符和空值处理。 ---name我建议用短横线连接的英文小写别用中文也别用空格。虽然有些版本对中文 name 也能识别但一旦涉及到路径引用或者脚本调用中文名会带来一堆麻烦。description则是重中之重它决定了这个 Skill 能不能被正确触发。我总结了一个 description 的写法公式触发场景 核心动作 关键约束。触发场景回答“什么时候用”核心动作回答“做什么”关键约束回答“有什么限制或偏好”。三者齐全模型的判断准确率会高很多。除了这两个必填字段还有一些可选字段值得关注。比如有些实现支持allowed-tools来限制这个 Skill 能调用哪些工具这在安全敏感的场景下很有用。还有的版本支持在 frontmatter 里声明依赖的外部文件路径。这些字段的具体支持情况跟版本有关建议你装完之后先翻一下官方文档确认。3.2 正文怎么写才不浪费 tokenfrontmatter 下面的正文才是 Skill 真正干活的部分。这里有个反直觉的点正文不是越长越好。因为正文是在 Skill 被触发时才加载的它会占用上下文窗口。如果你写了两千行那加载进来之后留给实际任务的空间就少了。我的做法是把正文分成三块流程步骤、示例、注意事项。流程步骤用有序列表写清楚“第一步做什么、第二步做什么”示例给一两个输入输出的对照注意事项则把那些“容易出错但文档里不会写”的点列出来。## 执行流程 1. 读取源 CSV 文件检测分隔符和编码 2. 对每一列做类型推断优先尝试 int、float、datetime、string 3. 处理空值默认填充为 null 而非空字符串 4. 写出 Parquet 文件使用 snappy 压缩 ## 注意事项 - 如果某列既有数字又有文本一律按 string 处理不要强行转换 - 日期格式不明确时先输出前 10 行让用户确认这种写法实测下来触发准确、执行稳定。我试过把一大段自然语言描述塞进正文结果模型反而抓不住重点还不如这种结构化的写法。3.3 引用外部脚本和资源文件Skill 目录里除了SKILL.md还可以放脚本、模板、参考数据等文件。在正文里用相对路径引用它们模型在执行时就能读取或调用。这个能力让 Skill 从“说明书”升级成了“工具箱”。比如我有个处理日志的 Skill目录结构是这样的log-analyzer/ ├── SKILL.md ├── scripts/ │ └── parse.py └── templates/ └── report.md在SKILL.md里我就写“调用scripts/parse.py解析日志然后按templates/report.md的格式输出报告”。模型读到之后会自己去读这些文件并按指示操作。这个机制特别适合那些“流程固定但细节繁琐”的任务。注意外部脚本的路径一定要用相对路径相对于SKILL.md所在目录。用绝对路径的话换台机器或者换个用户就失效了。4. 四十个 Skill 的组织方式分类、命名与优先级4.1 按领域分类而不是按工具分类装到第十几个的时候我的skills目录就开始乱了。一开始我是按“用了什么工具”来分的比如“git 相关”“docker 相关”结果发现很多 Skill 横跨多个工具根本没法归类。后来我改成按领域分情况就好多了。我现在的分类大概是这几大类代码质量类审查、重构、测试、数据处理类格式转换、清洗、分析、文档写作类技术文档、注释、提交信息、项目规范类目录结构、命名约定、依赖管理、领域专用类比如数学建模、论文检索这类特定场景。分类的好处是当你要新增一个 Skill 时能快速判断它该放哪、会不会和已有的重复。而且从模型的角度看同一类的 Skill 在 description 上有天然的区分度不容易误触发。4.2 命名要让人和模型都能看懂命名这件事我吃过亏。早期我用过helper1、util、misc这种名字结果过了一个月我自己都忘了它们是干嘛的。后来我定了个规矩name 必须能自解释看到名字就知道用途。好的命名像pytest-fixture-generator、sql-explain-analyzer、commit-message-writer一眼就知道是干什么的。坏的命名像code-helper、># 创建全局 Skill 目录 mkdir -p ~/.claude/skills # 创建项目级 Skill 目录 mkdir -p .claude/skills # 每个 Skill 一个子目录 mkdir -p ~/.claude/skills/csv-to-parquet每个 Skill 一个独立子目录子目录里放SKILL.md和可选的脚本、模板。这个结构别偷懒把所有 Skill 平铺在一个目录里后期维护会很痛苦。如果你是从 GitHub 上手动装别人的 Skill流程也简单把整个 Skill 目录 clone 或者下载下来放到skills目录下就行。注意检查一下SKILL.md的 frontmatter 是否完整有些分享出来的 Skill 会缺字段。5.2 一个完整 Skill 的编写过程我拿一个实际例子走一遍。假设我要写一个“生成数据库迁移脚本”的 Skill。第一步确定触发场景。这个 Skill 应该在什么时候用当用户提到“加字段”“改表结构”“迁移”这类词的时候。所以 description 我写成“当用户需要为数据库表结构变更生成迁移脚本时使用支持添加字段、修改类型、创建索引等操作。”第二步写执行流程。我把流程拆成读取当前 schema、对比目标 schema、生成变更语句、输出回滚语句。每一步都写清楚输入输出。第三步加注意事项。比如“修改字段类型时如果表里有数据要提醒用户先备份”“创建索引时如果表很大建议用并发创建”。第四步测试。写完之后重启会话然后故意用几种不同的说法触发它看看能不能正确调用。我一般会试三种说法直接的“帮我写个迁移脚本”、间接的“我要给用户表加个字段”、以及不该触发的“解释一下什么是数据库迁移”。第三种如果被触发了说明 description 需要收紧。5.3 参数计算与选择过程有些 Skill 涉及到参数选择这时候把计算过程写进正文会很有帮助。比如我有个处理图片压缩的 Skill里面就写了不同场景下的参数选择逻辑## 压缩参数选择 - 网页缩略图质量 60最大宽度 400px - 文章配图质量 75最大宽度 1200px - 归档存储质量 85保持原始尺寸 选择逻辑先看用途再看是否需要保留细节。 质量每降低 10文件大小约减少 25% 到 35%。这种把“为什么选这个参数”写清楚的做法能让模型在遇到边界情况时做出更合理的判断而不是死板地套用。6. 常见问题与排查技巧实录6.1 Skill 不触发怎么办这是最高频的问题。排查顺序我一般是这样的先看 frontmatter 格式对不对。YAML 对缩进和符号很敏感一个中文冒号或者少个空格都可能导致解析失败。我建议用---开头和结尾字段名和值之间用英文冒号和空格。再看 description 写得够不够具体。如果 description 太泛模型可能觉得“这个 Skill 好像沾边但又不太确定”结果就不调用。这时候把触发场景写得更明确一些。然后确认会话是否重启了。新加的 Skill 不会在当前会话生效这个前面提过。最后看目录层级对不对。SKILL.md必须在skills/技能名/这个层级下不能直接放在skills/里也不能再往下多套一层。6.2 Skill 被误触发怎么办误触发通常是因为 description 覆盖范围太宽。解决办法是在 description 里加排除条件或者把 Skill 拆得更细。我有个教训早期我写了个code-review的 Skilldescription 写的是“用于代码审查”。结果每次我提到“review”这个词哪怕是在聊别的事情它都会被触发。后来我改成“当用户明确要求对某段代码进行质量审查、安全检查或风格检查时使用”误触发就少多了。6.3 多个 Skill 冲突怎么办冲突的表现是模型在两个 Skill 之间反复横跳或者选了不合适的那个。处理方式是明确边界。如果两个 Skill 确实有重叠要么合并要么在各自的 description 里写清楚“我负责 A 场景不负责 B 场景”。我现在的做法是给每个 Skill 加一句“不适用场景”虽然多写几个字但省下了大量调试时间。问题排查方向解决方式完全不触发frontmatter 格式、description 具体度、会话是否重启逐项检查重启会话偶尔触发description 边界模糊补充触发关键词和排除条件频繁误触发description 覆盖过宽收紧描述拆分 Skill多个 Skill 冲突职责重叠合并或明确划分边界加载后无效果正文结构混乱、指令不明确改用结构化写法分步骤6.4 实操心得几个文档里不会写的点第一个心得Skill 的正文里动词比名词重要。与其写“这是一个用于处理日期的工具”不如写“读取日期字符串解析为 ISO 格式输出”。模型对动作指令的响应远好于对描述的响应。第二个心得给 Skill 写一个“反例”。在正文里加一段“以下情况不要使用本 Skill”能显著降低误触发率。这个技巧我是从一个开源 Skill 里学来的实测非常有效。第三个心得定期清理。Skill 不是越多越好四十个是我的舒适区上限。超过这个数维护成本就开始超过收益了。与其装一百个半吊子 Skill不如精修四十个真正用得上的。第四个心得版本控制。把你的skills目录纳入 git 管理每次改动都提交。这样当你改坏了一个 Skill 导致行为异常时能快速回滚。我吃过没做版本控制的亏改了一个 Skill 之后行为变得很奇怪又记不清改了什么只能凭记忆一点点试。7. 从四十个 Skill 到一套工作流装到四十个之后我最大的感受是Skill 的价值不在于数量而在于它们能不能串成一条流水线。单个 Skill 解决的是“一个点”的问题而当你把代码审查、测试生成、提交信息、文档更新这几个 Skill 串起来它就变成了一条“从改代码到提交”的完整链路。我现在的工作流大概是这样改完代码先触发审查 Skill 过一遍再触发测试 Skill 补测试然后触发提交信息 Skill 生成 commit message最后触发文档 Skill 更新相关说明。整个过程我只需要在关键节点确认一下剩下的它自己跑。这套东西配下来花了我大概两个周末但省下的时间早就回本了。如果你现在还在手动喂上下文的阶段我的建议是先从三五个最常用的场景开始写几个 Skill 试试水。等你体会到“不用重复交代背景”的爽感之后自然会想装更多。最后分享一个小技巧把你最常用的那个 Skill 的 description 背下来。这样当你想触发它的时候用词会更接近它的触发条件命中率会高很多。听起来有点傻但实测有效。