penpot-foundations

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

penpot-foundations — token & library foundation

penpot-foundations — token 与库基础

1. Title + How it works

1. 标题与工作原理

penpot-foundations
is the load-bearing skill of the kit: nothing downstream is correct without a governed token layer. Every mutation goes through
execute_code
; validate visually with
export_shape
; read structure with
penpotUtils.shapeStructure
(full tool surface:
shared/penpot-mcp-tool-reference.md
). This skill reads tokens with
penpotUtils.tokenOverview()
, creates them through
penpot.library.local.tokens
(
addSet
,
set.addToken({type,name,value})
), and binds them to shapes with
shape.applyToken(token, properties)
. It works in three tiers — primitive → semantic → component (see
shared/tokens-schema.json
) — and can also infer a token system from an existing hardcoded design.
penpot-foundations
是本工具包的核心支撑技能:没有规范化的token层,下游所有内容都无法保证正确性。所有变更都通过
execute_code
执行;使用
export_shape
进行视觉验证;通过
penpotUtils.shapeStructure
读取结构(完整工具说明见
shared/penpot-mcp-tool-reference.md
)。本技能通过
penpotUtils.tokenOverview()
读取token,通过
penpot.library.local.tokens
(
addSet
、
set.addToken({type,name,value})
)创建token,并通过
shape.applyToken(token, properties)
将token绑定到形状。它采用三层架构——基础层 → 语义层 → 组件层(见
shared/tokens-schema.json
),还可以从现有硬编码设计中推断出token系统。

2. The One Rule That Matters Most

2. 最重要的核心规则

Tokens before everything, and never one-shot. Build the foundation in small, idempotent steps: primitives first, then semantic aliases that reference them, then (only if needed) component tokens. Validate after each tier with
tokenOverview()
. Never invent values silently — propose the scale and let a human approve it at the checkpoint.
Token优先于一切,且绝不能一次性完成。 以小型、幂等的步骤构建基础:先做基础token,再做引用它们的语义别名,最后(仅在需要时)做组件token。每完成一层都用
tokenOverview()
验证。绝不能凭空创造值——提出刻度方案,由人工在检查点确认。

3. Penpot MCP Tool Reference

3. Penpot MCP 工具参考

Full surface:
shared/penpot-mcp-tool-reference.md
. Domain calls this skill leans on:
penpotUtils.tokenOverview()
/
shapeStructure()
(discovery + inference);
penpot.library.local.tokens.addSet
/
set.addToken
/
shape.applyToken
(writes);
penpot_api_info('TokenSet'|'Token'|'TokenCatalog')
before relying on member signatures.
完整接口说明见
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 Essentials

4. 插件 API 核心要点

Gotcha numbers refer to
shared/plugin-api-gotchas.md
.
  • #8 token creation —
    penpot.library.local.tokens
    ;
    addSet({name})
    /
    addTheme({group,name})
    take OBJECT args; new sets are INACTIVE (
    set.toggleActive()
    ); token
    value
    is always a string (literal or
    "{reference}"
    ); read
    token.resolvedValue
    .
  • Use the exact token
    type
    strings from
    shared/tokens-schema.json
    :
    color
    ,
    dimension
    ,
    spacing
    ,
    typography
    ,
    shadow
    ,
    opacity
    ,
    borderRadius
    ,
    borderWidth
    ,
    fontWeights
    ,
    fontSizes
    ,
    fontFamilies
    ,
    letterSpacing
    ,
    textDecoration
    ,
    textCase
    . (Note camelCase/plural — NOT
    border-radius
    or
    font-size
    .)
  • #2 async token application — this skill's critical failure mode.
    shape.applyToken(token, properties)
    is async (~100 ms) and binds by NAME (bindings re-resolve when the active set/theme changes — that is what makes dark mode work). Apply in one
    execute_code
    call, verify
    shape.tokens
    in a LATER call. Never mass-apply in a single call — hundreds of
    applyToken
    s in one loop race and scramble bindings; apply in chunks of ≈25–40 shapes per call, verify each chunk, retry misses. Text/Rectangle fill bindings are the flakiest (Boards are reliable); bindings are sticky — overwrite a wrong one by applying the correct token, don't try to clear it via
    fills
    .
  • Verify any unfamiliar member with
    penpot_api_info('TokenSet')
    /
    penpot_api_info('Token')
    first.
