mcpField
P
penpot-design-md

penpot-design-md

github.com/penpot设计与 UI108127 次安装3 周前更新
代码仓库

关于 penpot-design-md

penpot-design-md 可将 Penpot 设计文件整理为供人和编码 Agent 使用的便携 DESIGN.md。它记录实际读取的令牌、组件样式与视觉特征,不修改画布。

主要功能

  1. 01提取设计令牌和库资源
  2. 02采样组件样式与变体
  3. 03依据导出图像撰写视觉描述
  4. 04生成结构化的本地 DESIGN.md
  5. 05在 Known Gaps 中记录未知项

适用场景

  1. 01记录 Penpot 设计系统以便重建
  2. 02向人员和编码 Agent 传达设计细节
  3. 03在实现前找出缺失的设计信息

MCP 相关

它通过 Penpot MCP 工具读取文件结构和设计数据,并导出图像供视觉检查。技能不会修改画布,输出为本地 Markdown 文件。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/penpot/penpot-ai-kit --skill penpot-design-md

安装后在 Claude Code 中输入/penpot-design-md确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
01-extraction.md
02-designmd-format.md
03-inference.md
04-designmd-template.md
scripts/
extractDesignData.js
sampleComponentStyles.js

详细介绍

penpot-design-md — 从 Penpot 文件中提取 DESIGN.md 规范

1. 标题 + 工作原理

这项技能可将 Penpot 文件转换为 DESIGN.md:一份可移植的 Markdown 文档,让任何人类或 LLM 无需打开 Penpot,也能复现设计系统。文档包含承载设计令牌映射 (colors、typography、rounded、spacing、components)的 YAML frontmatter,以及说明系统行为的 文本章节(概览、各领域章节、注意事项、迭代指南、已知缺口)。 所有修改都通过 execute_code 进行;通过 export_shape 进行视觉验证;通过 penpotUtils.shapeStructure 读取结构(完整工具接口:shared/penpot-mcp-tool-reference.md)——但这项技能完全不修改画布:它只读取(设计令牌、资源库素材、抽样组件样式、导出的图片),并在 Agent 的 文件系统中写入一个本地 Markdown 文件。它在设计上采用多模态方式:美学描述(frontmatter 中的 description、概览、 注意事项)必须在查看实际导出内容之后编写,而不能仅凭设计令牌名称来写。


2. 最重要的一条规则

DESIGN.md 中的每个值都必须能追溯到你在文件中读取或看到的内容——绝不凭空捏造,也不使用“典型值”。 colors: 中出现的十六进制色值,必须来自设计令牌、资源库颜色或抽样形状填充。components: 中的内边距,必须来自真实组件的布局。“不要”项必须是在文件中观察到的(文件从未采用这种做法),而非臆想。如果无法提取某项内容,就将其列入已知缺口——坦诚说明缺口胜过给出看似合理的编造,因为下游 Agent 会根据这份文件构建内容。


3. Penpot MCP 工具参考

完整接口:shared/penpot-mcp-tool-reference.md。这项技能主要使用以下调用(均为只读):

需求调用(除非另有说明,否则在 execute_code 内调用)
页面清单penpotUtils.getPages()、penpotUtils.getPageByName(name)
设计令牌集、主题、设计令牌penpot.library.local.tokens → sets[]、themes[]、set.tokens[](name、type、value、resolvedValue)
资源库素材penpot.library.local → components[]、colors[]、typographies[]
组件样式抽样component.mainInstance(),然后遍历子项:fills、strokes、borderRadius*、flex(内边距/间距)、文本 fontFamily/fontSize/fontWeight/lineHeight/letterSpacing、shape.tokens
页面/画板结构penpotUtils.shapeStructure(shape, depth)
视觉依据在封面、关键组件画板和 1–2 个代表性界面上使用 export_shape(独立的 MCP 工具)

依赖任何不熟悉的签名前,先通过 penpot_api_info 核实。


4. 插件 API 要点

