Community研究与数据分析github.com

e9tgldr/skill-router

为任务选择正确的技能或技能链,按正确顺序加载,并只询问真正阻碍工作的问题。适用于任何规模的已安装技能库——它会索引所有存在的技能目录,无需事先知道技能名称。

skill-router 是什么?

Skill Router 是一个用于 AI 编码助手(如 Claude Code、Cursor、Codex 等)的智能路由技能。它的核心价值在于解决技能选择过载问题:当系统中安装了大量(比如170个)技能时,错误选择会导致上下文浪费和输出偏离目标。该技能通过一个轻量级的四步流程实现路由:首先快速解析任务特征(产出物、领域、现有工件、受众),然后检查预定义的任务类型映射表以走快速路径,接着使用基于 IDF 加权的词汇搜索脚本搜索技能目录,最后根据一套严格的规则(如最多三个技能、每个系列只选一个、尊重平台门控等)做出选择。它支持在任何技能目录上工作,因为它们会动态索引所有常见的技能安装位置(如 `~/.pi`、`~/.claude`、`~/.cursor` 等),并通过 `SKILL_ROUTER_ROOTS` 环境变量或 `--root` 参数支持自定义路径。此外,它还包括一个学习机制(`--learn`、`--wrong`)来纠正错误路由,以及一套评估和可移植性测试套件来保证路由质量。

兼容平台✓Claude Code✓Codex CLI✓Cursor
npx skills add https://github.com/e9tgldr/skill-router/tree/main

Installed? Explore more 研究与数据分析 skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Skill Router

当前在此处安装了大约170个技能,它们的质量和范围差异巨大, 其中几个彼此近似重复(三个独立的“让它看起来不通用”设计技能, 两份 impeccable 副本,xlsx 和 xlsx-dsh 并存)。选择错误是 单个代价最高的错误:错误的技能会消耗其整个文档的上下文, 并将答案引向离题,而完全没有技能通常比使用错误的技能更好。

因此:先路由,再工作。这个文件就是路由程序。它很廉价——只需一次文件扫描, 一两次工具调用——并且取代了从技能列表中猜测的过程。 该程序与安装无关:下面的计数、名称和系列描述的是它编写时所针对的目录, 搜索会根据实际找到的目录进行标准化。

1. 在接触任何内容之前先阅读任务

在内心回答以下问题,每个一行。它们决定路由方向,而不是交付物。

  • 产出什么? 文件(docx/xlsx/pdf/pptx/png)、运行代码、决策、消息、计划。
  • 什么领域? Web 前端、后端、数据、文档、设计、视频/动画、VR、运维。
  • 是否已有现有工件? 从零开始 vs. 修改别人的代码——这会将路由从构建技能转变为审核/审查和先理解的技能。
  • 谁阅读输出? 投资人、老师、队友、编译器。受众会改变写作技能,而不是技术技能。

如果请求只有一句话的纯粹意图(“给我弄个酷的东西”),那也是一个路由信号: 这意味着还不能选择任何技能,需要先提出问题(第6步)。

2. 快速路径——检查路由表

读取 references/task-types.md(相对于此技能目录)。第一个表将大约 40种常见任务形态映射到一屏内可展示的已验证技能链; 第二个表列出名称难以猜测的窄领域工具(animation-vocabulary、cdn-caching、vercel-connect), 没有人会直接搜索这些名字,所以在断定没有匹配项之前要检查它。

  • 找到匹配项 → 带着那个链进入第4步。不要同时再搜索; 表本身就是答案,再次搜索只会浪费令牌。
  • 没有匹配,或匹配不完全 → 第3步。
  • 表中列出了你没有的技能(不同的安装环境、不同的交互框架、 全新的机器)→ 完全跳过该表,进入第3步。表只是某个安装的映射; 搜索在任何目录上都能工作。用 --doctor 验证。

3. 搜索目录

一条命令,不需要模型参与:

# 路径相对于此技能的目录
node scripts/find_skills.mjs "着陆页感觉太模板化" -n 8
node scripts/find_skills.mjs --doctor      # 扫描了哪些根目录,找到了什么

它会根据名称和描述(使用 IDF 加权,因此罕见词比 user/code/when 权重更高) 加上一个经过策划的概念层(用于那些与目标技能没有共同词汇的措辞), 对所有已安装技能进行评分。打印出最佳匹配结果及其 SKILL.md 路径, 如果没有任何符合则显示 NO GOOD MATCH。