注意事项编号对应
shared/plugin-api-gotchas.md
文件。
  • #8 token 创建 — 通过
    penpot.library.local.tokens
    操作;
    addSet({name})
    /
    addTheme({group,name})
    接收对象参数;新创建的集合默认处于未激活状态(需调用
    set.toggleActive()
    激活);token 的
    value
    始终为字符串(字面量或
    "{reference}"
    引用格式);可读取
    token.resolvedValue
    获取解析后的值。
  • 请使用
    shared/tokens-schema.json
    中定义的精确token
    type
    字符串:
    color
    、
    dimension
    、
    spacing
    、
    typography
    、
    shadow
    、
    opacity
    、
    borderRadius
    、
    borderWidth
    、
    fontWeights
    、
    fontSizes
    、
    fontFamilies
    、
    letterSpacing
    、
    textDecoration
    、
    textCase
    。(注意是驼峰命名/复数形式——不是
    border-radius
    或
    font-size
    。)
  • #2 异步token应用——本技能的关键故障点。
    shape.applyToken(token, properties)
    是异步操作(约100毫秒),且按名称绑定(当激活的集合/主题变化时,绑定会重新解析——这是深色模式生效的原理)。请在一次
    execute_code
    调用中完成应用,在后续调用中验证
    shape.tokens
    。绝不要在单次调用中批量应用——循环中执行数百个
    applyToken
    会引发竞态,导致绑定混乱;请按每次调用约25-40个形状的批次应用,每批验证后重试失败项。文本/矩形的填充绑定最不稳定(画板绑定是可靠的);绑定是持久的——如果绑定错误,直接应用正确的token覆盖即可,不要尝试通过
    fills
    清除。
  • 遇到不熟悉的成员,请先调用
    penpot_api_info('TokenSet')
    /
    penpot_api_info('Token')
    确认。

5. Token-Aware Brief Contract

5. 具备Token意识的需求约定

Before mutating, restate the request as:
  • Context — product, brand, existing system (if any), light/dark needs.
  • Objective — single and specific (e.g., "create primitive + semantic color/spacing tokens and a dark theme").
  • Inputs — existing tokens, brand palette, type scale ratio (default Minor Third 1.2), spacing grid (default 4px).
  • Constraints — no hardcoded values; semantic tokens must reference primitives; spacing on the 4px grid.
  • Acceptance Criteria — every token resolves; semantic tier references primitives; all spacing is a 4px multiple; (if requested) a working dark theme.
Act as a senior design-systems engineer who never hardcodes values.
在进行变更前,请将需求重述为以下部分:
  • 上下文 — 产品、品牌、现有系统(如有)、浅色/深色模式需求。
  • 目标 — 单一且明确(例如:"创建基础+语义颜色/间距token和深色主题")。
  • 输入 — 现有token、品牌调色板、字号比例(默认小三度 1.2)、间距网格(默认4px)。
  • 约束 — 不允许硬编码值;语义token必须引用基础token;间距遵循4px网格。
  • 验收标准 — 所有token都能解析;语义层引用基础层;所有间距都是4px的倍数;(如要求)深色主题可正常工作。
请扮演从不硬编码值的资深设计系统工程师。

6. Mandatory Workflow

6. 强制工作流

