mcpField
P
penpot-foundations

penpot-foundations

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

关于 penpot-foundations

用于在 Penpot 中建立和治理设计令牌基础的技能,也能从现有设计推导令牌。它将令牌分为基础、语义及可选组件层级,并通过检查点验证引用、绑定与间距。

主要功能

  1. 01创建基础与语义令牌层级
  2. 02从现有设计推导令牌
  3. 03将图形绑定到语义令牌
  4. 04设置浅色与深色模式
  5. 05验证引用关系与间距

适用场景

  1. 01为设计系统建立令牌
  2. 02从硬编码设计提取令牌
  3. 03绑定现有图形以支持主题切换
  4. 04检查令牌引用与间距规则

MCP 相关

该技能通过 `execute_code` 使用 Penpot MCP 工具,包括 `penpotUtils.tokenOverview`、`shapeStructure` 以及令牌创建和应用接口。

安装

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

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

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

包含的文件

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

references/
01-discovery.md
02-token-architecture.md
03-infer-from-design.md
04-themes-modes.md
05-naming.md
06-anti-rationalization.md
07-error-recovery.md
scripts/
applyTokensToShapes.js
bindTokensToElements.js
createSemanticTokens.js
createThemes.js
createTokenSet.js
inferTokensFromShapes.js
inspectFileStructure.js
validateTokens.js

详细介绍

penpot-foundations — 令牌与组件库基础

1. 标题 + 工作原理

penpot-foundations 是工具包中承重的技能:没有受治理的令牌层,下游的任何内容都无法正确工作。所有变更都通过 execute_code 执行;使用 export_shape 进行视觉验证;使用 penpotUtils.shapeStructure 读取结构(完整工具接口: shared/penpot-mcp-tool-reference.md)。此技能使用 penpotUtils.tokenOverview() 读取令牌,通过 penpot.library.local.tokens(addSet、set.addToken({type,name,value}))创建令牌,并使用 shape.applyToken(token, properties) 将其绑定到形状。它分为三个层级——原始 → 语义 → 组件(参见 shared/tokens-schema.json)——也可以从现有的硬编码设计中推断令牌系统。

2. 最重要的一条规则

一切从令牌开始,绝不一次性完成。 分小步构建基础,确保操作幂等:先创建原始令牌,再创建引用它们的语义别名,最后(仅在需要时)创建组件令牌。每个层级完成后都使用 tokenOverview() 验证。绝不默默编造值——先提出比例,再在检查点让人工审核批准。

3. Penpot MCP 工具参考

完整接口:shared/penpot-mcp-tool-reference.md。此技能依赖的领域调用: penpotUtils.tokenOverview() / shapeStructure()(发现 + 推断); penpot.library.local.tokens.addSet / set.addToken / shape.applyToken(写入); 在依赖成员签名之前,调用 penpot_api_info('TokenSet'|'Token'|'TokenCatalog')。

4. Plugin API 要点

注意事项编号参见 shared/plugin-api-gotchas.md。

  • #8 令牌创建——penpot.library.local.tokens;addSet({name}) / addTheme({group,name}) 接受 OBJECT 参数;新集合处于非活动状态(set.toggleActive());令牌的 value 始终是字符串(字面值或 "{reference}");读取 token.resolvedValue。
  • 使用 shared/tokens-schema.json 中完全一致的令牌 type 字符串:color、dimension、spacing、typography、shadow、opacity、borderRadius、borderWidth、fontWeights、fontSizes、fontFamilies、letterSpacing、textDecoration、textCase。(注意 camelCase / 复数形式——不是 border-radius 或 font-size。)
  • #2 异步应用令牌——这是此技能最关键的失败模式。 shape.applyToken(token, properties) 是异步操作(约 100 ms),并且按名称进行绑定(活动集合 / 主题变更时,绑定会重新解析——这正是深色模式能够生效的原因)。在一次 execute_code 调用中应用,稍后再通过另一次调用验证 shape.tokens。绝不要在单次调用中批量应用——在一个循环中执行数百次 applyToken 会产生竞争,并扰乱绑定;每次调用应用约 25–40 个形状,验证每个批次,并重试遗漏项。文本 / Rectangle 的填充绑定最不稳定(Board 绑定可靠);绑定会保留——应用正确令牌覆盖错误绑定,不要尝试通过 fills 清除。
  • 遇到不熟悉的成员时,先通过 penpot_api_info('TokenSet') / penpot_api_info('Token') 验证。

5. 令牌感知型需求说明约定

