
以下是正文:做这个Skill的初衷很直接,也很现实:功能开发时容易"顺手新建一个",而不是先复用已有组件,造成组件库越来越臃肿。这件事对团队的伤害其实是复利型的:重复组件越来越多;维护成本越来越高;UI/交互一致性越来越差;AI生成代码时也更容易继续复制混乱。所以做这个Skill的目标不是"帮AI搜索一下",而是:把"复用优先"的思考过程流程化,让AI在写代码前先走一遍"查索引 → 判断是否复用 → 命不中再新建"的路径。
一开始很容易把问题理解成:"做个组件搜索工具给AI用就好了"。但实际落地后发现,真正的问题不是工具有没有,而是:AI会不会主动用;AI什么时候用;AI用完之后是否还能回到项目上下文;AI能不能稳定走同一条流程。这和Vercel在他们的agent评测里观察到的现象很像:skills本身不是没用,而是agent往往不会稳定触发;而把基础知识放进AGENTS.md这种"被动上下文"后,稳定性反而更高。Vercel的实验里,默认skill触发并没有提升通过率,加入显式指令后才明显改善,而AGENTS.md文档索引方案表现更稳定。这给了一个很关键的设计方向:先解决AI的"决策点"问题,再解决AI的"能力"问题。
最终采用的是三层结构:
把"组件复用优先"的规则、组件索引入口、扫描后需要做的事情,放进AGENTS.md(或同类常驻上下文机制)里。目的不是塞满文档,而是让AI每轮都知道:这个仓库有组件复用机制;默认应该先查可复用组件;查不到再考虑新建;扫描后还有描述补全流程需要继续执行。这层解决的是:AI根本不知道有这套机制。不写进去,AI主动使用skill的概率确实会很低(这点踩过坑)。
如果运行环境支持hooks(例如Claude Code的UserPromptSubmit支持在用户prompt处理前注入额外上下文),就可以做一层"意图路由增强":在用户提到"组件复用 / 是否有现成组件 / 封装组件 / 查组件"等语义时,给AI注入提示,让它优先走组件复用流程。Claude的文档明确写了UserPromptSubmit会在处理前触发,并且可通过additionalContext注入上下文。这层解决的是:AI知道有skill,但不一定想起来用。
Skill不是只写说明文档,而是要提供:明确的调用入口;稳定的输出格式;可执行脚本;失败时的兜底逻辑。OpenAI的Codex Skills文档里提到skills是"渐进披露"机制:运行时先看到skill的元信息(尤其是description),只有决定使用时才加载完整SKILL.md;而且隐式触发高度依赖description。这也是为什么skill的触发边界和描述要写得非常清楚。这层解决的是:AI想用了,但执行过程不稳定。
下面是这次组件复用Skill的几个关键实现点:
在SKILL.md里明确规定:Agent必须调用统一入口find - component.js。这样做的原因很简单:避免AI在多个脚本之间犹豫(scan - components、match - component、resolve - scope……);避免AI漏掉前置步骤(比如索引不存在时先扫描);避免AI调用路径不一致导致结果不稳定。统一入口做了几件事(都在find - component.js里):接收查询词(query)、仓库根路径(repoRoot)、当前聚焦路径(startDir)。如果components.csv缺失,内部自动触发run - scan.js;调用resolve - scope计算当前应用和允许搜索范围;调用match - component做匹配排序;命中时记录使用(用于后续加权);按固定JSON协议返回结果(成功/失败/无匹配/是否触发扫描等)。这一步本质上是把分散逻辑聚合成"一个业务动作":"查一下有没有可复用组件",而不是"先算scope,再查CSV,再排序,再补扫,再记usage"。这对AI很关键。
在monorepo场景里,组件复用很容易踩两个坑:只搜当前app,漏掉根级共享组件;全仓乱搜,结果太多太噪音。所以在resolve - scope.js里做了一个比较工程化的范围解析策略:读取pnpm - workspace.yaml解析workspace包;根据当前聚焦文件/目录反推currentAppRoot;再结合root_scope_patterns(例如apps/_share/、packages/ 等)构建允许范围;最终形成一个搜索集合:当前应用 + 根作用域共享包。如果没有聚焦子项目(比如startDir就是repo root),则切换为全量scope。这个设计很像人类工程师的查找策略:先看"我这个业务应用里有没有",再看"全局共享有没有",而不是直接在整个monorepo海里捞针。
组件匹配如果只做字符串包含,很快就会变成垃圾召回器。在match - component.js + fuzzy - match.js里做了一个组合评分,核心包括:名称精确/包含匹配;模糊匹配(编辑距离);Token重叠;首字母缩写匹配(例如dlp匹配DateLinkPicker);当前应用加权(当前app的组件优先);使用频率加权(常用组件更靠前);来源质量加权(README推断质量高于纯inferred);存在性校验(文件不存在则降权/过滤);记录类型权重(组件优先于依赖)。这一步的目标不是追求"算法先进",而是让排序更符合团队真实使用习惯:"更可能被复用的组件排在前面"。此外还加了一个低分阈值(NO_MATCH_SCORE_THRESHOLD):如果最高分太低,就认为是噪音命中;可以触发一次扫描后再查;还是低分则按"无匹配"返回,不把噪音结果塞给AI。这个点很重要,因为AI一旦拿到一些低质量候选,很容易"将错就错"。
很多类似方案停在“扫一遍生成CSV”,然后就过时了。这次把扫描做成了run - scan.js -> index - manager -> enrich的流水线,核心考虑是持续维护:
resolve - scope;updateIndex;自动触发autoEnrich(可配置)。
保留历史记录并合并;根据source_hash跳过未变化组件;记录last - scan - changed - ids.json;支持并行扫描(包数量较多时启用);对缺失文件支持标记exists = 0(在查找阶段也会回写)。
读取agent - enrich - prompts.json;找出summary占位符项;按id回到components.csv;读取源码/README;生成summary + keywords;再通过update - component - summary.js写回。更关键的是在配置里启用了:agent_mode_no_fallback = true。也就是说,在Agent模式下不走规则引擎降级,而是要求Agent必须完成这一步。这其实就是"流程化思考"的精髓:不是建议,而是纳入主流程。
一个很容易被忽视的点是:查找命中后,还记录了使用行为(usage - tracker)。这意味着系统不是静态的,它会逐步学习团队偏好:哪些组件经常被复用;哪些组件在某个app里更常出现;哪些结果应该在排序中更靠前。这是一种很轻量但非常实用的反馈机制——不需要搞复杂训练,也能提升AI下一次推荐质量。
这也是最想分享的部分:
如果不这样做,AI主动使用skill的概率很低。原因不是AI笨,而是agent的执行是有"决策成本"的:它要先意识到有skill;再判断该不该用;再决定什么时候用。而把基础上下文放进AGENTS.md或通过hook提前注入,本质上是在减少决策点。Vercel的评测结果说明了这种"被动上下文"在某些场景下会更稳定。
只写一堆说明文档不够。AI在工程任务里最需要的是:一个可以直接执行的入口;明确的参数;稳定的返回结构。所以把find - component.js做成统一入口,并定义了固定JSON输出(ok / matches / noMatch / scanTriggered / hint / error等),这会明显提升AI的执行稳定性。
这是最容易被忽略、也是最影响稳定性的一点。如果给AI暴露一堆脚本:resolve - scope.js;match - component.js;run - scan.js;scan - components.js;index - manager.js。它理论上能拼起来,但实践里很容易漏步骤、顺序错、参数错。所以在Skill里显式规定:查找时用find - component.js;构建时用run - scan.js;更新描述时用update - component - summary.js。把复杂系统收敛成几个明确入口,AI才容易稳定执行。
原来以为"写skill"是在给AI增加能力。现在更像是在做:给AI增加"默认工作方式"。换句话说,skill不只是能力包(capability bundle),也是流程控制器(workflow controller)。AGENTS.md负责"告诉AI世界观";Hook负责"提醒AI现在该用哪套流程";Skill负责"把动作做完,并且做得稳定";日志/CSV/usage负责"让系统可观测、可迭代"。这套思路不只适用于组件复用,后面也可以迁移到:任务优化闭环;日志分析标准化;策略诊断流程;代码规范治理。
AI开发前先查可复用组件,而不是直接新建;monorepo下按"当前应用 + 共享组件"范围检索;索引缺失自动扫描;组件描述富化进入主流程;匹配质量有加权与反馈回路;整体流程有明确入口和输出协议。
这次组件复用Skill的开发过程,对最大的启发不是"AI能帮写多少代码",而是:AI其实非常适合被放进一套清晰流程里工作。只要把下面三件事做好:基础上下文(AGENTS.md / hooks);可执行入口(工具函数);明确流程边界(统一入口 + 输出协议)。AI就不会只是"一个会说话的代码补全器",而会更像一个遵守团队规范的工程协作者。而这,才是做这个Skill真正想要的结果。