前阵子有个事让我挺难受的团队想把前端组件规范落地我花了一下午写了份特别详细的开发规范塞进CLAUDE.md让 Claude Code 按这个来。结果呢你让它看一眼某个组件它确实会参考这些规则但经常看完就忘重要的检查项漏掉一半。后来我认真研究了一圈才发现问题出在我的使用姿势上——规范这种东西放在内存里靠模型自觉执行远不如做成一个 Skill 来得可靠。于是我自己动手写了一个技能包让 AI 以一套固定流程去审查前端组件。现在它每次都会老老实实按我的规矩干活包括跑脚本检查、逐项输出报告、给出可执行的修改建议。这篇就完整记录一下我是怎么从零手写这个 Skill 的包括当时为什么这么设计、踩了哪些坑、以及怎么让它在你自己的项目里同样生效。适合已经在用或正准备用 Claude Code 的开发者尤其是前端方向、想让 AI 输出更可控的朋友。1. Skill 不是多了一个 Prompt而是多了一套带工具箱的流程先说一个容易被忽略的事实Skill 和你在对话里贴一大段 prompt 是两回事。很多人以为把指令写成SKILL.md文件就等于给 AI 上了一道紧箍咒其实它的价值根本不在于多写几句要求而在于它把知识、流程、可执行脚本绑定成了一个整体。1.1 Skill 和 CLAUDE.md、Commands、Hooks 到底怎么分工我最初困惑的是这几个东西看着都像配置规则到底该用哪个后来用多了我自己的理解是这样的机制本质推荐场景CLAUDE.md全局/项目级常驻背景知识项目技术栈、目录结构、命名约定等“一直在场的规则”Commands斜杠命令手动触发的指令模板特定固定动作比如“帮我写周报”“生成组件模板”Hooks事件驱动的自动化钩子在特定事件前后强制执行校验比如提交前检查Skills描述触发的专家流程包需要多步骤执行、可附带脚本、且希望模型“意识到自己正在用某个方法论”的场景这样一看就很清楚了。CLAUDE.md像贴在工位旁边的值班表AI 每次干活都能看见但它不会因为看见值班表就突然进入“审查专家模式”。Skill 更像是你打了一个电话一个带着自己检查表和工具箱的专家上门来干活——它有一套自己的执行流程而且如果写得好它还会主动调用工具脚本去验证代码而不是纯靠模型肉眼感觉。1.2 模型是怎么决定加载哪个 Skill的这里有个值得深入理解的机制Skill 的触发方式不是用户手动敲命令那是 Commands 的事而是模型根据当前任务上下文判断哪个 Skill 的description和任务相关再决定要不要加载对应的SKILL.md来执行。这意味着description写得好不好直接决定 AI 在什么场景下唤醒这个技能。我在第一次写 Skill 的时候就吃过亏。当时我把 description 写得很宽泛比如用于代码审查。结果模型在任何一次代码相关对话里都想套用它反而导致了误触发规则互相打架。后来我把 description 改成了当用户要求对某个前端组件文件进行质量检查、可访问性评估或性能优化建议时使用触发准确性一下子好了很多。所以如果你想把这个机制用好第一课就是description 要贴着用户在什么诉求下会需要这个技能来写而不是贴着这个技能内部做了什么来写。你要站在模型的角度去理解它判断的是用户现在想要什么而不是你这个功能有多强大。1.3 一个 Skill 在文件系统里长什么样社区里比较通用也是我现在一直在用的结构是这样.claude/skills/ component-auditor/ SKILL.md scripts/ audit_component.mjsSKILL.md是这个技能的核心说明书里面写清楚这个技能是干什么的、按什么步骤执行、必须遵守哪些硬性规则。scripts/目录用来放辅助脚本因为很多审查或生成类任务光靠模型读和想是不够的得靠代码去做客观检查。比如查一个文件里有没有console.log残留模型逐个看当然也能看出来但遇到几百上千行的文件脚本才是靠谱的。这个目录放进项目仓库后Claude Code 在项目里工作时就能识别到。全局的 Skills 则放在用户级目录~/.claude/skills/下这样任何项目都能用。两者的选择逻辑我在后面团队化那部分再具体展开。2. 先判断任务适不适合做成 Skill规则、频率、验证点不是说所有任务都值得做成 Skill。我做第一个 Skill 之前先列了一堆候选生成组件模板、写提交信息、做代码审查、总结 PR、生成数据模拟文件……最后只挑了其中一个来做。这个判断过程其实比写代码本身更重要因为方向错了做出来的 Skill 就是一堆没人用的死文件。2.1 好 Skill 的三个判断标准我总结下来适合做成 Skill 的任务至少要满足三条第一规则要能写清楚。如果你的任务靠的是玄学审美比如帮我把海报做得高级一点那还是别做成 Skill 了。Skill 的本质是把方法论结构化你需要能够明确列出先做什么、再做什么、什么是对、什么是错。审查类、检查类、格式化类、脚手架生成类任务天然适合因为规则是客观的。第二最好是高频复用的任务。Skill 的维护成本其实不算低你写它的时候要设计流程用的时候要验证后续还要迭代。如果这个任务一个月碰不到一次那每次现写 prompt 反而更灵活。我之所以先做组件审查是因为我长期在改一个遗留前端项目几乎每天都要看组件代码高频到不行。第三要有可验证的结果。一个好的 Skill 执行完应该给出能检查的东西一份报告、一个文件、一组修改。如果执行完只是AI 觉得可以了你根本没法判断这个 Skill 是好是坏也没法迭代。我在设计组件审查 Skill 时明确要求最终输出一份带检查项清单和结论的报告每一项都能被快速核验。2.2 为什么我第一个 Skill 选组件质量审查当时我手上的实际情况是这样的项目是 Vue 3 TypeScript组件代码有几百个文件团队规范散落在多个文档里。AI 写新组件的时候经常出现几个问题——用的命名风格和团队不一致、模板里出现内联样式、事件处理函数没做防抖、console.log忘删、可访问性属性缺失。这些问题每一个单独看都不大但每周收 code review 意见的时候总是重复出现。我意识到这些问题本质上是可以程序化检查的客观规则完全可以用一个 Skill 把团队规范固化成检查流程。AI 看到组件文件就自动按我的清单去核对而不是凭感觉给建议。2.3 设计 Skill 前先画规则草稿动手写SKILL.md之前先在纸上把规则草稿列出来。这一步特别容易被人跳过但真不能省。因为直接写文件时你会不自觉地开始组织语言而不是确认逻辑是否完整。我当时的草稿长这样组件命名必须是 PascalCase文件名必须和组件名一致props 定义必须带类型和默认值不允许隐式 any模板中不允许出现内联 style样式必须走 scoped class不允许console.log残留在生产代码里img标签必须有alt属性单文件组件行数超过 500 行时必须给出拆分建议需要支持键盘操作的元素必须有对应的可访问性处理这些就是我脑子里规矩的外化。草稿列出来之后我再决定哪些由模型判断比较合适哪些要交给脚本去检查。比如props 是否带类型这种人眼看得快但模型也看得出来而文件是否超过 500 行这种数行数的活让脚本去干更客观。最终的判断原则是凡是能用几行代码算出结果的尽量别让模型靠感觉凡是需要语义理解的留给模型。3. 动手写 SKILL.mdfrontmatter 和正文各自的门道很多人第一次写 SKILL.md 时容易把注意力全放在正文规则上忽略了前面的 YAML frontmatter。但前面说了模型的技能唤醒机制依赖description这个字段写不好后面全白搭。3.1 frontmatter 的写法决定AI 什么时候想起你我见过不少社区里的 SKILL.mddescription写得过于功能导向比如执行前端代码审查并输出质量报告。这听起来没问题但对模型来说它缺少的是用户的什么话应该触发我。用户不会说请执行前端代码审查用户会说的是帮我看下这个组件写得怎么样、这个按钮的样式有人能 review 一下吗、这个页面为什么要用内联样式。所以我的写法是把用户可能说的自然语言放进 description 里而不是把内部功能描述一遍--- name: component-auditor description: 当用户要求检查、审查或改进某个前端组件Vue/React或者询问组件里是否存在代码质量、可访问性、性能问题时使用。包含对命名规范、props 类型、事件处理、样式写法、可访问性等维度的逐项检查。 ---这个 description 写完之后我会问自己一个问题如果一个用户刚刚说了一句话这个描述能不能帮我判断该不该触发能判断就合格不能判断就继续改。3.2 正文结构从角色设定到输出模板SKILL.md的正文本质上是一份操作手册它要让 AI 像一个入职第一天就拿到文档的工程师一样按流程把活干完。我习惯把它分成五段角色与目标告诉 AI 它现在扮演什么角色任务目标是什么。这里不用写得花哨一两句话讲清楚就行。执行步骤用有序列表给出一二三四步顺序必须严格。审查类任务我一般定义成先定位目标文件并读取再运行辅助脚本做客观检查然后按检查清单逐项核对最后汇总生成报告。硬性规则这是整个 Skill 最核心的部分。每条规则尽量写成可验证的命题比如组件文件名必须与组件名完全一致包括大小写而不是组件命名要规范。同时我会刻意使用必须/禁止/除非这类强语义词把规则的边界说清楚减少模型自由发挥的空间。输出格式规定最终结果的格式。审查类任务我强制要求按检查清单逐项输出[通过]或[问题]并附上具体的文件名、行号和修改建议。这一步非常关键因为如果你不限制输出格式AI 会每次给你不同样子的报告没法看。示例给一两个好和坏的对比示例。模型非常吃示例这一套尤其当你的规则涉及风格判断时一个具体的坏例子比十句抽象描述都管用。3.3 脚本怎么和 SKILL.md 配合而不喧宾夺主Skill 里可以带脚本但脚本应该当工具人而不是当主角。我见过有人把 SKILL.md 写得很简单基本逻辑都在脚本里实现结果模型只是在傻傻地跑脚本、贴输出。这其实浪费了模型的理解能力。我的做法是脚本只负责输出客观事实比如文件行数、是否存在某个模式、是否引用了某个不存在的变量这些是脚本的强项。而规则的解释、优先级判断、修改建议留给模型。比如脚本发现某个 props 类型定义缺失模型应该根据这个事实去解释这会导致类型不安全建议补充接口定义。这才能发挥各自优势。4. 实战给前端项目做一个组件质量守门员理论说够了直接看完整实例。下面这个 Skill 我已经在真实项目里用了一段时间就是前面说的 component-auditor。4.1 目录与文件组织在项目根目录创建如下结构.claude/skills/component-auditor/ SKILL.md scripts/ audit_component.mjs把它放在项目仓库里意味着团队所有人都能共用同一份不需要额外分发。如果想让某个 Skill 对所有项目都生效可以移动到用户级~/.claude/skills/目录下这个看个人习惯。4.2 SKILL.md 的完整示例下面是我实际在用的版本略去了一些和具体业务强相关的内容--- name: component-auditor description: 当用户要求检查、审查或改进某个前端组件Vue/React或者询问组件里是否存在代码质量、可访问性、性能问题时使用。适合处理单个组件文件不适合做跨页面的整体架构评审。 --- # 前端组件质量审查 你是一名严格的前端代码审查工程师。你的目标不是夸组件写得好而是尽可能找出它和团队规范不一致的地方。 ## 执行步骤 1. 定位用户指定的组件文件并完整读取。 2. 运行 node .claude/skills/component-auditor/scripts/audit_component.mjs 文件路径 获取客观检查结果。 3. 结合文件内容和脚本输出逐项核对下面的硬性规则。 4. 如果发现问题明确指出对应文件和行号并给出可执行的修改建议。 5. 输出完整的审查报告。 ## 硬性规则 - 组件名称必须使用 PascalCase且文件名必须与组件名完全一致。 - props 必须声明明确的类型和默认值禁止隐式 any。 - 禁止在模板中使用内联 style样式必须写在 scoped 样式中且 class 命名必须使用 kebab-case。 - 生产代码中禁止出现 console.log、debugger。 - 所有 img 标签必须有 alt 属性如果图片是装饰性用途alt 必须写成空字符串。 - 所有可点击的非 button 元素必须补充 role 和键盘事件处理。 - 事件处理函数中如果涉及高频触发scroll、resize、input必须有防抖或节流处理。 - 单文件组件超过 400 行时必须给出拆分建议。 - 模板中禁止出现 v-html除非内容来自可信的富文本编辑器。 - 以上规则中任意一条不满足都必须在报告中标记为问题不得忽略。 ## 输出格式 必须按照以下格式输出 ### 审查对象 - 文件路径 - 组件名 - 文件行数 - 脚本检查结果通过 / 发现问题 ### 检查清单 - [x] 命名规范 - [ ] props 类型与默认值 - [ ] 样式写法 - [ ] 无调试残留 - [ ] 图片可访问性 - [ ] 键盘可访问性 - [ ] 事件性能 - [ ] 文件长度与拆分建议 - [ ] 安全风险 未勾选项必须用自然语言说明问题位置和建议。 ### 修改建议 按优先级从高到低列出需要修改的内容每条包含问题描述、位置、修改方案。你注意最后那个输出格式要求它非常重要。因为 AI 在执行规则检查时如果允许它自由发挥它会倾向于把整段代码重新讲一遍而不是聚焦在问题清单上。有了强制格式它的输出就变成了一份可阅读、可转发的报告而不是一篇宽泛的这个组件总体来说写得不错。4.3 辅助脚本怎么写脚本的作用是给模型提供客观事实。我的脚本不搞复杂逻辑就做几件小事读文件、统计行数、用正则匹配一些明显问题、计算一些简单指标最后输出 JSON。#!/usr/bin/env node // .claude/skills/component-auditor/scripts/audit_component.mjs import fs from node:fs; import path from node:path; const filePath process.argv[2]; if (!filePath) { console.error(Usage: node audit_component.mjs component-file); process.exit(1); } const absPath path.resolve(filePath); const source fs.readFileSync(absPath, utf8); const lines source.split(\n); const result { file: absPath, lineCount: lines.length, issues: [], }; // 检查 console.log 和 debugger if (/console\.log\(/.test(source)) { const lineNo lines.findIndex(l /console\.log\(/.test(l)) 1; result.issues.push({ rule: no-debug-console, severity: high, line: lineNo, message: 检测到 console.log 残留 }); } if (/debugger/.test(source)) { const lineNo lines.findIndex(l /\bdebugger\b/.test(l)) 1; result.issues.push({ rule: no-debugger, severity: high, line: lineNo, message: 检测到 debugger 语句 }); } // 检查内联 style if (/style[^]*/.test(source)) { const lineNo lines.findIndex(l /style[^]*/.test(l)) 1; result.issues.push({ rule: no-inline-style, severity: medium, line: lineNo, message: 模板中使用内联 style }); } // 检查 img 是否缺少 alt const imgTagRegex /img\b(?![^]*\balt)[^]*/g; let m; while ((m imgTagRegex.exec(source)) ! null) { const lineNo lines.slice(0, source.slice(0, m.index).split(\n).length).length; result.issues.push({ rule: img-alt, severity: high, line: lineNo, message: img 标签缺少 alt 属性 }); } // 检查 v-html针对 Vue 项目用不到可以删掉这一条 if (/v-html/.test(source)) { const lineNo lines.findIndex(l /v-html/.test(l)) 1; result.issues.push({ rule: no-v-html, severity: high, line: lineNo, message: 模板中使用 v-html存在 XSS 风险 }); } console.log(JSON.stringify(result, null, 2));这段脚本没有做任何智能判断它输出的都是检测到了什么 在哪一行这种事实。模型拿到 JSON 之后再结合上下文理解问题的严重性并补充上下文里才看得出来的问题比如组件命名是否 PascalCase、props 是否缺少默认值。这种脚本查客观 模型查语义的组合是我目前用下来最稳的模式。4.4 实际跑一次的效果我拿项目里一个真实的列表组件UserList.vue测了一下。这个文件 520 行脚本反馈了 2 个客观问题第 47 行有console.log第 233 行有内联 style。模型在报告里补充了另外两个需要语义判断的问题组件的文件名是UserList.vue内部defineComponent的名字却叫UserListView不一致props 里的dataSource没有声明默认值如果父组件忘记传值就会告警。以前我让 AI 直接 review 这个组件它十有八九会先说整体结构清晰实现了列表展示功能然后象征性提几个可有可无的建议。而走了 Skill 流程之后它变成了一份标准的审查报告每条问题都有定位和建议我直接复制进 code review 评论都不需要怎么改。5. 调试 Skill 时我踩过的几个坑从不触发到乱触发Skill 不是写完就能用的调试阶段才是真正理解的开始。我前后踩了不少坑挑几个最典型的说说。5.1 description 太宽泛带来的乱触发前面提到过这个问题。我最初把 description 写成用于前端代码质量审查结果只要我一提到这个代码怎么样模型就会调出这个 Skill哪怕我只是随口问问变量命名。后来我把描述收紧并且加上了当用户要求检查、审查或改进某个前端组件这个触发场景限制误触发就少了。这里还有一个细节description 不要太长但也不要太短。太短了模型没法判断适用场景太长了它会消耗大量上下文 token而且真正的关键信息会被淹没。我自己的经验是控制在两三句话把什么场景用和具体查什么都点明白。5.2 脚本路径的坑所有路径都必须是相对项目根目录的路径这个问题特别隐蔽。我在脚本里一开始用的是path.resolve(filePath)看起来没什么问题但实际跑的时候如果当前工作目录不是项目根目录脚本就会因为找不到文件而崩掉。Claude Code 执行命令时的工作目录通常是你启动它的目录但 Skill 里的脚本被调用时的环境不一定和你预期一致。我的解决办法是在SKILL.md里明确规定脚本调用必须从项目根目录执行同时在脚本内部也做一层防御如果文件不存在就在当前目录向上查找找到最近的package.json再重新拼路径。这样两条腿走路基本不会再出现明明文件在那脚本却说找不到的情况。5.3 规则写得太啰嗦反而浪费 token我最初写硬性规则时恨不得把团队规范全文抄进去结果一次审查任务下来光是加载 Skill 就消耗了大量 token而且规则之间还有矛盾。后来我做了个减法只保留可验证、高优先级、AI 容易搞错的规则其余的丢进CLAUDE.md作为背景知识而不是塞进 Skill 的强制清单里。比如缩进必须用两个空格这种规则极容易被文本编辑器自动满足就没必要写进 Skill 浪费时间。而生产代码禁止 console.log这种是 AI 默认不会主动检查的写进去才有价值。做了一次规则权重梳理之后整个 Skill 的输出质量明显提升token 开销也下降了。5.4 模型报喜不报忧的问题让它必须显式标记问题还有一个很有意思的现象如果你不强制输出格式模型在审查一个总体质量还行的文件时倾向于弱化问题甚至把潜在问题说成建议优化。我在一次测试中让 AI 审查一个明显有v-html的文件结果它居然写的是建议关注一下 v-html 的安全风险而没有直接标记为问题。这个语气太软了。后来我在 SKILL.md 里强行加了一条以上规则中任意一条不满足都必须在报告中标记为问题不得忽略不得弱化描述。 同时把输出格式固定为[通过]和[问题]两态。从那以后它的判断果断了很多不会再出现建议关注这种含糊表述。5.5 和 Hooks 的边界Skill 主动Hooks 被动最后提一个边界问题。很多人会问既然 Hooks 也能在特定事件触发校验为什么不用 Hooks 来做组件审查我一开始也试过把审查逻辑挂在文件保存的 hook 上每次改动都强制跑一遍。但实际体验很糟审查一次要等待模型生成报告频繁触发太打断节奏而且很多中间状态本来就不该被审查。后来我把方案改成Hooks 只负责在提交代码前跑脚本检查比如检查有没有console.log而完整的组件质量审查交给 Skill 在需要时主动调用。一被动一主动各管一段体验就顺了。6. 把 Skill 变成团队资产目录、版本与协作自己用顺手之后我开始琢磨怎么把它分享给团队。这部分的经验我觉得很多人用得上因为 Skill 的最大价值在复用而不仅仅是自己爽一下。6.1 项目级目录 vs 用户级目录项目级目录.claude/skills/会跟着仓库走所有人 clone 下来就自带一套。这适合和项目强相关的规则比如这个项目特定的组件命名、目录组织、状态管理约定。用户级目录~/.claude/skills/则是你自己的工具箱适合放那些跨项目通用的技能比如通用的代码审查、提交信息规范化、单元测试生成。我的习惯是项目规则入库通用能力入用户目录。6.2 团队共享 Skill独立仓库 安装脚本如果团队里有多个项目一个个复制.claude/skills/目录显然不现实。我是这样做的建了一个独立的仓库叫team-skills里面按 Skill 分目录组织然后写了一个简单的安装脚本可以一键把所以 Skill 软链到~/.claude/skills/下。这样既能把 Skill 纳入版本管理又能让所有项目同时生效。team-skills/ component-auditor/ SKILL.md scripts/ audit_component.mjs commit-message-writer/ SKILL.md install.shinstall.sh的内容很简单本质上就是逐个建立软链接。需要注意的是软链接在 Windows 上可能要管理员权限如果团队里有 Windows 同事可以直接用拷贝脚本替代。6.3 迭代节奏每一条规则都要能说清为什么Skill 上线之后还会持续迭代。我的迭代节奏大概是每次新发现一个团队反复出现的代码问题就评估要不要加进技能每次有人对审查结果提出异议就回看这条规则是否足够客观。这个过程中最重要的一条原则是每一条新增加的规则都必须能回答为什么这条规则值得让 AI 强制检查。答不上来的就先不加。变量命名风格这种主观的规则我至今没有写进去因为好命名和坏命名的边界对模型来说太模糊容易误报。反而是console.log 残留、内联 style这种客观规则加进去永远不出错。把客观规则和主观判断分开是一个 Skill 长期可用、不被队友吐槽的关键。6.4 基于组件审查 Skill 的思路继续扩展组件审查只是我把 Claude Code 用在规范落地上的第一个例子。同样的思路完全可以直接复制到其他场景提交信息规范化 Skill读取 git diff按照 Conventional Commits 规范生成提交信息。代码迁移 Skill比如把旧版 API 的调用改成新写法规则明确、步骤固定。测试生成 Skill读取组件代码按团队模板生成单元测试骨架。多人协作约定 Skill比如后端接口文档变更后自动同步前端类型定义。我目前已经把提交信息规范也做成了 Skill模板思路和组件审查几乎一样只是规则清单换了。你要是有心想试建议也从自己日常工作里重复出现且经常被吐槽的问题入手那个地方就是你第一个 Skill 的最佳选题。最后分享一个我自己的体会写 Claude Code 的 Skill最大的收获不是AI 更听话了而是逼我把团队的规矩想清楚了。你写每一条规则的时候都必须问自己这是不是客观的是不是可执行的是不是真的重要这些问题想一遍之后连团队文档都跟着变清晰了。所以哪怕你暂时没打算深入玩技能也值得动手写一个试试过程本身就是一种梳理。