变更之前,将请求重述为:

  • 背景——产品、品牌、现有系统(如有)、浅色 / 深色需求。
  • 目标——单一且具体(例如,“创建原始 + 语义颜色 / 间距令牌,并创建深色主题”)。
  • 输入——现有令牌、品牌调色板、字号比例(默认小三度 1.2)、间距网格(默认 4px)。
  • 约束——不得使用硬编码值;语义令牌必须引用原始令牌;间距必须符合 4px 网格。
  • 验收标准——每个令牌都能解析;语义层引用原始令牌;所有间距都是 4px 的倍数;(如有要求)深色主题可正常使用。

以绝不硬编码值的资深设计系统工程师身份行事。

6. 强制工作流

阶段 0 — 发现(只读)。 依次调用 high_level_overview、penpotUtils.tokenOverview(),然后读取 shapeStructure(penpot.currentPage.root, 3)。将现有内容记录到 RUN_ID 台账中。 ✋ 检查点:确认范围(新建系统、扩展现有系统,还是从设计推断)。

阶段 1 — 基础变量。 创建 primitives 集合,并将其激活(set.toggleActive() — 新集合默认处于非激活状态),然后添加原始颜色阶梯、间距比例(4px 网格)、圆角比例和字体比例(字体大小采用小三度音阶)。使用 scripts/createTokenSet.js。 ✋ 检查点:检查基础变量比例(tokenOverview() + 命名)。

阶段 2 — 语义变量。 添加引用基础变量的意图别名,并将其分配到两个集合中(被引用的 primitives 集合必须处于激活状态,否则引用会验证失败):

  • 颜色语义(color.action.primary.bg → {color.blue.500})→ modes/light;
  • 模式不变语义(spacing.*、radius.*、font.*)→ semantic。

scripts/createSemanticTokens.js 会按变量类型完成拆分。这样才能让暗色模式成为一套清晰的平行颜色集合。✋ 检查点:检查语义映射。

阶段 3 — 暗色模式(可选)。 使用 scripts/createThemes.js 创建平行的 modes/dark 颜色集合(颜色名称与 modes/light 相同,但颜色值适用于暗色模式);让 modes/light 保持激活状态作为默认模式,并将切换操作交给用户。覆盖 modes/light 中的每个颜色名称(脚本会返回 missing 列表)。暗色模式可用——用户激活 modes/dark 时,绑定会按变量名称重新解析——但 Agent 无法通过插件渲染切换操作(theme.addSet() 不会持久化;插件读取存在延迟)。用户可在 Penpot 的 Tokens 面板中开启 modes/dark / 关闭 modes/light(参见 references/04-themes-modes.md)。✋ 检查点:验证暗色模式的 resolvedValue,恢复浅色模式,并告知用户如何切换。

阶段 4 — 应用 / 推断 / 绑定。 可以将变量绑定到选区(scripts/applyTokensToShapes.js)、从硬编码设计中推断变量(scripts/inferTokensFromShapes.js),或者——最重要的是——按精确值匹配,将变量自动绑定到所有尚未绑定的元素,免得用户手动操作(scripts/bindTokensToElements.js)。这也是主题化的前置条件:只有图形绑定到变量名称时,设计才会随浅色 / 暗色切换而变化(集合 / 主题变化时,绑定会按名称重新解析)。分批应用并验证——applyToken 是异步操作,一次调用批量应用会导致竞争条件或绑定混乱;文本 / 矩形的填充绑定不稳定,需要验证并重试(参见 shared/plugin-api-gotchas.md)。仅按值匹配是一种启发式方法:对颜色相反的界面元素,标记出来以便检查其语义角色。✋ 检查点:检查绑定和覆盖率。

阶段 5 — 验证。 运行 scripts/validateTokens.js,检查孤立变量、未解析引用和偏离网格的间距。生成结构化报告。

7. 关键规则

  1. 基础变量 → 语义变量 → 组件变量。图形应绑定到语义变量,绝不能绑定到基础变量。
  2. 所有间距 / 内边距 / 间隙 / 圆角值都必须是 4px 的倍数。
  3. 绝不创建无法说明理由的变量;在检查点提出新变量,不要自动创建。
  4. 保证幂等:添加前按名称检查是否已有集合 / 变量(避免重复)。
  5. 字体大小遵循小三度音阶(1.2),除非品牌规范另有要求。
  6. 不要在同一次 execute_code 调用中应用变量后又读取其结果(操作是异步的)。
  7. 持续更新 RUN_ID 台账,以便会话截断后恢复工作。

8. 领域架构

三个令牌层级(参见 shared/tokens-schema.json):

  • primitives — 原始且不依赖上下文的刻度(color.blue.500、spacing.4、radius.md、font.size.300)。存在语义令牌时,绝不直接绑定到形状。
  • semantic — 引用 primitives 的意图别名(color.text.default → {color.gray.900}、spacing.inset.md → {spacing.4})。形状绑定的就是这一层。
  • components — 可选的组件级覆盖项,引用 semantic 令牌。仅在组件需要专属表面样式时创建。