Phase 0 — Discovery (read-only).
high_level_overview
, then
penpotUtils.tokenOverview()
and a
shapeStructure(penpot.currentPage.root, 3)
read. Record what already exists in the
RUN_ID
ledger. ✋ Checkpoint: confirm scope (new system vs. extend vs. infer-from-design).
Phase 1 — Primitives. Create the
primitives
set and activate it (
set.toggleActive()
— new sets are created inactive), then add raw color ramps, the spacing scale (4px grid), radius scale, and type scale (font sizes via Minor Third). Use
scripts/createTokenSet.js
. ✋ Checkpoint: review the primitive scales (
tokenOverview()
+ naming).
Phase 2 — Semantic. Add intent aliases that reference primitives, routed into two sets (the referenced
primitives
set must be active or references fail validation):
  • colour semantics (
    color.action.primary.bg
    →
    {color.blue.500}
    ) →
    modes/light
    ;
  • mode-invariant semantics (
    spacing.*
    ,
    radius.*
    ,
    font.*
    ) →
    semantic
    .
scripts/createSemanticTokens.js
does this split by token type. This is what makes dark mode a clean parallel colour set. ✋ Checkpoint: review semantic mapping.
Phase 3 — Dark mode (optional). Create the parallel
modes/dark
colour set (same colour names as
modes/light
, dark values) with
scripts/createThemes.js
; leave
modes/light
active as default and hand the toggle to the user. Cover every
modes/light
colour name (the script returns a
missing
list). Dark mode works — bindings re-resolve by token name when the user activates
modes/dark
— but the agent cannot render the switch from the plugin (
theme.addSet()
doesn't persist; the plugin's read lags). The user toggles
modes/dark
on /
modes/light
off in Penpot's Tokens panel (see
references/04-themes-modes.md
). ✋ Checkpoint: verify dark
resolvedValue
s, restore light, and tell the user how to switch.
Phase 4 — Apply / Infer / Bind. Either bind tokens to a selection (
scripts/applyTokensToShapes.js
), infer tokens from a hardcoded design (
scripts/inferTokensFromShapes.js
), or — fundamental — auto-bind tokens to every unbound element by exact value match so the user doesn't have to do it by hand (
scripts/bindTokensToElements.js
). This is also the precondition for theming: a design only follows a light/dark switch if its shapes are bound to token names (bindings re-resolve by name when sets/themes change). Apply in chunks and verify —
applyToken
is async and mass-application in one call races/scrambles bindings; Text/Rectangle fill bindings are flaky and need verify+retry (see
shared/plugin-api-gotchas.md
). Value-only matches are a heuristic: flag inverse-colored chrome for a semantic-role review. ✋ Checkpoint: review bindings + coverage.
Phase 5 — Validate.
scripts/validateTokens.js
— orphans, unresolved references, off-grid spacing. Produce the structured report.
阶段0 — 发现(只读)。 先执行
high_level_overview
,然后运行
penpotUtils.tokenOverview()
和
shapeStructure(penpot.currentPage.root, 3)
读取结构。在
RUN_ID
台账中记录已有的内容。 ✋ 检查点:确认范围(新建系统 / 扩展现有系统 / 从设计推断)。
阶段1 — 基础token。 创建
primitives
集合并激活它(调用
set.toggleActive()
—— 新集合默认未激活),然后添加原始色阶、间距刻度(4px网格)、圆角刻度和字号刻度(按小三度比例的字号)。使用
scripts/createTokenSet.js
脚本。 ✋ 检查点:审核基础刻度(
tokenOverview()
+ 命名)。
阶段2 — 语义token。 添加引用基础token的意图别名,分为两个集合(被引用的
primitives
集合必须处于激活状态,否则引用会验证失败):
  • 颜色语义(
    color.action.primary.bg
    →
    {color.blue.500}
    )→ 存入
    modes/light
    ;
  • 模式无关语义(
    spacing.*
    、
    radius.*
    、
    font.*
    )→ 存入
    semantic
    。