如何更好地进行查询:

  • 使用任务的名词,而不是用户的句子:spreadsheet charts csv, 而不是“你能把这个变成带图表的东西吗”。
  • 运行 2–3 个不同角度,而不是一个长查询——工件角度 (pitch deck)、领域角度(investor fundraising)、问题角度 (text looks templated)。如果需要,可以将它们合并到一次 bash 调用中。
  • --explain 会逐令牌打印每个结果排名原因——当结果看起来不对时使用它, 而不是去猜测原因。
  • 每个结果都标记为 [strong]、[likely] 或 [weak]。[weak] 意味着路由器在根据一个偶然出现的词进行猜测——将其视为建议,而不是答案, 并优先使用你自己的判断。如果所有结果都是 weak,脚本会说明。
  • --all 转储完整目录,--name pdf 将单个名称解析为路径,--json 给出机器可读的输出,-n 20 扩展列表(当你想看到更后面的结果时, 对于措辞不佳的查询,正确答案往往是第4个)。
  • 结果是排名,不是权威。你仍然需要做出选择。
  • 脚本位于此技能的 scripts/ 目录中。如果交互框架暴露了绝对路径, 使用它;否则先 cd 进入技能目录。
  • 它索引所有存在的东西,而不是一个固定的列表:它会扫描跨交互框架的 常见用户级和项目级技能目录(~/.pi、~/.claude、~/.codex、 ~/.agents、~/.cursor,加上 <cwd>/skills 和插件 node_modules)。 可以通过 SKILL_ROUTER_ROOTS=/a/skills:/b/skills 或 --root /a/skills 指向任何其他地方。在陌生的机器上,先运行 --doctor:它会列出每个根目录、 是否存在、贡献了多少技能、重复的名称以及无法解析的 SKILL.md 文件。 新目录不需要概念或门控——它们只是词汇排名的可选增强; 即使没有任何概念层,搜索仍然会根据名称和描述进行排名。

如果脚本本身不可用,或者搜索两次都没有返回合理结果, 则回退到从系统提示列表中读取 ~/.pi/agent/skills/ 的描述。 不要停滞不前,也不要打开五个 SKILL.md 文件期望其中某一个能行得通。

