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`、トークンの作成・適用 API が含まれます。

インストール

コマンドをコピーしてターミナルで実行します。

$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) でシェイプに適用します。3段階(プリミティブ → セマンティック → コンポーネント)で機能し(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}) はオブジェクト引数を取ります。新しいセットは非アクティブです(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。(キャメルケースや複数形に注意してください。border-radius や font-size ではありません。)
  • #2 非同期のトークン適用 — このスキルで最も重大な失敗要因です。 shape.applyToken(token, properties) は非同期(約 100 ms)で、名前によってバインドします(アクティブなセット/テーマが変わるとバインディングが再解決されます。これによってダークモードが機能します)。1 回の execute_code 呼び出しで適用し、後続の呼び出しで shape.tokens を検証します。1 回の呼び出しで大量に適用してはいけません。 1 つのループで数百の applyToken を実行すると競合が発生し、バインディングが乱れます。1 回の呼び出しにつき約 25~40 個のシェイプに分けて適用し、各チャンクを検証して、適用漏れがあれば再試行します。テキスト/長方形の塗りのバインディングは特に不安定です(ボードは安定しています)。バインディングは保持されます。誤ったバインディングは正しいトークンを適用して上書きし、fills 経由でクリアしようとしないでください。
  • 不慣れなメンバーは、まず penpot_api_info('TokenSet')/penpot_api_info('Token') で確認してください。

5. トークン対応ブリーフの契約

変更を加える前に、依頼内容を次のように言い換えます:

  • コンテキスト — 製品、ブランド、既存のシステム(あれば)、ライト/ダークの要件。
  • 目的 — 単一かつ具体的な目的(例:「プリミティブとセマンティックの色/間隔トークン、およびダークテーマを作成する」)。
  • 入力 — 既存のトークン、ブランドパレット、文字サイズスケールの比率(デフォルトは Minor Third 1.2)、間隔グリッド(デフォルトは 4px)。
  • 制約 — ハードコードされた値を使用しないこと。セマンティックトークンはプリミティブを参照すること。間隔は 4px グリッドに合わせること。
  • 受け入れ基準 — すべてのトークンが解決されること。セマンティック層がプリミティブを参照すること。すべての間隔が 4px の倍数であること。(依頼された場合)ダークテーマが機能すること。

値を決してハードコードしない、シニアのデザインシステムエンジニアとして行動してください。

6. 必須ワークフロー

フェーズ 0 — 調査(読み取り専用)。 high_level_overview、続いて penpotUtils.tokenOverview() と shapeStructure(penpot.currentPage.root, 3) の読み取りを実行します。既存の内容を RUN_ID 台帳に記録します。 ✋ チェックポイント:対象範囲(新規システム、拡張、デザインからの推測)を確認します。

フェーズ 1 — プリミティブ。 primitives セットを作成して有効化し(新しいセットは無効状態で作成されます)、生のカラーランプ、スペーシングスケール(4px グリッド)、角丸スケール、タイポグラフィスケールを追加します(フォントサイズには短三度を使用します)。scripts/createTokenSet.js を使用します。 ✋ チェックポイント:プリミティブのスケールを確認します(tokenOverview() と命名)。

フェーズ 2 — セマンティック。 プリミティブを参照する意図別のエイリアスを追加し、2 つのセットに振り分けます(参照先の primitives セットが有効でない場合、参照の検証に失敗します)。

  • 色のセマンティクス(color.action.primary.bg → {color.blue.500})→ modes/light;
  • モードに依存しないセマンティクス(spacing.*、radius.*、font.*)→ semantic。

scripts/createSemanticTokens.js はトークンの種類に応じてこの振り分けを行います。これにより、ダークモードをクリーンな並行カラーセットとして実現できます。✋ チェックポイント:セマンティックマッピングを確認します。

フェーズ 3 — ダークモード(任意)。 scripts/createThemes.js で、modes/light と同じ色名とダークカラー値を持つ並行した modes/dark カラーセットを作成します。デフォルトとして modes/light を有効のままにし、切り替え方法をユーザーに伝えます。modes/light の色名をすべて網羅します(スクリプトは missing リストを返します)。ダークモードは機能します。ユーザーが modes/dark を有効にすると、バインディングはトークンの名前によって再解決されます。ただし、エージェントはプラグインから切り替えを描画できません(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. ドメインアーキテクチャ

3 つのトークン階層(shared/tokens-schema.json を参照):

  • プリミティブ — コンテキストに依存しない生のスケールです(color.blue.500、spacing.4、radius.md、font.size.300)。セマンティックトークンが存在する場合、シェイプに直接割り当ててはいけません。
  • セマンティック — プリミティブを参照する意図のエイリアスです(color.text.default → {color.gray.900}、spacing.inset.md → {spacing.4})。シェイプが割り当てるのはこれです。
  • コンポーネント — セマンティックトークンを参照する、コンポーネントごとの任意のオーバーライドです。コンポーネント独自のサーフェスが必要な場合にのみ作成します。

セットの構成(shared/modes-and-policies.md を参照):モードに依存しないセマンティクスは semantic に置きます。色の セマンティクスは modes/light / modes/dark に置きます(両方で同じ名前を使用)。テーマは Penpot トークン テーマ(addTheme({ group, name }))としてモデル化し、対応する modes/* セットを切り替えます。プリミティブと モードに依存しない semantic セットは一定のままです。

9. モードとポリシー

デフォルトは レビュー です。新しいトークンの作成、テーマの構築、シェイプへのトークンの適用には、すべてチェックポイントが必要です。自動適用できる唯一のアクション(安全なセットは 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 調査既存トークンの概要新規作成/拡張/推定のどれにしますか?
1 プリミティブプリミティブの tokenOverview()スケールと命名を承認しますか?
2 セマンティックセマンティックからプリミティブへのマッピング意図のマッピングを承認しますか?
3 テーマテーマごとの解決済み値テーマの切り替えを承認しますか?
4 適用/推定サンプルの適用前/適用後バインディングを承認しますか?

12. 命名規則

shared/naming-conventions.md に従ったドット記法:セットは primitives / semantic(モードに依存しない)/ modes/light + modes/dark(色)/ 任意の components とします。トークンは小文字のドットパスとし、テーマは mode グループに Light / Dark / High Contrast という名前でまとめます。

13. 合理化を防ぐための表

LLM がする言い訳間違っている理由確実な対策
「今はこの 16 進数をハードコードして、後でトークン化します。」ハードコードされた値はテーマ設定とガバナンスを損ないます。「後で」は決して訪れません。そこで止めます。tokenOverview() を読み、セマンティックトークンを割り当てるか、レビュー用に提案します。
「手間を省くため、シェイプをプリミティブに直接割り当てます。」プリミティブはテーマごとに切り替えられず、ダークモードが崩れます。プリミティブを参照するセマンティックトークンを割り当てます。
「この間隔は 18px ですが、十分近いです。」グリッドから外れた値はリズムを損ない、ガバナンスに適合しません。最も近い 4px グリッドのトークン(16 または 20)に丸めます。例外は人間の承認を得た場合にのみ記録します。
「念のため、最初にトークンを 12 個作成します。」未使用または孤立したトークンは負債になります。今必要なものだけを作成し、残りはチェックポイントで提案します。

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孤立したトークン、未解決の参照、グリッドからの逸脱

Doctrine のパス。 shared/… と policies/… は、ネイティブインストールではこのバンドル内に解決されます(インストーラーによってベンダー化されます)。Claude Code プラグインのインストールでは、このファイルから 2 つ上のディレクトリにあるプラグインルート、${CLAUDE_PLUGIN_ROOT}/shared/… に置かれます。

コメント