scripts/createSemanticTokens.js
脚本会按token类型自动拆分。这是深色模式能作为平行颜色集干净实现的原因。 ✋ 检查点:审核语义映射关系。
阶段3 — 深色模式(可选)。 使用
scripts/createThemes.js
创建平行的
modes/dark
颜色集合(颜色名称与
modes/light
完全一致,值为深色版本);保持
modes/light
为默认激活状态,将切换权交给用户。需覆盖所有
modes/light
中的颜色名称(脚本会返回
missing
缺失列表)。深色模式可以正常工作——当用户激活
modes/dark
时,绑定会按token名称重新解析——但Agent无法在插件中渲染切换效果(
theme.addSet()
不会持久化;插件的读取会有延迟)。用户需要在Penpot的Token面板中手动开启
modes/dark
/ 关闭
modes/light
(见
references/04-themes-modes.md
)。 ✋ 检查点:验证深色模式的
resolvedValue
,恢复浅色模式,并告知用户切换方法。
阶段4 — 应用/推断/绑定。 可以将token绑定到选中内容(
scripts/applyTokensToShapes.js
),从硬编码设计推断token(
scripts/inferTokensFromShapes.js
),或者——核心功能——通过精确值匹配自动将token绑定到所有未绑定元素,免去用户手动操作(
scripts/bindTokensToElements.js
)。这也是主题化的前提:只有当设计中的形状都绑定到token名称时,设计才能跟随浅色/深色切换变化(集合/主题变化时,绑定会按名称重新解析)。请分批应用并验证——
applyToken
是异步操作,单次调用中批量应用会引发竞态/绑定混乱;文本/矩形的填充绑定不稳定,需要验证+重试(见
shared/plugin-api-gotchas.md
)。仅按值匹配是启发式方法:需标记反色的界面控件,供语义角色审核。 ✋ 检查点:审核绑定情况与覆盖率。
阶段5 — 验证。 运行
scripts/validateTokens.js
—— 检查孤立token、未解析引用、偏离网格的间距。生成结构化报告。

7. Critical Rules

7. 关键规则

  1. Primitives → semantic → component. Shapes bind to semantic tokens, never primitives.
  2. All spacing/padding/gap/radius values are multiples of 4px.
  3. Never create a token you can't justify; propose new tokens at a checkpoint, don't auto-create them.
  4. Idempotent: check for an existing set/token by name before adding (no duplicates).
  5. Type sizes follow a Minor Third (1.2) scale unless the brand dictates otherwise.
  6. Do not apply and read back a token in the same
    execute_code
    call (async).
  7. Keep the
    RUN_ID
    ledger updated so a truncated session can resume.
  1. 基础层 → 语义层 → 组件层。形状绑定到语义token,绝不直接绑定基础token。
  2. 所有间距/内边距/间隙/圆角值都是4px的倍数。
  3. 绝不创建无法说明用途的token;在检查点提出新token建议,不要自动创建。
  4. 幂等性:添加前先检查是否已存在同名集合/token(避免重复)。
  5. 除非品牌有特殊要求,字号遵循小三度(1.2)比例。
  6. 不要在同一次
    execute_code
    调用中既应用token又回读结果(异步特性)。
  7. 保持
    RUN_ID
    台账更新,以便会话中断后可以恢复。

8. Domain Architecture

8. 领域架构

Three token tiers (see
shared/tokens-schema.json
):
  • primitives — raw, context-free scale (
    color.blue.500
    ,
    spacing.4
    ,
    radius.md
    ,
    font.size.300
    ). Never bound directly to shapes when a semantic token exists.
  • semantic — intent aliases referencing primitives (
    color.text.default
    →
    {color.gray.900}
    ,
    spacing.inset.md
    →
    {spacing.4}
    ). This is what shapes bind to.
  • components — optional per-component overrides referencing semantic tokens. Create only when a component needs its own surface.
