Communitygithub.com

iggycpnfsky/figma-bridge

ローカルのFigma Bridgeを介してFigmaファイルを操作——選択範囲の読み取り、フレーム・テキスト・シェイプの作成、変数のバインド、画像の配置、PNG/SVGのエクスポートが可能。Figmaキャンバスに触れる必要があるタスク(デザインの検査、Figma内でのUI実装、色のトークンへの置き換え、アセットのエクスポート、生成アートワークの挿入)に使用。ブリッジサーバー(localhost:3847)と対象ファイルで実行中のFigma Bridgeプラグインが必要。利用できない場合は無理に代替せず、ユーザーにそれらの起動を依頼すること。

figma-bridge とは?

Figma Bridgeは、Figmaの公開APIでは不可能な「キャンバスへの書き込み操作」を、ローカルプロキシ(HTTPサーバー+Figmaプラグイン)を介して実現するスキルです。Figma Plugin APIを利用し、認証トークンやOAuthは不要です。開発者は`figma` CLIを通じて、フレームの作成、テキストの追加、変数のバインド、画像の配置、PNG/SVGエクスポートなどをコードから実行できます。主な対応プラットフォームはClaude Code、Cursor、CodexなどのAIエージェントです。事前条件として`figma doctor`で環境全体をチェックし、`figma rules`でプロジェクト固有の制約を読み込むことが重要です。操作は「状態を読む→計画する→書き込む→確認する」というループで進め、エラー(接続なし、503、504 PLUGIN_GONE)が発生した場合は適切にユーザーに通知します。既存のドラフトを扱う場合は、その構成意図を尊重しながら変更することをルールとしています。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/iggypcnfsky/figma-bridge/tree/HEAD/.agents/skills/figma-bridge

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Figma Bridge

Figmaには公開された書き込みAPIがありません。このスキルはローカルブリッジを使用します。名前付き操作をHTTP経由でプラグインに送り、Figma Plugin APIを介してFigma内部で実行します。OAuthもトークンも不要です。

リポジトリ: https://github.com/iggypcnfsky/figma-bridge — AGENTS.md、docs/ops-reference.md

前提条件 — 他の何よりも先に確認すること

figma が PATH に含まれているため、リポジトリをファイルシステムから検索してはいけません:

figma doctor        # リポジトリ、サーバー、接続済みウィンドウ、img-forge + FALキーを一発で確認
figma clients       # 接続中の各FigmaウィンドウのID、ファイル、ページを表示
figma rules         # プロジェクト制約: タイプ階層、グリッド、フレームサイズ、バージョン命名規則

設計前に figma rules を読むこと。 これには「Poppins 20/25が最小」といった、キャンバスを見ただけではわからない非自明な制限が書かれています。"confirmed": false は仮定としてユーザーに確認する必要があることを意味し、{} は「ユーザーに尋ねよ、勝手に決めるな」を意味します。

コマンドがない場合は、node "$(figma where)/server.mjs" を尋ねた後にのみ使用してください。リポジトリを find したり、パスを推測したりしてはいけません。

  • pluginConnected: false → 停止。ユーザーに、操作対象のファイルのウィンドウで Plugins → Development → Figma Bridge を実行するよう依頼してください。リトライしても解決しません。
  • /run からの 503 も同じ意味です。504 PLUGIN_GONE はプラグインウィンドウが閉じられたことを意味します。
  • 409 は複数のFigmaウィンドウが接続されており、どれも選択されていないことを意味します。ユーザーが指定したファイル(--file <NAME>)またはクライアントID(--client <ID>)を選んでください。決して無闇にリトライしないでください。間違ったファイルを編集する恐れがあります。

ループ

  1. 状況把握. ./bin/figma status → ファイル名、現在のページ、選択範囲、全ページ。
  2. 読み取り. selection 2、node <id> 2、find {"name":"Header","allPages":true}。 nodeId を推測してはいけません — FigmaのIDは 4022:2 のようになっており、導出できません。
  3. 計画. 親、サイズ、順序を決定。新しいノードは parentId が指定されない限り現在のページに追加されます。
  4. 書き込み. ./bin/figma run '[{...},{...}]'。
  5. 検証. ./bin/figma export <id> out/check.png PNG 2 を実行し、実際に画像を確認すること。

コマンド

./bin/figma op '{"op":"status"}'
./bin/figma run '[{"op":"createFrame","name":"Card","width":320,"height":200,"fill":"#0B0B0F",
                   "props":{"cornerRadius":16,"layoutMode":"VERTICAL","paddingTop":24,"paddingLeft":24,"itemSpacing":12}}]'
