关于 penpot-router
penpot-router 是一个只负责分流的设计技能,根据用户意图将请求交给一个 Penpot 技能或工作流,适合不确定该从哪种设计操作开始的场景。它先以只读方式检查当前文件,再整理需求并移交,不会修改画布。
主要功能
- 01只读检查页面与选择内容
- 02读取令牌状态和画面结构
- 03按意图选择一个目标
- 04生成需求契约并移交
- 05遇到意图歧义时先询问
适用场景
- 01判断应使用哪种 Penpot 设计技能
- 02为多步骤设计请求选择主要流程
- 03在修改前检查文件和令牌状态
MCP 相关
该技能通过 Penpot MCP 工具读取页面、选择内容、令牌和画面结构,以支持分流。它不执行画布修改,也不负责视觉验证。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ penpot/ penpot-ai-kit --skill penpot-router安装后在 Claude Code 中输入/penpot-router确认已加载。
附带文件references/01-intent-taxonomy.mdreferences/02-preflight-overview.md
详细介绍
penpot-router — 分发器
1. 标题 + 工作原理
penpot-router 是一个轻量入口。它不会绘图、分词或重组任何内容——它会读取用户的意图,并将请求交给且仅交给一个下游技能或工作流(构建屏幕、构建幻灯片、构建设计系统、审计、迁移、提取 DESIGN.md,……)。所有修改都通过 execute_code 执行;使用 export_shape 进行视觉验证;使用 penpotUtils.shapeStructure 读取结构(完整工具列表:shared/penpot-mcp-tool-reference.md)。此技能只会使用 high_level_overview 和只读的 execute_code 探查调用(penpotUtils.shapeStructure、penpotUtils.tokenOverview())。每项修改都由它所路由到的技能负责;此路由器不会进行任何视觉验证,因为它不会修改任何内容。如果宿主客户端已根据技能的 description 自动选择技能,此路由器会平稳降级为文档——references/01-intent-taxonomy.md 中的意图分类将成为参考地图,而非主动分发器。
2. 最重要的一条规则
必须路由到且仅路由到一个目标,并在此之前执行预检。 切勿在路由器内部开始修改,也不要将单个请求并行分发给多个会执行修改的技能。一个请求 → 一次预检(概览 + 快速读取结构/令牌)→ 一个目标技能或工作流 → 移交。 如果意图在两个目标之间存在歧义,请提出一个澄清问题;不要猜测并采取行动。
3. Penpot MCP 工具参考
完整工具列表:shared/penpot-mcp-tool-reference.md。路由器仅依赖以下两个调用:
| 调用 | 路由器使用它的原因 |
|---|---|
high_level_overview | 必须执行的会话前置步骤。做出并执行任何路由决策之前,必须先调用此项。 |
execute_code(只读) | 使用 penpotUtils.shapeStructure(penpot.currentPage.root, 2) 和 penpotUtils.tokenOverview() 感知文件的当前状态,确保路由基于实际情况,而非假设。 |
路由器绝不会调用 execute_code 来创建/修改/删除内容,也绝不会调用 export_shape(无需验证)。所有修改和验证均由下游技能负责。
4. 插件 API 要点
路由器只会访问读取路径:penpot.currentPage、penpot.selection、penpot.library.local.tokens、penpotUtils.shapeStructure、penpotUtils.tokenOverview、penpotUtils.getPages。注意事项(shared/plugin-api-gotchas.md):
- #2 应用令牌是异步的(约 100 ms)——切勿将读回的已解析值视为权威值;路由器不会应用任何令牌,因此它唯一真正的陷阱就是做得太多。
如果不确定某个探查辅助函数是否存在或其签名为何,请使用
penpot_api_info验证(例如penpot_api_info("PenpotUtils", "shapeStructure")),不要猜测。
5. 感知 Token 的简要约定
路由前,先将请求重述为一份简明约定,让选定的技能获得清晰的任务说明。 指定角色:**“扮演一位资深设计系统分流负责人,绝不在错误的工作流中开始工作。”**记录:
- 上下文 — 产品、受众,以及此文件中是否已存在设计系统(根据
tokenOverview()+shapeStructure得出)。 - 目标 — 一个以动词开头的意图(“构建设置屏幕”“审核对比度”“迁移 Figma 按钮库”)。如果用户提出了两个目标,就拆分并路由主要目标;其余目标排队等待处理。
- 输入 — 已选中的形状/画板、目标页面、引用的 Token/组件、外部参考(代码路径、Figma URL)。
- 约束 — 禁用的组件、不可违背的规则、模式(建议/审查/自动修复)、范围上限。如果用户已说明是否要避免通用 AI 风格,则将其作为
antiSlop: on|off传递;构建技能会据此保存设置并跳过其选择性提问。路由器绝不会主动询问此项。 - 验收标准 — 下游技能的“完成”标准(例如“正文文本对比度符合 WCAG AA,≥ 4.5:1”“所有间距均符合 4px 网格”“State 轴的变体矩阵完整”)。路由器不会验证这些标准;它会将其转交目标技能。
路由器将此约定作为交接负载发出。它不会臆造 Token 值或名称——如果请求意味着要创建新 Token,应由下游技能负责(并设置人工审批关卡)。
6. 强制工作流
阶段 0 — 探查(只读)
**目标:**确保会话已初始化,并了解文件状态。
- 确认本次会话中已调用
high_level_overview;如果尚未调用,现在调用。 - 调用一次只读
execute_code,浅层了解状态:return { pages: penpotUtils.getPages().map(p => p.name), currentPage: penpot.currentPage && penpot.currentPage.name, selectionCount: penpot.selection.length, selection: penpot.selection.map(s => ({ id: s.id, name: s.name, type: s.type })), topLevel: penpotUtils.shapeStructure(penpot.currentPage.root, 1) }; - 调用一次只读操作,了解 Token 状态:
return penpotUtils.tokenOverview();
**退出标准:你已了解 (a) 是否存在 Token/集合,(b) 当前选中了什么,(c) 深度为 1 的页面布局。✋ 检查点:**无需检查点——只读操作——直接进入阶段 1。
阶段 1 — 意图分类
**目标:将用户的表述映射到路由表(§8 / references/01-intent-taxonomy.md)中的一行。
按字面理解请求,并结合阶段 0 获取的状态(例如,“尚无 Token”会让含糊的“建立我的设计系统”更倾向于 penpot-foundations / design-system-bootstrap 工作流)。如果请求明确对应一个目标,则继续。如果它以相近的置信度对应两个或更多目标,✋ 检查点:**提出一个消除歧义的问题(用通俗语言列出两个候选目标)。
阶段 2 — 交接
**目标:**通过清晰的任务说明移交控制权。
- 明确说明选定的目标(“正在路由到 penpot-build-screen,因为……”)。
- 将 §5 的感知 Token 简要约定作为负载发出。
- 说明已排队等待处理的次要意图。
- 调用/指示目标技能。路由器的工作到此结束;它不会执行任何修改。 **退出标准:**明确指定且仅指定一个目标,已发出约定,次要意图已排队等待处理。 **✋ 检查点(有条件):**仅当 (a) 阶段 1 存在歧义(两个候选目标的置信度相近),或 (b) 目标是在已有内容的文件上执行成本较高的修改型工作流(迁移、在成熟系统上执行引导流程、任何会重构组件的操作)时,才询问“正在路由到 X——确认还是重选?”对于清晰无歧义的匹配,说明路由目标并继续——目标技能自身的阶段 0 检查点就是用户自然的审核节点;在此再次确认只会增加阻力,不会提升安全性。
7. 关键规则
- 在对路由采取行动前,务必确认已运行
high_level_overview。 如果跳过概览,则不得在该会话中执行任何路由决策。 - 每个请求只指定一个目标。 拆分多意图请求;路由主要意图,将其余意图排队。
- 仅限只读操作。 路由器绝不调用会修改内容的
execute_code,也绝不调用export_shape。 - 有歧义时不要猜测。 如果存在两个合理目标,就提一个问题,而不是抛硬币决定。
- 根据文件状态确定路由。 使用 Phase 0 读取结果来区分(空文件与成熟系统)。
- 原样转发简述。 不要悄悄删去约束或验收标准。
- 退回到文档说明。 如果宿主已经根据描述进行路由,就不要重复分发;将分类体系用作地图,然后退到一旁。
- 默认模式 = 建议。 路由器提出路由建议;它不负责更改画布。
8. 领域架构——路由表
路由器的产物是一个决策,而非画布内容。决策空间如下表所示。
完整措辞映射及回退方案:references/01-intent-taxonomy.md。
技能
| 意图 | 目标技能 | 用户表述示例 |
|---|---|---|
| 建立令牌 / 基础规范(颜色、间距、字体、圆角比例;主题) | penpot-foundations | “设置我们的设计令牌”、“创建颜色 + 间距比例”、“添加深色主题”、“初始化基础规范” |
| 构建 / 扩展可复用组件及变体 | penpot-component-factory | “创建带变体的 Button 组件”、“构建带状态的 Input”、“将其转换为组件”、“添加 Size 轴” |
| 根据简述 + 现有系统组装屏幕 / 视图 | penpot-build-screen | “设计一个设置屏幕”、“排布一个仪表板”、“根据这份简述构建定价页面” |
| 根据代码 / 标记构建屏幕 / 视图 | penpot-build-from-code | “在 Penpot 中创建这个 React 页面”、“将此组件的 JSX 推送到画板”、“构建与此代码匹配的屏幕” |
| 根据简述设计演示文稿 / 幻灯片 | penpot-build-deck | “创建一份演示文稿”、“制作一套幻灯片”、“路演演示文稿”、“为这场演讲制作幻灯片”、“将这份大纲转换为幻灯片” |
| 为交接编写设计文档 / 添加注释 | penpot-document-handoff | “为此设计编写文档”、“为此屏幕添加注释”、“为交接做好准备”、“添加观察记录”、“创建评审卡片”、“向开发人员说明此流程” |
| 无障碍审计(WCAG) | penpot-audit-accessibility | “检查无障碍性”、“WCAG AA 审计”、“检查对比度”、“触控目标是否足够大”、“无障碍审查” |
| 令牌治理审计 | penpot-audit-tokens | “查找硬编码颜色”、“审计令牌使用情况”、“哪些内容不符合 4px 网格”、“查找孤立 / 未使用的令牌” |
| 比较设计与代码(偏差) | penpot-design-to-code-review | “此设计是否与代码匹配”、“设计到代码审查”、“查找 Penpot 与组件之间的偏差” |
| 从文件中提取可移植的 DESIGN.md 规范 | penpot-design-md | “生成一个 DESIGN.md”、“将我们的设计指南导出为 Markdown”、“为我们的编码 Agent 创建样式指南文件” |
| 从 Figma 导入 / 迁移 | penpot-migrate | “迁移此 Figma 文件”、“从 Figma 导入”、“将我们的 Figma 资源库引入 Penpot” |
| 检查设计 / 引导设计摆脱泛泛的 AI 风格 | penpot-anti-slop | “这看起来像 AI 生成的吗”、“检查是否有 AI 味”、“让它显得不那么泛泛”、“¿看起来像 AI 做的吗?”、“避免 AI 风格” |
| 按语义重命名图层 | penpot-rename-layers | “重命名这些图层”、“整理图层名称”、“使用语义化 HTML 图层名称”、“修正 Rectangle 12 这类名称” |
工作流(多技能编排)
| 意图 | 目标工作流 | 用户表达示例 |
|---|---|---|
| 决定从哪里开始(元问题) | routing | “我不知道需要哪个工具”“我该从哪里开始”“帮我处理这个 Penpot 文件” |
| 从头开始/根据代码构建设计系统 | design-system-bootstrap | “搭建完整的设计系统”“从我们的代码库生成令牌、组件和文档”“初始化整个组件库” |
| 从设计简报到完成的屏幕(检查基础 → 构建 → 无障碍) | brief-to-screen | “根据这份简报制作并交付一个屏幕”“端到端设计并验证这个页面” |
| 从设计简报到完成且可播放的幻灯片(构建幻灯片 → 检查幻灯片无障碍 + 幻灯片质量迭代) | brief-to-deck | “把这个大纲做成精良的幻灯片”“端到端设计并验证这份演示文稿” |
| 让 Penpot 与代码保持同步 | code-to-penpot-sync | “让我们的组件与代码同步”“让 Penpot 与代码仓库保持一致”“让设计与代码保持一致” |
| 完整的 Figma → Penpot 迁移计划 | figma-migration | “迁移整个 Figma 项目”“完整导入 Figma,包括令牌、组件和屏幕” |
| 在交接前通过无障碍检查把关设计 | accessibility-gate | “无障碍检查通过前不要交接”“运行无障碍检查关卡”“交付前进行验证” |
9. 模式与策略
默认模式:suggest(参见 shared/modes-and-policies.md)。路由器本质上是只读的,因此
没有安全集自动修复项——无论采用哪种模式,它都不会修改画布。无需询问即可执行的操作:
调用 high_level_overview,运行只读的 shapeStructure/tokenOverview 探索,
并提出路由建议。始终需要用户(或下游技能自身关卡)确认的操作:意图不明确时执行路由,
以及目标技能执行的任何操作(这些操作沿用该技能的模式)。
10. 状态管理
路由器只写入最少的状态(shared/state-management.md)。它不拥有 RUN_ID 工作流——
该工作流归路由到的技能所有——但会记录路由决策,方便恢复会话时了解路由依据:
storage.router = { lastIntent, chosenTarget, queuedIntents, overviewCalled: true }(会话缓存)。- 可选地,通过
setSharedPluginData在penpot-ai命名空间下写入文件内的面包屑,键为router.lastRoute(依赖前请先用penpot_api_info确认签名)。
恢复时:重新读取 storage.router 和面包屑,重新运行第 0 阶段的探索(文件状态可能已改变),
并重新分类,而不是盲目继续——路由必须反映当前实际情况。
11. 用户检查点
| 阶段之后 | 展示的产物 | 询问内容 |
|---|---|---|
| 第 0 阶段(探索) | 页面列表、选区摘要、令牌集是否存在 | (仅告知——无需批准;继续。) |
| 第 1 阶段(分类)——仅在意图不明确时 | 用通俗语言描述的两个候选目标 | “哪一个最符合你的需求——A 还是 B?” |
| 第 2 阶段(交接)——仅在意图不明确,或目标是针对现有内容且会进行高成本修改的流程时 | 选定的目标 + Token-Aware Brief Contract + 排队的意图 | “将路由到 X——确认还是改选?”(明确匹配时:说明路由并继续) |
12. 命名约定
路由器本身不强制命名,但复述设计简报时必须使用该工具包的术语,确保下游技能继承正确的预期(shared/naming-conventions.md):令牌使用
点分隔命名(color.action.primary.bg),组件使用 PascalCase(Button),变体使用
Property=Value 格式(State=Hover),图层使用语义化的 kebab-case HTML 名称(nav、card-container)。
如果请求涉及 RUN_ID(任何多步骤工作流),请使用约定的 slug,例如
dsb-2026-06-05-a,并由目标技能负责管理。
13. 反合理化表
| LLM 给出的借口 | 错误之处 | 会中止流程的确定性对策 |
|---|---|---|
| “这显然是一个构建请求——我现在就开始创建画板。” | 路由器是只读的;此时开始修改会绕过目标技能的发现、简报约定和检查点。 | 停止。路由到 penpot-build-screen/penpot-build-from-code,输出 §5 简报,并由该技能负责阶段 0 和所有修改。 |
| “请求同时提到了令牌和屏幕——我会同时路由到两者。” | 并行分发给两个会修改内容的技能会产生冲突编辑,并导致运行过程无法审计。 | 拆分意图。路由主要目标;将其余意图加入 storage.router.queuedIntents 队列。每个请求只对应一个目标。 |
| “意图有点模糊,但我会选择更可能的技能并继续。” | 错误流程一旦启动,就很难撤销(几何/变体更改不在安全集内)。 | 在阶段 1 检查点暂停;提出一个澄清问题,并提供两个候选目标供选择。 |
“可能之前已经调用过 high_level_overview;我就跳过吧。” | 未加载 MCP 自身的指导就采取行动,是后续 API 误用的首要原因。 | 确认它在本次会话中运行过;如有疑问,就调用它。否则不执行任何路由。 |
| “宿主客户端自动选择了一个技能,但为保险起见,我会再次分发。” | 重复分发会导致相同工作运行两次,或两个技能互相冲突。 | 检测宿主是否自动选择了技能;降级为文档说明(将分类表作为地图提供),然后让出控制权。 |
| “我只根据用户的措辞来路由——没必要读取文件。” | 相同措辞在空文件和成熟系统中会路由到不同目标(“设置我的设计系统”→初始化 vs. 扩展)。 | 执行阶段 0 读取(tokenOverview、shapeStructure),并在分类前根据文件状态解决歧义。 |
14. 辅助代码片段
仅用于只读发现——路由器绝不修改内容。
// Phase 0a — state sense (paste into one execute_code call)
return {
pages: penpotUtils.getPages().map(p => p.name),
currentPage: penpot.currentPage && penpot.currentPage.name,
selectionCount: penpot.selection.length,
selection: penpot.selection.map(s => ({ id: s.id, name: s.name, type: s.type })),
topLevel: penpotUtils.shapeStructure(penpot.currentPage.root, 1)
};
// Phase 0b — token state (does a design system already exist?)
const ov = penpotUtils.tokenOverview();
return {
hasTokens: !!(ov && ov.totalTokens),
overview: ov
};
// Optional — drop a routing breadcrumb into the file (verify signature first via
// penpot_api_info("PenpotFile", "setSharedPluginData"))
penpot.currentFile.setSharedPluginData(
"penpot-ai",
"router.lastRoute",
JSON.stringify({ chosenTarget: "REPLACE-ME", at: "RUN_ID_HERE" })
);
return { recorded: true };
15. 参考资源
penpot_api_info("PenpotUtils", "shapeStructure")、penpot_api_info("PenpotUtils", "tokenOverview")— 确认发现辅助工具的签名。penpot_api_info("PenpotFile", "setSharedPluginData")— 确认面包屑签名。shared/penpot-mcp-tool-reference.md— 工具接口。shared/modes-and-policies.md— 路由器为何只提供建议。- 同级技能自身的
SKILL.md描述 — 路由器映射所依据的权威触发条件列表。
16. 支持文件
references/(渐进式披露的深入说明)
| 文件 | 加载时机 | 内容 |
|---|---|---|
references/01-intent-taxonomy.md | 阶段 1(分类) | 用户措辞 → 目标技能/工作流的完整映射,包含后备方案、平局判定规则和多意图拆分规则。 |
references/02-preflight-overview.md | 阶段 0(发现) | 如何调用 high_level_overview 并执行快速 shapeStructure / tokenOverview 读取,为路由决策提供依据。 |
scripts/(粘贴到 execute_code 中的模板)
无。路由器不执行任何修改,也不需要可复用的修改模板——它唯一使用 execute_code
的地方,是 §14 中内联的只读发现代码片段。
workflows/(随原生安装一并打包)
在原生 Claude Code 安装中,此技能包还包含 workflows/——七个多技能流水线(§8 的工作流目标:routing、design-system-bootstrap、brief-to-screen、brief-to-deck、
code-to-penpot-sync、figma-migration、accessibility-gate),每个流水线都包含一个 README.md(说明文字)和一个 pipeline.json(确定性步骤列表)。路由到工作流时,请从此处打开相应文件;在种子指针安装中,这些文件位于工具包根目录下的 workflows/。
Doctrine paths. 在原生安装中,shared/… 和 policies/… 在此技能包内解析(由安装程序随附);在 Claude Code 插件安装中,它们位于插件根目录下——${CLAUDE_PLUGIN_ROOT}/shared/…,从此文件向上两级。