关于 penpot-migrate
penpot-migrate 是将 Figma 设计迁移到 Penpot 的技能,先构建中间表示,再分阶段转换令牌、组件和屏幕。它支持通过 Figma MCP 读取设计,也可使用粘贴的导出数据,并逐步检查结构与视觉保真度。
主要功能
- 01构建中间表示后再写入 Penpot
- 02迁移变量、令牌、组件和屏幕
- 03将 Auto Layout 转为 flex 或 grid
- 04按阶段检查迁移结果
- 05报告保真度差异
适用场景
- 01将 Figma 设计系统迁移到 Penpot
- 02从粘贴的 Figma 导出数据创建 Penpot 文件
- 03逐屏检查迁移后的布局和视觉效果
MCP 相关
该技能通过 Figma MCP 读取设计数据,并通过 Penpot MCP 创建和验证目标内容;也可在没有 Figma MCP 时处理粘贴的导出数据。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ penpot/ penpot-ai-kit --skill penpot-migrate安装后在 Claude Code 中输入/penpot-migrate确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/01-figma-analysis.md02-ir-building.md03-token-migration.md04-component-migration.md05-layout-translation.md06-screen-migration.md07-validation.md08-error-recovery.mdscripts/analyzeFigmaStructure.jsbuildIR.jsmigrateComponent.jsmigrateScreen.jsmigrateTokens.jsvalidateFidelity.js详细介绍
penpot-migrate — Figma → Penpot,以保真度为先
1. 标题 + 工作原理
penpot-migrate 连接两个 MCP 服务:它通过 Figma MCP 读取 Figma 设计,再通过 Penpot MCP 将其写入 Penpot——所有修改都通过 execute_code 完成;使用 export_shape 进行视觉验证;使用 penpotUtils.shapeStructure 读取结构(完整工具列表:shared/penpot-mcp-tool-reference.md)。它绝不会直接将 Figma 数据写入 Penpot——而是先构建标准化的中间表示(IR),再将 IR 转换为 Penpot 构造(画板、弹性布局、令牌、组件)。如果无法使用 Figma MCP,也可以手动粘贴 Figma 导出内容或 JSON,由它据此进行迁移。
2. 最重要的一条规则
**任何写入 Penpot 的操作之前都要先构建 IR,并分层迁移。**先迁移令牌,再迁移组件,最后迁移屏幕——每层都要验证。绝不要一次性迁移整个文件。IR 是解耦 Figma 模型与 Penpot API 的契约。
3. Penpot MCP 工具参考
完整工具列表:shared/penpot-mcp-tool-reference.md。写入 Penpot 的工具:createBoard/addFlexLayout/addGridLayout、penpot.library.local.tokens.addToken、createComponent/createVariantFromComponents,以及用于保真度检查的 export_shape。读取 Figma 的工具:Figma MCP 的设计上下文工具(名称各不相同;将其视为生成原始数据,再由 IR 进行标准化)。
4. 插件 API 要点
注意事项编号对应 shared/plugin-api-gotchas.md。
- Penpot 使用画板(不是 Frame);自动布局对应画板的弹性布局(
dir、间距、内边距、填充/自动/固定尺寸)或网格布局。 - Figma 变量 → 通过
addToken({type,name,value})转换为 Penpot 令牌,使用实际的类型字符串(shared/tokens-schema.json)。将 Figma 模式映射为 Penpot 主题。 - #9 Figma 组件集/变体 → Penpot 变体容器:优先使用
penpotUtils.createVariantContainer([{ shape: mainInstance, properties }])(≥ 2.17);penpot.createVariantFromComponents(mainInstances)是底层备用方案;Board.combineAsVariants(ids)虽列于 2.17 中,但尚未验证——不要使用。注意 #12——变体修改会损坏文件;优先采用先创建再分组的方式,绝不要就地编辑变体容器。 - #2 令牌应用是异步的——在一次调用中应用,并在之后的调用中验证
resolvedValue/shape.tokens;#4 弹性布局会覆盖子项的 x/y;#6 修改实例内部结构前先分离实例。 - 遇到不熟悉的签名时,先用
penpot_api_info验证。
5. 令牌感知型需求说明契约
- 上下文 — 源 Figma 文件/范围、目标 Penpot 文件、保真度预期。
- 目标 — 唯一目标:“以 <保真度> 将 Figma 中的 <范围> 迁移到 Penpot”。
- 输入 — Figma 访问方式(MCP 或粘贴的导出内容)、命名/令牌映射规则。
- 约束 — 保留层级/布局/变体;将变量映射为令牌;间距符合网格。
- 验收标准 — 已构建 IR;令牌已迁移且解析正常;组件/变体已重建;屏幕视觉匹配(对比导出内容);保真度报告。
扮演一名重视结构保真度的迁移工程师。
6. 强制工作流
**视觉自检(强制):**在每个展示视觉成果的 ✋ 检查点之前,运行
shared/visual-self-review.md中的导出 → 查看 → 修复循环——导出刚完成的单元,对照检查清单自行检查图像,修复可见缺陷(最多 2 轮),并展示同一份导出,同时指出仍然存在的缺陷。
**阶段 0 — Figma 分析。**读取源数据(Figma MCP 或粘贴的数据);盘点令牌/组件/屏幕(scripts/analyzeFigmaStructure.js、references/01-figma-analysis.md)。✋ 检查点:范围与映射规则。
**阶段 1 — 构建 IR。**将数据规范化为 IR(scripts/buildIR.js、references/02-ir-building.md)。IR 是纯数据;此时还不写入 Penpot。✋ 检查点:审核 IR 覆盖范围。
**阶段 2 — 令牌。**将 Variables 转换为令牌(scripts/migrateTokens.js、references/03-token-migration.md);与 penpot-foundations 协调。✋ 检查点。
**阶段 3 — 组件。**重建组件与变体(scripts/migrateComponent.js、references/04-component-migration.md)。✋ 检查点。
**阶段 4 — 布局与屏幕。**将 Auto Layout 转换为 flex/grid(references/05-layout-translation.md);构建屏幕(scripts/migrateScreen.js、references/06-screen-migration.md)。每个屏幕设一个 ✋ 检查点(export_shape)。
**阶段 5 — 验证保真度。**运行 scripts/validateFidelity.js(references/07-validation.md)——检查结构、令牌和视觉对比。报告结果。(遇到问题时参阅 references/08-error-recovery.md。)
7. 关键规则
- 先构建 IR,再进行任何 Penpot 写入。
- 按顺序迁移令牌 → 组件 → 屏幕,并逐项验证。
- 将 Auto Layout 转换为 flex/grid;绝不要将自动布局的内容改为绝对定位。
- 将 Variables 转换为带有实际类型字符串的令牌;将 modes 转换为主题。
- 如果缺少 Figma MCP,则以适当方式降级处理(接受粘贴的数据)。
- 如实报告保真度差异;不完全一致时不要声称达到 1:1。
8. 领域架构
IR(纯 JSON)用于解耦这两个工具:
{ tokens:[{type,name,value,mode?}],
components:[{name, variantProps?, layout, children:[...]}],
screens:[{name, size, layout, children:[...]}] }
每个 IR 节点都包含足以构建对应 Penpot 结构的信息(布局 = flex/grid 规范;子项引用组件或基本元素)。转换过程读取 IR,并写入 Penpot。
9. 模式与策略
默认采用 review。组件/变体重构和分离操作绝不自动执行(shared/modes-and-policies.md)。
10. 状态管理
在 RUN_ID 下维护账本:phase、ir(或其指针)、migrated:{tokens,components,screens}、gaps:[...]。IR 是可恢复的工作产物——截断后重新读取它。
11. 用户检查点
| 阶段结束后 | 产物 | 询问 |
|---|---|---|
| 0 | 盘点清单 + 映射规则 | 是否批准范围/映射? |
| 1 | IR 覆盖范围 | 是否批准 IR? |
| 2 | 已迁移的令牌(tokenOverview) | 是否批准令牌? |
| 3 | 组件/变体 | 是否批准组件? |
| 4 | 屏幕 export_shape | 是否批准屏幕? |
12. 命名约定
shared/naming-conventions.md:将 Figma 名称映射为 Penpot 约定(PascalCase 组件、Property=Value 变体、语义图层、点分隔令牌)。
13. 反合理化对照表
| 借口 | 错在哪里 | 应对措施(停止) |
|---|---|---|
| “跳过 IR,直接从 Figma 写入 Penpot。” | 这会耦合两种模型,导致脆弱且有损。 | 先构建 IR;再从 IR 进行转换。 |
| “全部使用绝对定位来匹配像素。” | 会失去 Auto Layout 的响应式特性。 | 将 Auto Layout 映射为 flex/grid;只有 Figma 使用绝对定位时才使用绝对定位。 |
| “将 Variables 重新创建为硬编码值。” | 这会丢弃令牌系统。 | 将 Variables 迁移为令牌;将 modes 转换为主题。 |
| “一次性迁移整个文件。” | 一次完成会损失保真度,也无法审计。 | 分层迁移:令牌 → 组件 → 屏幕,并逐项验证。 |
| “Figma MCP 未连接,所以我来猜设计。” | 猜测会凭空捏造设计。 | 请用户粘贴导出内容/JSON;根据真实数据操作。 |
| “声称结果完美达到 1:1。” | Figma 的部分功能无法直接映射。 | 如实报告保真度差异。 |
14. 辅助代码片段
// Translate an IR layout node to a Penpot flex Board
function buildFromIR(node, parent){
const b = penpot.createBoard(); b.name = node.name;
if (node.layout && node.layout.type === "flex"){
const f = b.addFlexLayout();
f.dir = node.layout.dir || "column";
f.rowGap = node.layout.rowGap || 0; f.columnGap = node.layout.columnGap || 0;
}
(parent || penpot.currentPage.root).appendChild(b);
return b;
}
return { ok: true };
15. 参考资源
penpot_api_info('Board')、penpot_api_info('VariantContainer')、penpot_api_info('TokenSet')。- Figma MCP 设计上下文工具(名称因版本而异)——通过 Figma MCP 自身的概览了解可用工具。
16. 配套文件
references/:01-figma-analysis.md、02-ir-building.md、03-token-migration.md、04-component-migration.md、05-layout-translation.md、06-screen-migration.md、07-validation.md、08-error-recovery.md。
scripts/:analyzeFigmaStructure.js、buildIR.js、migrateTokens.js、migrateComponent.js、migrateScreen.js、validateFidelity.js。
Doctrine 路径。 在原生安装中,shared/… 和 policies/… 指向此软件包内的路径(由安装程序供应);在 Claude Code 插件安装中,它们位于插件根目录下——${CLAUDE_PLUGIN_ROOT}/shared/…,也就是此文件上方两级目录。