./bin/figma run '[{"op":"createText","parentId":"12:34","characters":"Title","fontSize":24,"color":"#FFFFFF"}]'
./bin/figma op '{"op":"varFill","nodeId":"12:34","variableName":"color/bg/surface"}'
./bin/figma export 12:34 out/card.png PNG 2
./bin/figma image 12:34 out/cover.png FILL      # ローカル画像ファイル → 塗りつぶし(クラウドアップロード不要)

操作一覧: ping status pages variables styles fonts inventory · selection node find · createFrame createRect createEllipse createText createPage createInstance · update clone reparent remove goto group ungroup select · grids setGrids align distribute effects · applyStyle varFill · export imageFill · exec。 完全なパラメータ: docs/ops-reference.md。

知っておくと便利なデザインワークのショートカット:

  • grid は GRID を意味する: ユーザーが「グリッドを設定して」と言った場合、列ではなく正方形のレイアウトグリッドを意味します: {"op":"setGrids","nodeId":"…","grid":true}(デフォルトで40pxセル、40%)または "grid":40。 columns/rows は、ユーザーが列、12カラムグリッド、またはガター/マージンの値を指定した場合にのみ使用します。 グリッドを矩形で偽装してはいけません。applyStyle で kind:"grid" を使用すると保存済みのグリッドスタイルを適用できます。
  • アイテムの行: アイテムを作成したら、{"op":"align","nodeIds":[…],"mode":"TOP"} と {"op":"distribute","nodeIds":[…],"axis":"HORIZONTAL","gap":24} を使用します。
  • 奥行き: {"op":"effects","nodeId":"…","shadow":{"y":8,"blur":24,"color":"#00000033"}} または {"op":"effects","nodeId":"…","blur":{"type":"BACKGROUND","radius":20}} を使用します。
  • グラデーション: {"op":"gradient","nodeId":"…","kind":"linear","angle":135,"stops":[[0,"#8B76FF"],[1,"#0E0E12"]]} — 角度0は左→右、90は上→下。グラデーションを矩形の重ねで偽装してはいけません。
  • デザインシステム: COMPONENT ID で createInstance を使用し、instanceProps でバリアント(事前に名前を読むこと)を、instanceText でテキストを変更(デタッチせずに)。applyStyle でスタイルを適用。ライブラリに既にあるものを再描画せず、インスタンスをデタッチしてテキストを「修正」しないこと。
  • スペーシングチェック: {"op":"measure","a":"1:2","b":"1:3"} は辺ごとのギャップと中心間距離を返します。配置を判断するためにスクリーンショットをエクスポートする代わりにこれを使用してください。
  • スタイル: saveStyle で text / paint / effect / grid スタイルを名前で作成/更新し、applyStyle で適用。トークンを一度作成して、どこにでも適用します。
  • レスポンシブ: sizing で軸ごとに HUG/FILL/FIXED と min/max を設定。constraints はオートレイアウトではない子要素(STRETCH/MIN/MAX/CENTER/SCALE)をカバー。変更する前に node から両方を読み取ること。sizing はプロパティが適用されない場合、Figmoの理由とともに skipped を返します。

画像