集合布局(参见 shared/modes-and-policies.md):模式不变的语义放在 semantic 中;颜色 语义放在 modes/light / modes/dark 中(两者使用相同名称)。主题建模为 Penpot 令牌 主题(addTheme({ group, name })),用于切换匹配的 modes/* 集合;primitives 和 模式不变的 semantic 集合保持不变。

9. 模式与策略

默认模式为 review。创建新令牌、构建主题或将令牌应用到形状,都需要检查点。唯一可自动应用的操作(安全集合,shared/modes-and-policies.md)是:将一个原始值替换为某个令牌,且该值必须与该令牌解析后的值完全相同。

10. 状态管理

RUN_ID 下的记录键(参见 shared/state-management.md):phase、created:[{kind:'set'|'token'|'theme', name, id}]、proposed:[...]、applied:[...]。截断后,继续操作前先使用 tokenOverview() 重新推导实际状态。

11. 用户检查点

阶段之后展示的内容询问事项
0 Discovery现有令牌摘要新建、扩展还是推断?
1 Primitivesprimitives 的 tokenOverview()批准刻度和命名?
2 Semanticsemantic→primitive 映射批准意图映射?
3 Themes各主题下的解析值批准主题切换?
4 Apply/Infer示例的前后对比批准绑定?

12. 命名约定

遵循 shared/naming-conventions.md 使用点分隔命名:集合为 primitives / semantic(模式不变)/ modes/light + modes/dark(颜色)/ 可选的 components;令牌使用小写点分隔路径;主题 归入 mode 组,名称为 Light / Dark / High Contrast。

13. 防止自我合理化对照表

大模型的借口错误原因确定性应对措施
“我先硬编码这个十六进制值,以后再改成令牌。”硬编码值会破坏主题适配和治理;“以后”永远不会到来。停下。读取 tokenOverview(),绑定到语义令牌,或提交一个令牌供审核。
“我直接把形状绑定到 primitive,省一步。”Primitives 无法按主题切换;深色模式会出问题。绑定到引用该 primitive 的语义令牌。
“这个间距是 18px,差不多就行。”偏离网格的值会破坏节奏并违反治理要求。四舍五入到最接近的 4px 网格令牌(16 或 20)。任何例外都必须经人工批准并记录。
“我先创建十几个令牌,以防万一。”未使用或孤立的令牌会形成负担。只创建当前所需的令牌;其余令牌在检查点提交。

14. 辅助代码片段

// Idempotent set + token creation (Phase 1)
const tok = penpot.library.local.tokens;
let prim = tok.sets.find(s => s.name === "primitives") || tok.addSet({ name: "primitives" });
if (!prim.active) prim.toggleActive();          // new sets are INACTIVE by default
if (!prim.tokens.find(t => t.name === "color.blue.500")) {
  prim.addToken({ type: "color", name: "color.blue.500", value: "#0066FF" });
}
return { set: prim.name, count: prim.tokens.length };
// Semantic alias referencing a primitive (Phase 2)
const tok = penpot.library.local.tokens;
let sem = tok.sets.find(s => s.name === "semantic") || tok.addSet({ name: "semantic" });
if (!sem.active) sem.toggleActive();            // and the referenced 'primitives' set must be active too
if (!sem.tokens.find(t => t.name === "color.action.primary.bg")) {
  sem.addToken({ type: "color", name: "color.action.primary.bg", value: "{color.blue.500}" });
}
return { ok: true };

15. 参考资源

  • penpot_api_info('TokenCatalog')、penpot_api_info('TokenSet')、penpot_api_info('Token')。
  • shared/tokens-schema.json(分类体系 + 实际类型字符串)、shared/plugin-api-gotchas.md。

16. 支持文件

references/

文件加载用途
01-discovery.md阶段 0 只读清点
02-token-architecture.md层级、比例和类型比例
03-infer-from-design.md从硬编码设计中构建令牌
04-themes-modes.md浅色/深色主题建模
05-naming.md令牌命名细则
06-anti-rationalization.md治理借口及应对措施
07-error-recovery.md常见故障及修复方法

scripts/

文件用途
inspectFileStructure.js读取页面/库/令牌
createTokenSet.js幂等地创建基础令牌集和令牌
createSemanticTokens.js创建引用基础令牌的语义别名
inferTokensFromShapes.js从原始值推导令牌
applyTokensToShapes.js将令牌绑定到选区
bindTokensToElements.js按值将令牌自动绑定到未绑定的元素(分块执行并验证)——支持主题化
createThemes.js浅色/深色主题
validateTokens.js检查孤立令牌、未解析的引用和偏离网格的值

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

评论

支持 Markdown