这项技能容易踩中的问题(完整列表:shared/plugin-api-gotchas.md):

  • #1 样式数组——读取 fills[0].fillColor 等属性;不要尝试写入(这项技能不会修改内容)。
  • 读取变体是安全的(#12 仅禁止修改)——可随意读取 variants.properties、variantComponents()[].variantProps,以记录变体轴。
  • 资源库颜色重复——library.local.colors 可能包含多个短名称相同(default、hover)的条目,且属于不同分组;映射到语义名称前,要通过 color.path`/分组消除歧义,或改用基于值的分组。
  • 文本度量位于形状上——某些构建版本中的 fontSize 是字符串;输出 typography: 时,将其规范化为 px 数值。
  • 大型组件的 mainInstance() 可能很慢——按批次抽样组件,每批约 5 个,每次调用一次 execute_code;不要一次性全部处理。
  • 使用前,通过 penpot_api_info 核实不熟悉的签名。

5. 令牌感知型简报约定

提取前,先复述请求。请以资深设计系统文档撰写者的身份行事:读者是另一个 Agent,它将仅凭你的文件重建此系统。

  • 上下文 — 涉及哪些 Penpot 文件和页面、产品是什么、谁会使用 DESIGN.md(人类、编码 Agent,还是两者)。
  • 目标(单一) — 例如:“为 Pencil 设计系统编写 DESIGN.md,涵盖令牌、字体、形状语言,以及 Button/Input/Modal 组件系列。”
  • 输入 — 文件中的令牌集及主题、库组件/颜色/字体、要抽样的页面、文件的输出路径。
  • 约束 — 范围(整个系统还是指定组件);哪个主题为规范主题(浅色/深色),以及如何记录另一主题;格式遵循 design-md 合约(参见 references/02-designmd-format.md)——不要自行另创章节名称。
  • 验收标准(量化) —
    • 每个 colors: 条目都包含从文件中读取的十六进制值,并在正文或 Known Gaps 中注明其来源(令牌/库颜色/抽样填充);
    • 每个 typography: 条目都包含从字体资源或抽样文本形状中读取的 fontFamily/fontSize/fontWeight/lineHeight/letterSpacing;
    • components: 涵盖已商定的组件列表,每个组件的值都通过 {colors.*}/{typography.*}/{rounded.*} 插值(存在已映射颜色时,不得使用原始十六进制值);
    • Overview 和 Do's & Don'ts 仅引用观察到的行为;撰写前至少实际查看过一项导出内容;
    • Known Gaps 列出所有无法提取的领域(响应式行为、动效、层级等)。

6. 强制工作流

视觉依据(强制): 此技能采用 shared/visual-self-review.md 的变体——在导出并查看封面/关键屏幕之前,不得撰写 description、Overview 或 Do's & Don'ts。仅凭令牌名称撰写的审美描述属于臆造。

阶段 0 — 发现(只读)
  • 目标: 在确定提取计划前,盘点文件中提供的内容。
  • 步骤:
    1. 每个会话调用一次 high_level_overview。
    2. execute_code:运行 scripts/extractDesignData.js → 页面、令牌集(含主题及激活状态)、库组件/颜色/字体、计数。将结果缓存到 storage.run.inventory。
    3. 与用户商定范围(要深入记录哪些组件)、规范主题和输出路径。
  • 退出标准: 已完成清单盘点,并商定范围和输出路径。
  • ✋ 检查点: 展示清单摘要和拟定的 DESIGN.md 范围(哪些章节会详细撰写,哪些内容会列入 Known Gaps)。
阶段 1 — 令牌与资源提取
  • 目标: 为前置元数据映射表准备原始材料。
  • 步骤: 按组执行 execute_code:导出颜色令牌(名称 → 解析后的值;令牌集不同时按主题分别导出)、尺寸/间距/圆角令牌、字体资源、库颜色(按组/路径去重)。根据令牌名称/层级推导语义映射(canvas、surface-*、ink-*、primary、hairline、semantic-*);若令牌中没有,则根据库颜色分组和使用情况抽样推导(参见 references/03-inference.md)。
  • 退出标准: 完成 colors:、typography:、rounded:、spacing: 映射表草稿,并为每个条目注明来源。
  • ✋ 检查点: 展示映射表草稿和所有未映射项。确认语义名称,避免其在文档中定型后难以更改。
第 2 阶段 — 组件采样
  • 目标: components: 映射 + Components 正文部分。
  • 步骤: 对每个范围内的组件(每次 execute_code 最多处理 5 个):解析 mainInstance(),读取背景/文本/边框/圆角/内边距/排版及绑定的令牌;捕获变体轴(variants.properties、variantProps)——各状态分别作为独立条目(button-primary-hover,等等)。通过第 1 阶段的映射插值变量值。
  • 退出标准: 每个范围内的组件都有一个前置元数据条目和正文要点;未解析的值均已标记。
  • ✋ 检查点: 在处理完整列表前,先展示 2–3 个组件条目示例,以供审核语气和格式。
第 3 阶段 — 视觉特征审查
  • 目标: 如实描述美学特征。
  • 步骤: 对封面和 1–3 个有代表性的画板/屏幕执行 export_shape。查看它们。 撰写:前置元数据中的 description(一段内容紧凑的文字,涵盖主要表面、强调色的使用、字体特征、形状语言和节奏)、Overview(概述)及 Key Characteristics(关键特征)要点,以及 Do's & Don'ts(注意事项与禁忌;仅包含文件本身展现的规则或其令牌结构所暗示的规则)。
  • 退出标准: 所写内容以实际观察为依据;每条禁忌都能追溯到一项观察(“没有任何胶囊按钮”“只有一种强调色调”)。
  • ✋ 检查点: 将导出结果与拟好的文字并列展示。
第 4 阶段 — 组装、自查并写入文件
  • 目标: 交付成果。
  • 步骤: 按照 references/02-designmd-format.md 组装(章节顺序固定);运行格式自检(前置元数据可解析为 YAML、每个 {ref} 都能对应到一个前置元数据键、存在 colors: 条目时 components: 中不得出现原始十六进制值、Known Gaps 不得为空,除非内容确实完整);将文件写入双方约定的路径。
  • 退出标准: 文件已写入;自检通过。
  • ✋ 检查点: 展示文件(或其大纲和关键摘录),以供最终确认。

7. 关键规则

  1. 画布只读。 绝不修改形状、令牌或库。唯一的写入操作是本地 Markdown 文件。
  2. 不得编造值。 所有十六进制值/像素值/字重都必须从文件中读取。未知值 → Known Gaps。
  3. 引用插值,不重复罗列。 正文文字和 components: 应引用 {colors.x}/{typography.y}/{rounded.z};原始值仅在前置元数据映射中出现一次。
  4. 先查看,再描述。 至少查看一个 export_shape 的结果后,才能撰写美学描述(第 3 阶段)。
  5. 明确主题。 如果文件包含浅色/深色两套设置,应在映射中记录规范主题,并将另一套作为差异小节记录——绝不要悄悄混用两套值。
  6. 按组对库中的颜色去重后,再进行语义映射;不同组中相同的短名称代表不同的颜色。
  7. 整理后披露。 对于包含 100 多个令牌的文件,应归纳为语义分组,并说明合并了哪些内容(“107 个全局令牌 → 14 个语义颜色;完整集合名称见 Known Gaps”)——不得悄悄截断。
  8. 每次 execute_code 调用只执行一个提取步骤;组件采样每批最多处理 5 个。
  9. 变体轴是重要的文档内容——对包含变体轴的组件,记录 Property=Value 矩阵;读取这些信息是安全的。
  10. 输出必须通过格式检查——章节顺序和前置元数据键必须与 references/02-designmd-format.md 完全一致。

8. 领域架构

DESIGN.md 规范(摘要——完整规范见 references/02-designmd-format.md):

--- (YAML frontmatter)
version, name, description        # description = one dense aesthetic paragraph
colors:      { semantic-name: "#hex", ... }          # canvas/surface-*/ink-*/primary/hairline/semantic-*
typography:  { style-name: {fontFamily,fontSize,fontWeight,lineHeight,letterSpacing}, ... }
rounded:     { xs..pill: Npx }
spacing:     { xxs..section: Npx }
components:  { component-or-state: {backgroundColor,textColor,typography,rounded,padding,...}, ... }
---
## Overview                      # prose + **Key Characteristics** bullets
## Colors                        # Brand & Accent / Surface / Text / Semantic subsections, sources cited
## Typography                    # Font Family / Hierarchy / Principles / substitutes note
## Layout                        # Spacing System / Grid & Container / Whitespace Philosophy
## Elevation & Depth             # shadows/borders ladder (or "flat by design")
## Shapes                        # Border Radius Scale + shape language
## Components                    # per component: **`name`** + purpose + property bullets with {refs}
## Do's and Don'ts               # observed rules only
## Responsive Behavior           # only if derivable from the file; else Known Gaps
## Iteration Guide               # how a future agent should edit designs with this doc
## Known Gaps                    # everything not extractable — mandatory honesty section

运行记录键(见 §10):inventory、maps、componentEntries、exportsViewed、gaps。


9. 模式与策略

参见 shared/modes-and-policies.md。此技能为 suggest 模式,并始终保持该模式:它不会修改画布,因此不存在安全应用集合,也没有任何内容可自动应用。唯一的副作用——写入 Markdown 文件——会在第 4 阶段的检查点执行,路径使用用户在第 0 阶段批准的路径。 覆盖现有 DESIGN.md 需要明确确认(请先展示差异摘要)。

10. 状态管理

参见 shared/state-management.md。RUN_ID slug 示例:designmd-2026-07-09-a。会话缓存位于 storage.run.*(清单、映射、组件条目、已查看的导出、缺口)。此技能为只读,因此 不会写入 setSharedPluginData,除非用户要求持久化指向生成文档的指针(designmd.lastGenerated = 路径 + 日期)。恢复时:重新读取 storage.run;如果已不存在, 则重新运行第 0 阶段(提取开销低且幂等)。


11. 用户检查点

阶段后展示的产物询问内容
0 发现清单(页面、集合、主题、资源)+ 拟定范围和输出路径“请确认范围、规范主题以及文件写入位置。”
1 设计令牌草拟的 frontmatter 映射 + 未映射值“是否批准这些语义名称/指出映射错误?”
2 组件2–3 个组件条目示例“语气和详略程度是否合适?确认后我会补全列表。”
3 视觉导出内容 + 草拟的描述/概述/注意事项“这些文字是否符合你看到的内容?”
4 汇总已编写的文件(大纲 + 摘录)“请最终确认——已知缺口中还有什么要补充的吗?”

12. 命名约定

参见 shared/naming-conventions.md。Frontmatter 键使用 kebab-case 语义名称,遵循 design-md 惯例(ink-muted、surface-2、display-xl、button-primary-hover)——将 Penpot 的点号表示法令牌映射到这些名称,并在 Colors 部分记录映射关系(color.text.muted → ink-muted), 以便文档可以追溯到源文件。组件条目使用组件的 kebab-case 名称,并根据变体值派生 -hover/-pressed/-disabled/-selected 状态后缀。


13. 反合理化对照表

LLM 给出的借口错误原因确定性应对措施
“文件里没有令牌,所以我会写一套常见配色。”编造的值会污染文档的所有下游使用者。停止。采样真实的形状填充(references/03-inference.md),映射现有内容,其余内容列入已知缺口。
“我可以从令牌名称描述美学风格。”color.primary = #00d1b8 并不能说明设计是紧凑还是疏朗、扁平还是有层次。在至少查看 1 个 export_shape 前,暂停第 3 阶段。文字描述必须引用观察到的内容。
“107 个令牌太多了;我就原样列出来吧。”原始转储不是文档——此格式要求按语义组进行整理。整理到语义映射中,然后在 Colors + Known Gaps 中明确说明归并情况。
“这个组件一目了然——标准按钮,8px 圆角。”“标准”是编造的;此文件中的按钮可能是 6px 圆角并带有极细边框。编写任何组件条目前,先采样实际的 mainInstance()。
“注意事项本来就是通用最佳实践。”此部分记录的是这个系统的规则,而不是设计常识。每条注意事项都必须能追溯到一项观察(令牌结构、采样样式或已查看的导出内容)。
“浅色和深色值不同;我会取平均值或按属性挑选。”混合主题值描述的是一个并不存在的设计。选择规范主题(第 0 阶段的决策);将另一个主题记录为差异小节。

14. 辅助代码片段

清单(第 0 阶段——或使用 scripts/extractDesignData.js):

const lib = penpot.library.local;
return {
  pages: penpotUtils.getPages().map(p => p.name),
  sets: (lib.tokens.sets || []).map(s => ({ name: s.name, active: s.active, count: (s.tokens||[]).length })),
  themes: (lib.tokens.themes || []).map(t => ({ group: t.group, name: t.name })),
  components: (lib.components || []).length, colors: (lib.colors || []).length,
  typographies: (lib.typographies || []).map(t => t.name)
};

转储带解析结果的颜色令牌(第 1 阶段):

const out = [];
for (const s of penpot.library.local.tokens.sets || []) {
  if (!s.active) continue; // canonical theme only — dump inactive sets separately as the delta
  for (const t of s.tokens || []) if (t.type === "color")
    out.push({ set: s.name, name: t.name, value: t.value, resolved: String(t.resolvedValue) });
}
return { count: out.length, tokens: out };

采样单个组件的样式(第 2 阶段):

const comp = penpot.library.local.components.find(c => c.name === "REPLACE-ME");
const root = comp.mainInstance();
const texts = penpotUtils.findShapes(s => s.type === "text", root).slice(0, 3);
return {
  name: comp.name,
  bg: root.fills && root.fills[0] ? root.fills[0].fillColor : null,
  radius: root.borderRadius ?? null,
  padding: root.flex ? [root.flex.topPadding, root.flex.rightPadding, root.flex.bottomPadding, root.flex.leftPadding] : null,
  gap: root.flex ? [root.flex.rowGap, root.flex.columnGap] : null,
  boundTokens: root.tokens || {},
  text: texts.map(t => ({ family: t.fontFamily, size: t.fontSize, weight: t.fontWeight, lh: t.lineHeight, ls: t.letterSpacing, fill: t.fills && t.fills[0] && t.fills[0].fillColor })),
  variantAxes: comp.isVariant && comp.isVariant() ? comp.variantProps : null
};

15. 参考资源

  • penpot_api_info("TokenCatalog")、("LibraryComponent", "mainInstance")、("Variants")、("LibraryTypography")——在第 1/2 阶段前进行验证。
  • shared/penpot-mcp-tool-reference.md(工具接口)、shared/plugin-api-gotchas.md(易踩的坑)、shared/tokens-schema.json(层级、Penpot 令牌类型字符串)。
  • 此格式的规范骨架:references/04-designmd-template.md(自包含——无需外部语料)。

16. 支持文件

参考资料(渐进式披露——在相应阶段运行时加载)
文件阅读阶段内容
references/01-extraction.md阶段 0–2在哪里读取什么:令牌集/主题、库资源、组件采样方法、变体维度、主题处理
references/02-designmd-format.md阶段 3–4完整的 DESIGN.md 规范:frontmatter 架构、章节顺序、插值规则、语气、自检清单
references/03-inference.md阶段 1(令牌较少的文件)如何在没有令牌的情况下推导语义映射:库颜色分组、填充频率采样、表面层级检测
references/04-designmd-template.md阶段 4可填写的 DESIGN.md 框架(通用且自包含)——复制后填入提取的值,并删除指导说明
脚本(粘贴到 execute_code 调用中;替换占位符)
脚本用途
scripts/extractDesignData.js阶段 0——一次调用即可进行只读清点:页面、集合、主题、资源、计数
scripts/sampleComponentStyles.js阶段 2——批量采样最多 5 个组件的解析后样式、绑定令牌和变体维度

规范路径。 在原生安装中,shared/… 和 policies/… 会在此捆绑包内解析(由安装程序随附);在 Claude Code 插件安装中,它们位于插件根目录——${CLAUDE_PLUGIN_ROOT}/shared/…,也就是本文件向上两级的目录。

评论

支持 Markdown