4. 选择——保持链简短的规则

  1. 流程优先于实现。 设定如何运行工作的技能(头脑风暴、 编写计划、系统调试、测试驱动开发、写作技能) 在设定输出看起来什么样的技能(设计、docx、nextjs)之前加载。 流程技能通常会告诉你下一步加载哪个实现技能——让它们引导。

  2. 最多三个技能。 一个是正常的,两个很常见,三个是上限。第四 个意味着你在收集而不是在决定。

  3. 每个系列只选一个。 永远不要加载同一系列的两个成员——取第一列:

    系列选一个
    前端品味 / 反模板design-taste-frontend, ui-craft, impeccable, frontend-design, craft
    重复副本impeccable(agents/)优于 impeccable-dsh;xlsx 优于 xlsx-dsh;kimi/* 优于 dsh/*,除非 dsh 的那个明显更具体
    文档格式正好匹配文件的那个:docx、pdf、pptx、xlsx
    动画animate(Web)、animate-expo(React Native)——不要同时选择
    后端backend-patterns、create-a-backend、api-design——最多两个
    探索 / VRhz-* 系列 + metavr-cli;始终以 hz-quest-verify-first 开始
  4. 尊重平台门控。 hz-*、portal、metavr-cli 需要 Quest/VR 上下文; cloudbase 需要 CloudBase;kimi-webbridge / kimi-cu 需要真实的浏览器或 桌面 GUI。如果任务没有提到平台名称,即使词语匹配得再好,该技能也不适用。

  5. 证明或拒绝。 对于每个候选技能,用一个子句说明:为什么选这个。 如果子句是“它提到了同样的词”,那就拒绝它。两个技能可以共享词汇但仍然用于不同的机器。

  6. 没有技能也是有效的答案。 如果没有任何技能符合标准,用简短的几句话说明, 然后用你自己的判断完成任务。缺少技能不是启动一个半相关技能的理由。

  7. 仅在任务转向时重新路由。 同一工作流中的新子任务 不会触发新的搜索。领域变更(用户说“实际上,把它做成幻灯片” )则会。

5. 用一行说明路由,然后继续

在执行工作之前,声明一次路由:

使用 design-taste-frontend(反模板化着陆页)→ animate 用于英雄区。 文案部分没有合适的技能;我自己来写。

这一行的规则:一两个句子,只包含名称和理由。不要写关于技能库存的论文, 不要写“我为这个任务选择了以下技能,因为……”。用户想看到决策, 而不是决策过程。如果路由不寻常或你明知偏离了表格, 那一行中值得增加一个额外的子句。

6. 只询问真正阻碍工作的问题

这是路由真正体现价值的地方:选定的技能会告诉你它需要知道什么, 所以问那些问题——而且只问那些。

在以下情况下提问,而且只在以下情况下提问:

  • 任务有两个或更多真正不同的交付物(“一张海报”可能是 PNG 或 幻灯片,并且文件不同),
  • 受众或格式未知且无法从上下文中猜测,
  • 所选技能自身的指令要求一个用户必须拥有的决策(品牌、 预算、凭证、真实 vs. 模拟数据),
  • 某个路由会涉及真金白银或触及生产环境。

不要问:

  • 该用哪个技能——这是本技能的工作。问关于结果的问题,让路由从答案中得出,
  • 任何请求已经回答过的问题,任何代码库或文件能回答的问题,
  • 任何合理的默认值可以覆盖的问题。选择默认值,在声明行中说你选了哪个默认值, 然后继续前进。这个用户更喜欢长时间无人值守的运行,而不是逐轮确认。

形式:一次 ask_user_question 调用,最多3个问题,每个问题2-4个选项,推荐选项放在第一位并标注“(推荐)”, 每个选项用一句简短的话说明它承诺了什么。永远不要在第一个问卷之后紧接着再堆一个; 如果一个答案引发了新问题,优先选择一个合理的默认值而不是再来一次往返。

如果你加载的技能有自己的探索或提问阶段(大多数设计和规划技能都有), 则运行那个阶段,而不是自己发明问题。连续两轮提问会被认为是拖延。

7. 加载并执行

  • 使用 read 工具完整读取搜索返回路径的 SKILL.md。 草草阅读的技能会产生草率的输出。

  • 解析任何 references/、scripts/、assets/ 路径时,相对于该技能的目录—— 搜索输出会打印文件路径,因此父目录就是技能根目录。

  • 按脚本原样运行。如果某个脚本需要一个它没有文档说明的参数, 直接说明,而不是用你自己的实现来代替。

  • 技能在冲突时获胜。 一旦加载,它的指令会覆盖本文件关于如何执行工作的意见, 并且覆盖通用的最佳实践。这个文件只负责选择它。

  • 如果加载的技能以“先问用户”或“先计划再写代码”开头, 那就去做——路由到一个流程技能然后跳过它的流程, 比完全不路由更糟糕。

  • 如果在工作中途发现技能选择错误,直接说明并重新路由(第4步)。 悄悄绕过错误的技能是失败的模式。

  • 记录修正,以便同一错误不会再次发生:

    node scripts/find_skills.mjs --learn "<出错的措辞>" <正确的技能>
    node scripts/find_skills.mjs --wrong "<出错的措辞>" <错误的技能>
    

    每当用户拒绝某个路由、加载的技能被证明是错误工具、 或者你不得不手动路由因为搜索遗漏了,就这样做。 学习到的修正会在未来类似的查询中超越词汇得分, 并且它们会随安装环境一起移动——这是路由器在其从未见过的环境中变得更好的方式。

8. 结束

在最后用一行说明:使用了哪些技能,以及工件放在哪里。然后停止—— 不要总结技能内容,不要主动解释路由过程。

维护——在不破坏路由器的情况下更改它

路由器是经过评分的,而不是靠感觉。scripts/eval_routing.mjs 包含80个 真实查询,每个查询都附带一组真正可接受的技能答案, 以及十几个门控案例(一个通用的 React 查询绝不能浮现出一个 Quest 技能)。 在任何更改前后运行它:

node scripts/eval_routing.mjs
# 得分: 80/80 (100.0%)  门控泄露: 0
node ... --verbose      # 逐案例排名
node ... quest          # 仅匹配案例

node scripts/smoke_portable.mjs   # 外部目录 + 学习 + 600技能规模

smoke_portable.mjs 是可移植性测试:它在本路由器从未见过的领域(Kubernetes、Rust、Salesforce、Terraform…)中虚构了16个技能,检查排名、释义鲁棒性、可移植门控、学习、重复名称、空目录、含空格的路径、SKILL_ROUTER_ROOTS 以及600技能的规模运行。如果你更改了评分,两个测试套件都必须保持绿色——eval 套件在已知目录上守护质量,smoke 套件在未知目录上守护行为。

任何能提高分数的更改都是进步;任何降低分数的更改都是回归,无论代码看起来多整洁。期望技能未安装的案例会被跳过,而不是失败,因此套件可以在任何机器上运行。

当真实任务路由错误时,在最便宜、最能解释问题的层面修复它:

  1. 同一概念用词不当 → 在 find_skills.mjs 中添加一个经过策划的 CONCEPTS 规则 (when 正则 → boost 分数,可选的 unless 否决和 demote)。这一层用于那些与技能没有共同词汇的意图: “模糊想法,没有规格” → brainstorming。 一次性问题? 不要为此使用这一层——改为记录它(--learn)。CONCEPTS 是 用于通用行为;记忆则用于“这个措辞,这个技能”。
  2. 重复出现的任务形态 → 在 references/task-types.md 中添加一行。 查询时无需额外成本,快速路径完全跳过搜索。
  3. 某个技能总是输给噪声邻居 → 将其添加到 DEMOTE,或者给噪声技能 添加一个 demote 概念(例如,单独的 dashboard 不能胜过 ui-craft 与 ui-craft-dense-dashboard)。
  4. 平台技能泄露到通用查询中 → 扩展 GATES,添加必须存在才能激活的关键词。
  5. 用户纠正过的路由 → --learn / --wrong,然后继续。偶尔检查 --memory:如果同一技能对于同一种措辞反复被纠正, 将模式提升到 CONCEPTS 中,并 --forget 那些条目。

首先将失败的查询添加到 CASES 中,看着它失败,然后再修复。不要在没有记录下的查询上调整评分—— 那样路由器最终会在你的例子上表现良好,而在用户的实际问题上表现糟糕。

危险信号——你在合理化,停下来

想法现实
“这个很简单,不需要路由”快速路由,快速实现。快速路径

…

[truncated for translation]

相关技能