penpot-design-md について
penpot-design-mdは、Penpotのデザインファイルを、人やコーディングエージェント向けの持ち運べるDESIGN.mdにまとめるスキルです。実際に読み取ったトークン、コンポーネントのスタイル、視覚的特徴を記録し、キャンバスは変更しません。
主な機能
- 01デザイントークンとライブラリアセットの抽出
- 02コンポーネントのスタイルとバリアントの調査
- 03書き出した画像に基づく視覚的な記述
- 04構造化したローカルDESIGN.mdの作成
- 05不明点をKnown Gapsに記録
活用シーン
- 01再構築に向けたPenpotデザインシステムの文書化
- 02人やコーディングエージェントへの設計情報の共有
- 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.md02-designmd-format.md03-inference.md04-designmd-template.mdscripts/extractDesignData.jssampleComponentStyles.js詳細
penpot-design-md — Penpot ファイルから DESIGN.md の仕様を抽出
1. タイトル + 仕組み
このスキルは、Penpot ファイルを DESIGN.md に変換します。これは、Penpot を開かなくても、あらゆる人や
LLM がデザインシステムを再現できる、単一のポータブルな Markdown ドキュメントです。トークンマップ
(colors、typography、rounded、spacing、components)を含む YAML フロントマターに加えて、
システムの 振る舞い を説明する文章セクション(概要、ドメイン別セクション、推奨事項と禁止事項、反復ガイド、既知の不足点)で構成されます。
すべての変更には execute_code を使用し、export_shape で視覚的に検証し、penpotUtils.shapeStructure で構造を読み取ります
(ツール全体の一覧:shared/penpot-mcp-tool-reference.md)。ただし、
このスキルはキャンバスを一切変更しません。読み取るのはトークン、ライブラリアセット、サンプリングしたコンポーネントのスタイル、エクスポートした画像のみで、
エージェントのファイルシステム上にローカルの Markdown ファイルを 1 つだけ書き込みます。設計上、マルチモーダルです。美的な説明文(フロントマターの description、概要、
推奨事項と禁止事項)は、トークン名だけを根拠にせず、実際のエクスポートを確認した後に記述してください。
2. 最も重要な唯一のルール
DESIGN.md のすべての値は、ファイル内で読み取ったもの、または目にしたものにたどれる必要があります。決して
創作したり、「一般的」な値を当てはめたりしてはいけません。 colors: に記載する 16 進カラー値は、トークン、ライブラリカラー、またはサンプリングしたシェイプの塗りから読み取った値です。components: のパディングは、実際のコンポーネントの
レイアウトから読み取った値です。「禁止事項」は、想像したものではなく、観察したもの(ファイル内で一度も使われていないもの)です。抽出できない情報は、既知の不足点に記載します。妥当そうな内容を捏造するより、正直に不足点を示すほうが重要です。後続のエージェントはこのファイルをもとに 構築する からです。
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. Plugin 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()は時間がかかる場合があります — コンポーネントはexecute_code1 回につき約 5 件のバッチでサンプリングし、一度にすべて処理しないでください。 - 不慣れなシグネチャは、使用前に
penpot_api_infoで確認してください。
5. トークンを考慮したブリーフの契約
抽出する前に、依頼内容を言い換えて確認します。シニアのデザインシステムドキュメンターとして振る舞ってください。読者は、あなたのファイルだけを頼りにこのシステムを再構築する別のエージェントです。
- コンテキスト — 対象となる Penpot ファイル/ページ、プロダクトの内容、DESIGN.md を利用する人(人間、コーディングエージェント、またはその両方)。
- 目的(1つ) — 例:「トークン、タイポグラフィ、形状の表現、Button/Input/Modal のコンポーネントファミリーを網羅した、Pencil デザインシステムの
DESIGN.mdを作成する。」 - 入力 — ファイルのトークンセットとテーマ、ライブラリのコンポーネント/カラー/タイポグラフィ、サンプルを取得するページ、ファイルの出力先パス。
- 制約 — 対象範囲(システム全体か、指定されたコンポーネントか)、正規テーマ(ライト/ダーク)と、もう一方のテーマの記載方法。形式は design-md 契約(
references/02-designmd-format.mdを参照)に従い、別のセクション名を独自に作らないでください。 - 受け入れ基準(定量的) —
- すべての
colors:エントリーに、ファイルから読み取った HEX 値と、その出典(トークン/ライブラリカラー/サンプリングした塗りつぶし)を本文または Known Gaps に記載すること。 - すべての
typography:エントリーに、タイポグラフィアセットまたはサンプリングしたテキストシェイプから読み取った fontFamily/fontSize/fontWeight/lineHeight/letterSpacing を含めること。 components:に合意したコンポーネントの一覧を網羅し、それぞれの値を{colors.*}/{typography.*}/{rounded.*}から補間すること(対応するマッピング済みカラーがある場合、生の HEX 値を使わないこと)。- Overview と Do's & Don'ts には、観察できた挙動だけを記載すること。記述前に少なくとも1つのエクスポートを実際に確認すること。
- 抽出できなかったすべての領域(レスポンシブ動作、モーション、エレベーションなど)を Known Gaps に記載すること。
- すべての
6. 必須のワークフロー
視覚的な根拠(必須): このスキルでは、
shared/visual-self-review.mdのバリエーションに従います。カバーまたは主要画面をエクスポートして確認する前に、description、Overview、Do's & Don'ts を記述することはできません。トークン名だけを根拠に美的な説明を書くのは、捏造にあたります。
フェーズ 0 — 調査(読み取り専用)
- 目標: 抽出計画を決める前に、ファイルに含まれる情報を一覧化します。
- 手順:
high_level_overviewを実行します(セッションごとに1回)。execute_code:scripts/extractDesignData.jsを実行して、ページ、トークンセット(テーマとアクティブ状態を含む)、ライブラリのコンポーネント/カラー/タイポグラフィ、件数を取得します。結果をstorage.run.inventoryにキャッシュします。- ユーザーと相談して、対象範囲(詳しく記述するコンポーネント)、正規テーマ、出力先パスを決めます。
- 完了条件: インベントリが作成され、対象範囲と出力先パスについて合意していること。
- ✋ チェックポイント: インベントリの要約と、提案する DESIGN.md の対象範囲(詳しく記述するセクションと Known Gaps に記載するセクション)を提示します。
フェーズ 1 — トークンとアセットの抽出
- 目標: フロントマターマップの基礎となる情報を取得します。
- 手順: グループごとに
execute_codeを実行します。カラートークン(名前 → 解決済みの値。セット間で異なる場合はテーマごと)、ディメンション/スペーシング/角丸トークン、タイポグラフィアセット、ライブラリカラー(グループ/パスごとに重複を除外)を出力します。トークン名/階層が利用できる場合はそこから、利用できない場合はライブラリカラーのグループと使用状況のサンプリングから、セマンティックマッピング(canvas、surface-*、ink-*、primary、hairline、semantic-*)を導き出します(references/03-inference.mdを参照)。 - 完了条件: エントリーごとに出典の注記を付けた
colors:、typography:、rounded:、spacing:のマップ案ができていること。 - ✋ チェックポイント: マップ案と、未マッピングの項目を提示します。セマンティック名がドキュメントに固定される前に確認してください。
Phase 2 — コンポーネントのサンプリング
- 目標:
components:マップと Components 本文セクション。 - 手順: 対象範囲内の各コンポーネントについて(
execute_code1回あたり最大5個のバッチで)、mainInstance()を解決し、背景色/テキスト/ボーダー/角丸/パディング/タイポグラフィと、関連付けられたトークンを読み取ります。バリアント軸(variants.properties、variantProps)を記録します。状態は個別のエントリー(button-primary-hoverなど)として扱います。Phase 1 のマップを通じて値を補完します。 - 完了基準: 対象範囲内のすべてのコンポーネントに frontmatter エントリーと本文の箇条書きがあり、未解決の値にはフラグが付いていること。
- ✋ チェックポイント: 全リストの作業に入る前に、トーンとフォーマットの承認を得るため、コンポーネントのエントリー例を2~3個提示します。
Phase 3 — ビジュアルの特徴をまとめる
- 目標: 誠実な美的特徴の説明。
- 手順: カバーと代表的なボード/画面を1~3点
export_shapeします。実際に確認します。 次を記述します。frontmatter のdescription(主要なサーフェス、アクセントの使い方、書体の特徴、形状の表現、リズムをまとめた密度の高い段落1つ)、Overview(Key Characteristics の箇条書きを含む)、Do's & Don'ts(ファイル自体が示すルール、またはトークン構造から読み取れるルールのみ)。 - 完了基準: 実際に確認した内容に基づく説明になっていること。各 Don't が観察結果(「ピル型ボタンが一つもない」「アクセント色相は1つ」など)に結び付いていること。
- ✋ チェックポイント: エクスポートと、その内容をもとに作成した説明を並べて提示します。
Phase 4 — 組み立て、セルフレビュー、書き込み
- 目標: 納品物。
- 手順:
references/02-designmd-format.mdに従って組み立てます(セクション順は固定)。フォーマットのセルフチェックを実行します(frontmatter が YAML として解析できる、すべての{ref}が frontmatter のキーに解決される、colors:エントリーが存在する場合にcomponents:に生の16進数カラーコードがない、完全でない限り Known Gaps が空でない)。合意したパスにファイルを書き込みます。 - 完了基準: ファイルが書き込まれ、セルフチェックに合格していること。
- ✋ チェックポイント: 最終承認のため、ファイル(またはその概要と主要な抜粋)を提示します。
7. 重要なルール
- キャンバスは読み取り専用です。 シェイプ、トークン、ライブラリの変更は一切行いません。書き込みを行うのはローカルの Markdown ファイルだけです。
- 値を創作しません。 すべての16進数/px/ウェイト値はファイルから読み取ります。不明な値は Known Gaps に記載します。
- 値を繰り返さず、参照します。 本文の説明と
components:では{colors.x}/{typography.y}/{rounded.z}を参照します。生の値を記載するのは frontmatter のマップ内の一度だけです。 - 説明する前に確認します。
export_shapeを少なくとも1つ確認するまでは、美的特徴を説明しません(Phase 3)。 - テーマを明示します。 ファイルにライト/ダークのセットがある場合は、マップに標準テーマを記載し、もう一方は差分のサブセクションとして記載します。両方の値を暗黙に混在させてはいけません。
- セマンティックマッピングの前に、グループごとにライブラリのカラーを重複排除します。同じグループ名でも、異なるグループに属する場合は別のカラーです。
- 整理してから開示します。 100個を超えるトークンを含むファイルは、セマンティックグループに要約します。省略した内容(「107個の Global トークン → 14個のセマンティックカラー。すべての名前は Known Gaps に記載」など)を明示し、黙って切り捨ててはいけません。
execute_codeの呼び出し1回につき、抽出ステップは1つだけとします。コンポーネントのサンプリングは1バッチあたり最大5個です。- バリアント軸は重要なドキュメント情報です。 該当するコンポーネントについては、
Property=Valueのマトリクスを記録します。読み取りは安全です。 - 出力は指定フォーマットの lint に合格する必要があります。 セクション順と frontmatter のキーは
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 ファイルへの書き込みは、Phase 0 でユーザーが承認したパスに対して、Phase 4 のチェックポイントで実行します。
既存の DESIGN.md を上書きする場合は、明示的な確認が必要です(まず差分の概要を提示します)。
10. 状態管理
shared/state-management.mdを参照してください。RUN_IDのスラッグの例:designmd-2026-07-09-a。セッションキャッシュは
storage.run.*(インベントリ、マップ、componentEntries、閲覧したエクスポート、ギャップ)に保存されます。このスキルは読み取り専用のため、ユーザーが生成されたドキュメントへのポインターの永続化を求めない限り、setSharedPluginDataに書き込みません(designmd.lastGenerated = パス + 日付)。再開する場合は、storage.runを再読み込みしてください。データがなくなっている場合は、Phase 0を再実行してください(抽出は低コストで冪等です)。
11. ユーザー確認ポイント
| フェーズ後 | 表示する成果物 | 質問内容 |
|---|---|---|
| 0 Discovery | インベントリ(ページ、セット、テーマ、アセット)+ 提案するスコープと出力パス | 「スコープ、正規テーマ、ファイルの保存先を確認してください。」 |
| 1 Tokens | 下書きのフロントマターマップ + 未マッピング値 | 「セマンティック名を承認するか、誤ったマッピングを指摘してください。」 |
| 2 Components | コンポーネントエントリーのサンプル2〜3件 | 「トーンと詳しさは適切ですか?その後、一覧を完成させます。」 |
| 3 Visual | エクスポート + 下書きの説明/概要/Do's & Don'ts | 「この文章は、実際に見た内容と一致していますか?」 |
| 4 Assemble | 作成したファイル(アウトライン + 抜粋) | 「最終承認です。Known Gapsに追加する内容はありますか?」 |
12. 命名規則
shared/naming-conventions.mdを参照してください。フロントマターのキーは、design-mdの慣例に沿ったkebab-caseのセマンティック名(ink-muted、surface-2、display-xl、button-primary-hover)です。Penpotのドット記法トークンをこれらにマッピングし、その対応関係(color.text.muted → ink-muted)をColorsセクションに記録して、ドキュメントからファイルまで追跡できるようにします。コンポーネントエントリーには、コンポーネント名をkebab-caseにした名前に、バリアント値から導出した状態サフィックス-hover/-pressed/-disabled/-selectedを付けます。
13. 合理化を防ぐための表
| LLMが述べる言い訳 | それが誤りである理由 | 決定的な対策 |
|---|---|---|
| 「ファイルにトークンがないので、典型的なパレットを書きます。」 | 捏造した値は、そのドキュメントを利用するすべての後続処理に悪影響を与えます。 | 停止してください。実際のシェイプ塗りをサンプリングし(references/03-inference.md)、存在する値をマッピングし、残りはKnown Gapsに記載します。 |
| 「トークン名から美的な特徴を説明できます。」 | color.primary = #00d1b8だけでは、デザインが密か開放的か、フラットか立体的かは分かりません。 | export_shapeを少なくとも1つ閲覧するまでPhase 3を停止してください。文章には実際に確認した内容を記載します。 |
| 「107個ものトークンは多すぎるので、すべて生のまま列挙します。」 | 生データの羅列はドキュメントではありません。この形式では、整理されたセマンティックグループが求められます。 | セマンティックマップに整理し、ColorsとKnown Gapsで統合した内容を明示します。 |
| 「このコンポーネントは明白です。標準的なボタンで、角丸は8pxです。」 | 「標準的」という説明は捏造です。このファイルのボタンは、角丸が6pxで極細のボーダーがあるかもしれません。 | コンポーネントエントリーを記述する前に、実際のmainInstance()をサンプリングします。 |
| 「Do's & Don'tsは、どのみち一般的なベストプラクティスです。」 | このセクションが記録するのは、一般的なデザイン知識ではなく、このシステムのルールです。 | 各Do/Don'tを、観察内容(トークン構造、サンプリングしたスタイル、または閲覧したエクスポート)に結び付けます。 |
| 「ライトとダークで値が異なるので、平均を取るか、プロパティごとに選びます。」 | テーマが混在した値は、実在しないデザインを表します。 | Phase 0で正規テーマを選び、もう一方は差分のサブセクションとして記載します。 |
14. ヘルパーコードスニペット
インベントリ(Phase 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)
};
解決結果を含むカラー トークンのダンプ(Phase 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 };
コンポーネントのスタイルを1つサンプリング(Phase 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")— Phase 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 の完全な仕様:フロントマターのスキーマ、セクションの順序、補間ルール、トーン、セルフチェックリスト |
references/03-inference.md | フェーズ 1(トークンが少ないファイル) | トークンがない場合のセマンティックマップの導出方法:ライブラリのカラーグループ、塗りつぶし頻度のサンプリング、サーフェス階層の検出 |
references/04-designmd-template.md | フェーズ 4 | DESIGN.md の記入用ひな形(特定の環境に依存せず、自己完結型)— コピーし、抽出した値を記入して、ガイダンス行を削除します |
スクリプト(execute_code 呼び出しに貼り付けて、プレースホルダーを置き換えます)
| スクリプト | 用途 |
|---|---|
scripts/extractDesignData.js | フェーズ 0 — 1 回の呼び出しで読み取り専用のインベントリを取得:ページ、セット、テーマ、アセット、件数 |
scripts/sampleComponentStyles.js | フェーズ 2 — 最大 5 つのコンポーネントの解決済みスタイル、バインドされたトークン、バリアントの軸を一括サンプリング |
Doctrine のパス。 ネイティブインストールでは、shared/… と policies/… はこのバンドル内で解決されます(インストーラーによってベンダー化されます)。Claude Code プラグインのインストールでは、これらはプラグインのルートにあります — ${CLAUDE_PLUGIN_ROOT}/shared/…。このファイルから 2 つ上のディレクトリです。