Set layout (see
shared/modes-and-policies.md
): mode-invariant semantics live in
semantic
; colour semantics live in
modes/light
/
modes/dark
(same names in both). Themes are modeled as Penpot token themes (
addTheme({ group, name })
) that toggle the matching
modes/*
set; primitives and the mode-invariant
semantic
set stay constant.
三层token架构(见
shared/tokens-schema.json
):
  • 基础层(primitives) — 原始的、无上下文的刻度(
    color.blue.500
    、
    spacing.4
    、
    radius.md
    、
    font.size.300
    )。当存在语义token时,绝不要直接绑定到形状。
  • 语义层(semantic) — 引用基础token的意图别名(
    color.text.default
    →
    {color.gray.900}
    、
    spacing.inset.md
    →
    {spacing.4}
    )。形状绑定的就是这一层。
  • 组件层(components) — 可选的、引用语义token的单组件覆盖值。仅当组件需要专属表层时创建。
集合布局(见
shared/modes-and-policies.md
):模式无关的语义token存放在
semantic
集合中;颜色语义token存放在
modes/light
/
modes/dark
集合中(两者名称完全一致)。主题以Penpot token主题的形式实现(
addTheme({ group, name })
),用于切换对应的
modes/*
集合;基础集合和模式无关的
semantic
集合保持不变。

9. Modes & Policies

9. 模式与策略

Default review. Creating a new token, building a theme, or applying tokens to shapes all require a checkpoint. The only auto-applicable action (safe set,
shared/modes-and-policies.md
) is replacing a raw value that is exactly equal to an existing token's resolved value with that token.
默认采用审核模式。创建新token、构建主题或将token应用到形状都需要经过检查点。唯一可自动执行的操作(安全操作,见
shared/modes-and-policies.md
)是:将与现有token解析后值完全相等的原始值替换为该token。

10. State Management

10. 状态管理

Ledger keys under
RUN_ID
(see
shared/state-management.md
):
phase
,
created:[{kind:'set'|'token'|'theme', name, id}]
,
proposed:[...]
,
applied:[...]
. Re-derive reality with
tokenOverview()
after truncation before continuing.
RUN_ID
下的台账键(见
shared/state-management.md
):
phase
、
created:[{kind:'set'|'token'|'theme', name, id}]
、
proposed:[...]
、
applied:[...]
。会话中断后继续操作前,请用
tokenOverview()
重新获取实际状态。

11. User Checkpoints

11. 用户检查点

After phaseArtifacts shownWhat we ask
0 Discoveryexisting tokens summaryNew / extend / infer?
1 Primitives
tokenOverview()
of primitives
Approve scales & naming?
2 Semanticsemantic→primitive mappingApprove intent mapping?
3 Themesresolved values per themeApprove theme switch?
4 Apply/Inferbefore/after on a sampleApprove bindings?
阶段完成后展示产物我们确认的内容
0 发现阶段现有token汇总新建 / 扩展 / 推断?
1 基础token阶段基础token的
tokenOverview()
结果
是否认可刻度与命名?
2 语义token阶段语义→基础映射关系是否认可意图映射?
3 主题阶段各主题的解析后值是否认可主题切换?
4 应用/推断阶段样本的前后对比是否认可绑定结果?

12. Naming Conventions

12. 命名规范

Dot-notation per
shared/naming-conventions.md
: sets are
primitives
/
semantic
(mode-invariant) /
modes/light
+
modes/dark
(colour) / optional
components
; tokens are lowercase dot paths; themes grouped
mode
with names
Light
/
Dark
/
High Contrast
.
遵循
shared/naming-conventions.md
的点分命名法:集合名为
primitives
/
semantic
(模式无关) /
modes/light
+
modes/dark
(颜色) / 可选的
components
;token为小写点路径;主题分组为
mode
,名称为
Light
/
Dark
/
High Contrast
。

13. Anti-Rationalization Table

13. 反合理化对照表

Excuse the LLM makesWhy it's wrongDeterministic countermeasure
"I'll hardcode this hex now and tokenize later."Hardcoded values break theming and governance; "later" never comes.Stop. Read
tokenOverview()
, bind to a semantic token, or propose one for review.
"I'll bind shapes straight to a primitive to save a step."Primitives can't switch per theme; dark mode breaks.Bind to a semantic token that references the primitive.
"This spacing is 18px, close enough."Off-grid values erode rhythm and fail governance.Round to the nearest 4px-grid token (16 or 20). Document any exception only with human approval.
"I'll create a dozen tokens up front to be safe."Unused/orphan tokens are debt.Create only what's needed now; propose the rest at a checkpoint.
LLM常找的借口错误原因确定性应对措施
"我先硬编码这个色值,之后再token化。"硬编码值会破坏主题化和治理;"之后"永远不会来。停止操作。读取
tokenOverview()
,绑定到语义token,或提出新token供审核。
"我直接把形状绑定到基础token,省一步。"基础token不能按主题切换;深色模式会失效。绑定到引用该基础token的语义token。
"这个间距是18px,差不多就行。"偏离网格的值会破坏节奏,且不符合治理要求。四舍五入到最近的4px网格token(16或20)。所有例外都需经人工批准并记录。
"我先创建十几个token备用,更稳妥。"未使用的/孤立的token是技术债务。只创建当前需要的内容;其余的在检查点提出建议。

14. Helper Code Snippets

14. 辅助代码片段

js
// 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 };
js
// 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 };
js
// 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 };
js
// 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. Reference Resources

15. 参考资源

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

16. Supporting Files

16. 配套文件

references/
FileLoaded for
01-discovery.md
Phase 0 read-only inventory
02-token-architecture.md
tiers, scales, type ratio
03-infer-from-design.md
building tokens from a hardcoded design
04-themes-modes.md
light/dark theme modeling
05-naming.md
token naming specifics
06-anti-rationalization.md
governance excuses + countermeasures
07-error-recovery.md
common failures & fixes
scripts/
FilePurpose
inspectFileStructure.js
read pages/library/tokens
createTokenSet.js
idempotent primitives set + tokens
createSemanticTokens.js
semantic aliases referencing primitives
inferTokensFromShapes.js
propose tokens from raw values
applyTokensToShapes.js
bind tokens to a selection
bindTokensToElements.js
auto-bind tokens to unbound elements by value (chunked + verify) — enables theming
createThemes.js
light/dark themes
validateTokens.js
orphans, unresolved refs, off-grid
Doctrine paths.
shared/…
and
policies/…
resolve inside this bundle in native installs (vendored by the installer); in a Claude Code plugin install they live at the plugin root —
${CLAUDE_PLUGIN_ROOT}/shared/…
, two directories up from this file.
references/
文件加载用途
01-discovery.md
阶段0 只读清单
02-token-architecture.md
层级、刻度、字号比例
03-infer-from-design.md
从硬编码设计构建token
04-themes-modes.md
浅色/深色主题建模
05-naming.md
token命名细节
06-anti-rationalization.md
治理借口与应对措施
07-error-recovery.md
常见故障与修复方法
scripts/
文件用途
inspectFileStructure.js
读取页面/库/token
createTokenSet.js
幂等创建基础token集合与token
createSemanticTokens.js
创建引用基础token的语义别名
inferTokensFromShapes.js
从原始值提出token建议
applyTokensToShapes.js
将token绑定到选中内容
bindTokensToElements.js
按值自动绑定token到未绑定元素(分批+验证)—— 实现主题化
createThemes.js
浅色/深色主题
validateTokens.js
检查孤立token、未解析引用、偏离网格
规则文件路径:原生安装时,
shared/…
和
policies/…
位于本包内部(由安装程序内置);在 Claude Code 插件安装场景下,它们位于插件根目录——
${CLAUDE_PLUGIN_ROOT}/shared/…
,即本文件的上两级目录。