penpot-build-screen
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesepenpot-build-screen — brief to on-system screen
penpot-build-screen — 从需求说明到符合系统规范的界面
1. Title + How it works
1. 标题与工作原理
penpot-build-screenexecute_codeexport_shapepenpotUtils.shapeStructureshared/penpot-mcp-tool-reference.mdpenpot-foundationspenpot-build-screenexecute_codeexport_shapepenpotUtils.shapeStructureshared/penpot-mcp-tool-reference.mdpenpot-foundations2. The One Rule That Matters Most
2. 最重要的核心规则
Reuse the system; build incrementally. Prefer existing components and semantic tokens over raw
shapes. Build one section, checkpoint with an , then continue. If no system exists,
bootstrap only a minimal one (hand off to for anything substantial).
export_shapepenpot-foundations复用系统,增量构建。 优先使用现有组件和语义 tokens,而非原始形状。构建一个段落,用 设置检查点,然后继续。如果不存在设计系统,仅搭建最小化版本(任何实质性的系统搭建都交由 处理)。
export_shapepenpot-foundations3. Penpot MCP Tool Reference
3. Penpot MCP 工具参考
Full surface: . Key calls: /
for the screen and sections; + to reuse components;
for token binding; at checkpoints.
shared/penpot-mcp-tool-reference.mdpenpot.createBoard()addFlexLayout()penpot.library.local.componentscomp.instance()shape.applyTokenexport_shape('selection'|'page')完整接口说明:。核心调用:
shared/penpot-mcp-tool-reference.md- /
penpot.createBoard():用于创建界面和段落addFlexLayout() - +
penpot.library.local.components:复用组件comp.instance() - :绑定 tokens
shape.applyToken - 检查点使用
export_shape('selection'|'page')
4. Plugin API Essentials
4. 插件 API 核心要点
Gotcha numbers refer to .
shared/plugin-api-gotchas.md- Screen and sections are Boards with flex layout; compose with append order + gaps + align/justify.
- Reuse components via ; don't redraw system parts as raw shapes.
component.instance() - #3 text auto-sizing — set to
growType/auto-widthAFTER anyauto-height(which forcesresize()).fixed - #4 flex overrides child x/y — use for stretch/margins.
layoutChild - Bind colors/spacing/radius/type to semantic tokens, never hardcoded.
- #11 every new Board is born with an OPAQUE WHITE fill — this skill's critical failure mode. ships
createBoard(); left in place, a structural wrapper's square white corners poke out behind rounded children (radius looks broken), and layout boards keeping the literal white never flip in dark mode (no token, off-system). Fill policy: decide per board — a structural board (layout-only chrome: sections, rows, wrappers) getsfills = [{ fillColor: "#FFFFFF", fillOpacity: 1 }]; a surface (screen bg, card, sheet, button) binds aboard.fills = []token, never a literal. Default layout containers to transparent (color.bg.*).shared/modes-and-policies.md - #13b exact font match — ;
penpot.fonts.all.find(f => f.name === "…")is a substring search.findByName - #15 — set only AFTER
layoutChild.*;appendChildis async (two-call protocol: create+open, then assertopenPagebefore anycurrentPage.id).createBoard - #16 — run after every section (fill-sized children can come back with
clearFlip; canonical helper inflipX = true).shared/visual-effects.md - #17 — before reading geometry (replaces the sleep-100ms idiom).
await board.waitForLayoutUpdate() - #18 — image fills: , verified in the next call — see
const img = await penpot.uploadMediaUrl(name, url); shape.fills = [{ fillOpacity: 1, fillImage: img }].shared/visual-effects.md - Verify unfamiliar signatures with first.
penpot_api_info
注意事项编号对应 中的条目。
shared/plugin-api-gotchas.md- 界面和段落都是带有 flex 布局的 Board;通过追加顺序 + 间距 + 对齐/分布来组合。
- 通过 复用组件;不要将系统组件重绘为原始形状。
component.instance() - #3 文本自动调整大小 — 在任何 操作(会强制设为固定大小)之后,将
resize()设置为growType/auto-width。auto-height - #4 flex 布局会覆盖子元素的 x/y 坐标 — 使用 来设置拉伸/边距。
layoutChild - 将颜色/间距/圆角/字体绑定到语义 tokens,绝对不要硬编码。
- #11 每个新 Board 默认带有不透明白色填充——这是本技能的关键失败点。 默认会设置
createBoard();如果保留这个设置,结构包装器的白色方角会从圆角子元素后面露出来(圆角看起来像坏了),而且布局 Board 保持字面白色的话,在深色模式下不会切换(没有 token 绑定,不符合系统规范)。填充策略: 按 Board 类型决定——结构型 Board(仅用于布局的容器:段落、行、包装器)设置fills = [{ fillColor: "#FFFFFF", fillOpacity: 1 }];表面型 Board(界面背景、卡片、面板、按钮)绑定board.fills = []类型的 token,绝对不要用字面量值。布局容器默认设为透明(参考color.bg.*)。shared/modes-and-policies.md - #13b 精确字体匹配 — 使用 ;
penpot.fonts.all.find(f => f.name === "…")是子字符串搜索。findByName - #15 — 仅在 之后设置
appendChild;layoutChild.*是异步的(两步协议:创建+打开,然后在任何openPage操作前断言createBoard)。currentPage.id - #16 — 每个段落完成后运行 (填充大小的子元素可能会返回
clearFlip;标准辅助方法见flipX = true)。shared/visual-effects.md - #17 — 读取几何属性前先 (替代 sleep 100ms 的旧写法)。
await board.waitForLayoutUpdate() - #18 — 图片填充:,在下一次调用中验证——参考
const img = await penpot.uploadMediaUrl(name, url); shape.fills = [{ fillOpacity: 1, fillImage: img }]。shared/visual-effects.md - 遇到不熟悉的接口签名,先使用 确认。
penpot_api_info
5. Token-Aware Brief Contract
5. 支持 Token 的需求说明规范
- Context — product, audience, platform, brand mood.
- Objective — the single screen and its primary user goal.
- Inputs — content/sections, existing tokens & components, style profile, viewport size.
- Constraints — use existing components; on-grid spacing; semantic tokens only; forbidden patterns; none of the named tells in §7; with strict anti-slop on, none of the keys the direction step refused (
shared/design-quality.md§1).shared/anti-slop.md - Acceptance Criteria — clear hierarchy; 4px rhythm; AA contrast; reuses system; responsive intent stated; design-quality score ≥ 3 on all seven axes (§8) or the weak axes explicitly presented; with strict anti-slop on, slop score ≤ 35 (
shared/design-quality.mddiagnose).penpot-anti-slop
Act as a senior product/visual designer who makes deliberate aesthetic decisions, not generic ones.
- 背景 — 产品、受众、平台、品牌调性。
- 目标 — 单个界面及其主要用户目标。
- 输入 — 内容/段落、现有 tokens 与组件、风格配置、视口大小。
- 约束 — 使用现有组件;间距对齐网格;仅使用语义 tokens;禁用模式;不得出现 第7节中列出的问题;开启严格 anti-slop 时,不得包含方向步骤拒绝的关键词(
shared/design-quality.md第1节)。shared/anti-slop.md - 验收标准 — 清晰的层级;4px 网格节奏;AA 级对比度;复用设计系统;明确说明响应式意图;所有七个维度的设计质量评分 ≥ 3(第8节),否则需明确说明薄弱维度;开启严格 anti-slop 时,slop 评分 ≤ 35(通过
shared/design-quality.md诊断)。penpot-anti-slop
扮演资深产品/视觉设计师的角色,做出深思熟虑的美学决策,而非泛泛之选。
6. Mandatory Workflow
6. 强制工作流
Visual self-review (mandatory): before every ✋ checkpoint that shows visual work, run the export → look → fix loop from— export the unit you just built, inspect the image yourself against the checklist, fix visible defects (max 2 iterations), and present that same export with any remaining defects named.shared/visual-self-review.md
Phase 0 — Discovery. ; inventory tokens/components (); analyze the brief (); pick a style profile () and a named screen skeleton ( §5) — check the ledger for prior screens this session and apply the variety rule (differ on ≥ 1 axis, say which). Anti-slop opt-in: read the stored preference ( → ); if it is unset and the brief doesn't answer it, ask the question in §0 (user's language, once per file) and store the answer. When it is , run the direction step ( ) before choosing profile and skeleton, and fold its refused keys into the Constraints. ✋ Checkpoint: confirm brief + style + skeleton + section list (+ the direction block when strict mode is on).
high_level_overviewscripts/setupOrReuseSystem.jsreferences/01-brief-analysis.mdreferences/02-style-profiles.mdshared/design-quality.mdpenpot-anti-slopscripts/antiSlopPrefs.jsshared/anti-slop.mdonpenpot-anti-slopreferences/02-direction-playbook.mdPhase 1 — Frame. Create the screen Board with (idempotent; returns ids; binds bg/gap/padding tokens). Set viewport size. ✋ Checkpoint.
scripts/createScreenFrame.jsPhase 2..N — Sections. Build each section as a tokenized flex Board reusing components (). One section per call. ✋ Checkpoint after each ().
scripts/buildSection.jsexecute_codeexport_shapePhase N+1 — Assemble & critique. composes sections; checks layout coverage (every board has flex/grid), token binding, on-grid spacing, naming. A non-empty fails the gate — add a layout to each flagged board before reporting done. Then run the scored critique (): score the final export 1–5 on the seven axes of §8; any axis < 3 → targeted revision (max 2 passes), then emit the design-quality report (Markdown + JSON per , mirrored to the ledger). Strict mode on: run diagnose on the screen board and include its slop score in the report (it feeds the axis); outside a workflow, a score > 35 means presenting its top fixes, not declaring done. Report.
scripts/assembleScreen.jsscripts/auditScreenQuality.jsboardsWithoutLayoutreferences/05-critique-framework.mdshared/design-quality.mdshared/report-schemas/design-quality-report.schema.jsonpenpot-anti-slopdistinctiveness视觉自查(强制要求): 在每个展示视觉成果的 ✋ 检查点之前, 执行中的导出 → 检查 → 修复循环——导出你刚构建的单元, 对照检查清单自行检查图片,修复可见缺陷(最多2次迭代), 然后提交该导出结果,并说明剩余的缺陷。shared/visual-self-review.md
阶段 0 — 调研发现。 生成 ;盘点 tokens/组件();分析需求说明();选择风格配置()和指定的界面骨架( 第5节)——检查本次会话的台账中之前的界面,应用多样性规则(至少在1个维度上有所不同,并说明是哪个维度)。Anti-slop 启用: 读取存储的偏好设置( → );如果未设置且需求说明中没有相关内容,用 第0节中的问题询问用户(使用用户的语言,每个文件问一次)并存储答案。当设置为 时,在选择风格配置和骨架之前,运行方向步骤( ),并将其拒绝的关键词加入约束条件。✋ 检查点:确认需求说明 + 风格 + 骨架 + 段落列表(严格模式下还要加上方向块)。
high_level_overviewscripts/setupOrReuseSystem.jsreferences/01-brief-analysis.mdreferences/02-style-profiles.mdshared/design-quality.mdpenpot-anti-slopscripts/antiSlopPrefs.jsshared/anti-slop.mdonpenpot-anti-slopreferences/02-direction-playbook.md阶段 1 — 框架搭建。 使用 创建界面 Board(幂等;返回 id;绑定背景/间距/内边距 tokens)。设置视口大小。✋ 检查点。
scripts/createScreenFrame.js阶段 2..N — 段落构建。 将每个段落构建为绑定 token 的 flex Board,复用组件()。每次 调用仅构建一个段落。每个段落完成后设置 ✋ 检查点(使用 )。
scripts/buildSection.jsexecute_codeexport_shape阶段 N+1 — 组装与评审。 组合各个段落; 检查布局覆盖率(每个 Board 都有 flex/grid 布局)、token 绑定、网格对齐间距、命名规范。如果 非空,则不通过门禁——在报告完成前,为每个标记的 Board 添加布局。然后运行评分评审():按照 第8节的七个维度为最终导出结果打 1–5 分;任何维度 < 3 → 针对性修订(最多2轮),然后生成设计质量报告(按照 格式的 Markdown + JSON,同步到台账中)。严格模式开启时: 对界面 Board 运行 诊断,并将 slop 评分纳入报告(它会影响「独特性」维度);在工作流之外,评分 > 35 意味着需要展示主要修复方案,而非宣布完成。提交报告。
scripts/assembleScreen.jsscripts/auditScreenQuality.jsboardsWithoutLayoutreferences/05-critique-framework.mdshared/design-quality.mdshared/report-schemas/design-quality-report.schema.jsonpenpot-anti-slop7. Critical Rules
7. 关键规则
- Flex by default — every container is a layout Board. The instant you create a Board, give it a
flex () or grid (
addFlexLayout()) layout before appending children — the screen root, every section, AND every nested grouping (card, row, list, stat cluster, form field, button group). NEVER arrange UI elements with absoluteaddGridLayout()/x, and NEVER use a plain Group to lay out UI. A Board without a layout is a bug; the Phase N+1 audit (y) fails the build if any exist.boardsWithoutLayout - Reuse existing components before creating raw shapes.
- Bind to semantic tokens; never hardcode color/spacing/radius/type.
- One section per call; checkpoint with .
export_shape - All spacing on the 4px grid; consistent rhythm.
- Don't bootstrap a full design system here — hand off to .
penpot-foundations - State responsive intent (sizing: fill/auto/fix) explicitly.
- 默认使用 flex 布局——每个容器都是带布局的 Board。 创建 Board 的瞬间,就要在追加子元素之前为其添加 flex()或 grid(
addFlexLayout())布局——界面根容器、每个段落、以及每个嵌套分组(卡片、行、列表、统计集群、表单字段、按钮组)都是如此。绝对不要用绝对addGridLayout()/x坐标排列 UI 元素,也绝对不要用普通 Group 来布局 UI。没有布局的 Board 就是 bug;阶段 N+1 的审计(y)如果发现任何无布局的 Board,会判定构建失败。boardsWithoutLayout - 优先复用现有组件,再考虑创建原始形状。
- 绑定语义 tokens;绝对不要硬编码颜色/间距/圆角/字体。
- 每次调用仅构建一个段落;用 设置检查点。
export_shape - 所有间距对齐 4px 网格;保持一致的节奏。
- 不要在这里搭建完整的设计系统——交由 处理。
penpot-foundations - 明确说明响应式意图(大小模式:fill/auto/fix)。
8. Domain Architecture
8. 领域架构
A screen = a root flex Board (column) → section Boards (each its own flex) → component instances +
tokenized primitives. Composition follows a clear visual hierarchy: primary action prominent, content
grouped, whitespace on the spacing scale, type from the semantic type tokens.
界面 = 根 flex Board(纵向排列)→ 段落 Board(每个都有自己的 flex 布局)→ 组件实例 + 绑定 token 的基础元素。组合遵循清晰的视觉层级:主要操作突出,内容分组,留白遵循间距尺度,字体使用语义字体 tokens。
9. Modes & Policies
9. 模式与策略
Default review. Geometry/layout changes always require a checkpoint ().
shared/modes-and-policies.md默认评审模式。几何/布局变更始终需要设置检查点()。
shared/modes-and-policies.md10. State Management
10. 状态管理
Ledger under : , , , , , (the §8 report object), (, , — when strict mode is on). The opt-in itself is file-wide plugin data → . Resume by re-reading structure.
RUN_IDphasescreenBoardIdsections:[{name,id,done}]styleProfileskeletondesignQualityantiSlopprefdirectionreports[]penpot-aiprefs.antiSlopRUN_IDphasescreenBoardIdsections:[{name,id,done}]styleProfileskeletondesignQualityantiSlopprefdirectionreports[]penpot-aiprefs.antiSlop11. User Checkpoints
11. 用户检查点
| After phase | Artifacts | Ask |
|---|---|---|
| 0 (pref unset) | the anti-slop opt-in question ( | Avoid the generic-AI look? |
| 0 | brief + style + skeleton + sections (+ direction block if strict) | Approve direction? |
| 1 | empty frame | Approve frame/viewport? |
| each section | section | Approve section? |
| assemble | full screen | Approve / iterate? |
| 阶段完成后 | 产出物 | 询问内容 |
|---|---|---|
| 0(偏好未设置) | anti-slop 启用问题( | 是否要避免通用AI风格? |
| 0 | 需求说明 + 风格 + 骨架 + 段落(严格模式下含方向块) | 是否确认设计方向? |
| 1 | 空框架 | 是否确认框架/视口? |
| 每个段落完成后 | 段落 | 是否确认该段落? |
| 组装完成 | 完整界面 | 是否确认 / 需要迭代? |
12. Naming Conventions
12. 命名规范
shared/naming-conventions.mdheadermainsectionnavbuttonDashboard参考 :图层使用语义 HTML 命名(、、、、);界面 Board 以视图命名(如 )。
shared/naming-conventions.mdheadermainsectionnavbuttonDashboard13. Anti-Rationalization Table
13. 反合理化对照表
| Excuse | Why it's wrong | Countermeasure (halt) |
|---|---|---|
| "I'll draw a quick button instead of using the component." | Raw shapes drift from the system. | Instantiate the existing component; reuse beats reinvention. |
| "Hardcode this spacing/color, faster." | Breaks rhythm/theming/governance. | Bind to semantic tokens; snap spacing to 4px. |
| "Generate the whole screen in one go." | One-shot output is generic and unauditable. | Build section by section with checkpoints. |
| "Centered cards + generic gradient looks fine." | Distributive convergence → bland, off-brand UI. | Apply a deliberate style profile; justify aesthetic choices. |
| "I'll skip the anti-slop question, the user is busy." | Strict mode is the user's choice; guessing either way is wrong. | Read |
| "I'll set up tokens here real quick." | Foundations belong in their skill. | Hand off to |
| "I'll just position these with x/y, it's faster." | Absolute coords don't resize, reflow, or theme; off-system. | Wrap them in a flex/grid Board; order by append + gaps/align. |
| "A plain Group is enough to bunch these together." | Groups don't lay out — they only bound. | Use a Board with |
| "This little container doesn't need a layout." | Every UI container needs one for rhythm + responsiveness. | Add flex/grid before appending children — no exceptions. |
| 借口 | 错误原因 | 应对措施(立即停止) |
|---|---|---|
| “我就快速画个按钮,不用组件了。” | 原始形状会偏离设计系统。 | 实例化现有组件;复用胜于重造。 |
| “硬编码这个间距/颜色更快。” | 破坏节奏/主题/治理规范。 | 绑定语义 tokens;间距对齐 4px 网格。 |
| “一次性生成整个界面就行。” | 一次性输出的内容泛化且不可审计。 | 逐段构建,设置检查点。 |
| “居中卡片 + 通用渐变看起来不错。” | 趋同设计 → 平淡、不符合品牌的 UI。 | 应用明确的风格配置;为美学决策提供依据。 |
| “用户很忙,我就跳过 anti-slop 问题了。” | 严格模式是用户的选择;擅自猜测是错误的。 | 读取 |
| “我很快就能在这里搭好 tokens。” | 基础系统属于对应技能的范畴。 | 任何非琐碎的系统搭建都交由 |
| “我用 x/y 定位这些元素更快。” | 绝对坐标无法自适应大小、重排或主题切换;不符合系统规范。 | 将它们包裹在 flex/grid Board 中;通过追加顺序 + 间距/对齐来排列。 |
| “用普通 Group 把这些元素组在一起就行。” | Group 不负责布局——仅做边界包裹。 | 使用带有 |
| “这个小容器不需要布局。” | 每个 UI 容器都需要布局以保证节奏和响应式能力。 | 在追加子元素前添加 flex/grid 布局——没有例外。 |
14. Helper Code Snippets
14. 辅助代码片段
js
// Screen frame (Phase 1)
const screen = penpot.createBoard();
screen.name = "Dashboard";
screen.resize(1440, 1024);
const flex = screen.addFlexLayout();
flex.dir = "column";
flex.horizontalSizing = "fix"; flex.verticalSizing = "auto";
penpot.currentPage.root.appendChild(screen); // append first (#7); layoutChild only after append (#15)
// SPACING: bind tokens, never literals (#8: padding tokens bind on ≥ 2.17; numeric mirror + ledger exception otherwise)
const gap = penpotUtils.findTokenByName("spacing.24");
if (gap) screen.applyToken(gap, ["rowGap"]); else flex.rowGap = 24;
const pad = penpotUtils.findTokenByName("spacing.32");
const FLEX_PROP = { paddingTop: "topPadding", paddingBottom: "bottomPadding", paddingLeft: "leftPadding", paddingRight: "rightPadding" };
for (const side of Object.keys(FLEX_PROP)) {
try { if (!pad) throw new Error("no token"); screen.applyToken(pad, [side]); }
catch (e) { flex[FLEX_PROP[side]] = pad ? Number(pad.resolvedValue) : 32; } // record { kind: "padding-mirrors-token" } in the ledger
}
// FILL POLICY (gotchas #11): the screen root is THE one surface — bind its bg to a token so it flips in
// dark mode. Every section nested inside stays transparent (buildSection.js clears their default white).
screen.fills = []; // drop Penpot's default opaque #FFFFFF
const bg = penpotUtils.findTokenByName("color.bg.default");
if (bg) screen.applyToken(bg, ["fill"]); // bound surface, not a literal
storage.bs = { screenBoardId: screen.id };
return { screen: screen.id, bgBound: !!bg, gapBound: !!gap, padBound: !!pad };js
// Screen frame (Phase 1)
const screen = penpot.createBoard();
screen.name = "Dashboard";
screen.resize(1440, 1024);
const flex = screen.addFlexLayout();
flex.dir = "column";
flex.horizontalSizing = "fix"; flex.verticalSizing = "auto";
penpot.currentPage.root.appendChild(screen); // append first (#7); layoutChild only after append (#15)
// SPACING: bind tokens, never literals (#8: padding tokens bind on ≥ 2.17; numeric mirror + ledger exception otherwise)
const gap = penpotUtils.findTokenByName("spacing.24");
if (gap) screen.applyToken(gap, ["rowGap"]); else flex.rowGap = 24;
const pad = penpotUtils.findTokenByName("spacing.32");
const FLEX_PROP = { paddingTop: "topPadding", paddingBottom: "bottomPadding", paddingLeft: "leftPadding", paddingRight: "rightPadding" };
for (const side of Object.keys(FLEX_PROP)) {
try { if (!pad) throw new Error("no token"); screen.applyToken(pad, [side]); }
catch (e) { flex[FLEX_PROP[side]] = pad ? Number(pad.resolvedValue) : 32; } // record { kind: "padding-mirrors-token" } in the ledger
}
// FILL POLICY (gotchas #11): the screen root is THE one surface — bind its bg to a token so it flips in
// dark mode. Every section nested inside stays transparent (buildSection.js clears their default white).
screen.fills = []; // drop Penpot's default opaque #FFFFFF
const bg = penpotUtils.findTokenByName("color.bg.default");
if (bg) screen.applyToken(bg, ["fill"]); // bound surface, not a literal
storage.bs = { screenBoardId: screen.id };
return { screen: screen.id, bgBound: !!bg, gapBound: !!gap, padBound: !!pad };15. Reference Resources
15. 参考资源
- ,
penpot_api_info('Board'),penpot_api_info('LibraryComponent').penpot_api_info('Text')
- 、
penpot_api_info('Board')、penpot_api_info('LibraryComponent')。penpot_api_info('Text')
16. Supporting Files
16. 支持文件
references/: , , , , , , ; effects, image placeholders, gradients: .
scripts/: , (Phase 1 frame: idempotent, token-bound bg/gap/padding, ledger), , , .
01-brief-analysis.md02-style-profiles.md03-layout-composition.md04-component-recipes.md05-critique-framework.md06-anti-rationalization.md07-error-recovery.mdshared/visual-effects.mdsetupOrReuseSystem.jscreateScreenFrame.jsbuildSection.jsassembleScreen.jsauditScreenQuality.jsDoctrine paths. and resolve inside this bundle in native installs (vendored by the installer); in a Claude Code plugin install they live at the plugin root — , two directories up from this file.
shared/…policies/…${CLAUDE_PLUGIN_ROOT}/shared/…references/:、、、、、、;效果、图片占位符、渐变:。
scripts/:、(阶段1框架:幂等、绑定 token 的背景/间距/内边距、台账记录)、、、。
01-brief-analysis.md02-style-profiles.md03-layout-composition.md04-component-recipes.md05-critique-framework.md06-anti-rationalization.md07-error-recovery.mdshared/visual-effects.mdsetupOrReuseSystem.jscreateScreenFrame.jsbuildSection.jsassembleScreen.jsauditScreenQuality.js文档路径说明。 和 在原生安装中位于此包内(由安装程序内置);在 Claude Code 插件安装中,它们位于插件根目录——,即此文件的上两级目录。
shared/…policies/…${CLAUDE_PLUGIN_ROOT}/shared/…