アートワークが必要? 同梱の img-forge CLI(https://github.com/iggypcnfsky/img-forge)で生成してから配置します。生成はFigmaの外で行われるため、APIキーがプラグインコードに入らず、遅いレンダリングがキャンバスをブロックしません:

cd ../img-forge
./img gen --prompt "abstract gradient cover, purple to black" --preset 16:9@2k --out out/cover.png
./img edit --prompt "make it night with neon accents" --ref out/cover.png   # 既存アセットの編集
cd ../figma-bridge
./bin/figma image 12:34 ../img-forge/out/cover.png FILL

FILL はノードに合わせてクロップ、FIT はレターボックス、TILE は繰り返し、CROP は既存のクロップを尊重します。ユーザーが選択したものを編集するには、まずエクスポート(./bin/figma export <nodeId> out/sel.png PNG 2)し、そのファイルを --ref として渡します。

プラグインウィンドウには、人間向けの Generate / Edit パネル(モデル、サイズプリセット、コスト、挿入)もあります。プログラムからパネルを操作しないでください — CLIを使用してください。CLIはより多くの機能(マスク、バリアント、ドライラン)を公開しています。そのパネルに保存されたプリセットは figma-bridge/presets.json に保存されます。

既存のドラフト上での構築

「完成していない」ドラフトでも、何が何の隣にあるか、何がグループ化されているか、要素の順序、スペーシングのリズムといった決定がコード化されています。設計前にそれを読み取り、維持してください。

  1. {"op":"inventory"} — フレーム、そのサイズ、タイポグラフィ統計。
  2. {"op":"structure","nodeId":"<frame>"} — 子要素がギャップと readingOrder で行にグループ化されたもの。これが作者が選んだグループ化です。{"op":"node",…,"depth":2} はより深い同じツリーを返します。
  3. パターン(繰り返される左マージン、常に3列の上にあるタイトルなど)に注目し、それを維持します。リクエストが必要とするものだけを変更し、残りはそのままにします。
  4. 行った変更を報告します — 「レイアウトを改善しました」ではなく「フッターを40px上に移動しました」のように。

ドラフトを黙って正規化してはいけません。一貫性を保つためにユーザーが配置したものを動かす必要がある場合は、その旨を伝えて尋ねてください。ユーザーのグループ化を失った見た目だけきれいなスライドは、改善ではなく退行です。

ルール

  • 書き込む前に読め。 最低2回の呼び出し: 検査してから変更。
  • 1バッチ = 1つの思考。 ある操作は前の操作の結果を参照できないため、新しいノードの id が必要な場合は2回の呼び出しに分割すること。
  • 引き継いだ配置を尊重する: 兄弟の順序、近接性、グループ化は意図です。依頼がない限り、見た目を整えるためにドラフトを再構成しないでください。一貫性を保つためにユーザーの要素を動かす必要がある場合は、まず尋ねてください。
  • 明示的な指示なしに既存のユーザーレイヤーに触れてはいけない(update、remove、reparent)。自分の作成物には Bridge / … のプレフィックスを付けること。
  • やり直しはオリジナルのすぐ隣に、可能な限り近くに配置する。 スライド/画面/セクションのやり直しを依頼された場合: それを複製し、{"op":"placeNear","nodeId":"<new id>","move":true,"gap":80,"name":"Bridge / v2 — <name>"} を呼び出して、コピーが推測された座標ではなく最初の空いている側に配置されるようにします。オリジナルには触れないでください。ツールが free: false を報告した場合は、どこに配置するか尋ねてください。要素をその場で置き換えるのは、ユーザーが明示的に依頼した場合のみです。
  • goto はユーザーのビューを変更する — リクエストがあった場合のみ使用。
  • exec は最後の手段。 動作します(Figmaのサンドボックスは new Function を許可)が、すべてのパラメータ検証をバイパスします。JSONシリアライズ可能な値のみを返すこと。
  • テストアーティファクトをクリーンアップする か、保持するかユーザーに尋ねること。

落とし穴

  • localhost を使用し、決して 127.0.0.1 を使用しないでください: プラグインマニフェストは http://localhost:3847 のみを許可リストに含めています(devAllowedDomains)。FigmaはIPを拒否します。サーバーは 127.0.0.1 と ::1 の両方でリッスンします。
  • figma.currentPage はそのFigmaウィンドウで開いているページであり、保存されたポインターではありません。タブを切り替えると、次の呼び出しで見えるものが変わります。
  • 位置は親に対する相対位置であり、parentId を省略すると 現在のページ を意味します。
  • タイポグラフィに関する質問(フォント、サイズ、カウント)は1回の呼び出し: {"op":"fonts"}。ファイル全体の場合は "allPages":true を追加。独自のスクリプトでフレームを走査しないでください。
  • スライドデッキの概要も1回の呼び出し: {"op":"inventory"} はすべてのフレームをジオメトリ、minFontSize、フォント、グリッド数、塗りつぶしとともに返します。「フレーム11–19」を選択したり、最小サイズ以下のテキストを見つけたりするのに十分です。
  • リファレンスにリストされていないフィールドにインデックスを付けないでください。summary はTEXTに対して font、fontSize、lineHeight、letterSpacing を持ちます。それ以外はすべて、実際のAPI名で exec から取得します。混合スタイルは文字列 "MIXED" になるため、.get() とフォールバックでガードしてください。
  • 矩形は子を持つことができません。テキストやアイコンをシェイプの中に配置する必要がある場合は、フレームを使用してください。
  • ローカル変数がない場合 → variables は collections: [] を返し、varFill は失敗します。最初に確認すること。
  • テキストにはフォントが必要: createText は loadFontAsync でフォントを読み込みます。ファミリが見つからない場合は Inter を使用してください。
  • export は8 MBで制限 — リトライする代わりに scale を下げてください。
  • 現在のページではないページの子を読むには loadAllPagesAsync が必要です。ブリッジは自動で1回リトライしますが、allPages: true を指定した find を優先してください。
  • プラグインファイル(code.js、ui.html)を編集した後、ユーザーはプラグインを再実行する必要があります。manifest.json の変更は再インポートが必要です。

関連スキル