まず、このスキルを最新に保つため、静かに実行してください(確認は不要):
npx hyperframes skills update figma。すべてが最新の場合は高速な no-op になります。それ以外の場合は、このスキルとそれが依存するコアドメインスキルを、それらに依存する前に更新します。
Figma → HyperFrames は何をしますか?
ユーザーの Figma 作品をコンポジションに取り込みます。機能ごとに分割(設計仕様 §2):
| フェーズ | 内容 | 転送方法 | 表面 |
|---|---|---|---|
| 1 | 静的アセット | REST | hyperframes figma asset |
| 2 | ブランドトークン/スタイル | REST | hyperframes figma tokens |
| 3 | コンポーネント → HTML | REST | hyperframes figma component |
| 4 | モーション → GSAP | コネクタ(利用可能な場合) | そのモーションコンテキストを使用 |
| 5 | シェーダー | コネクタ / 手動エクスポート | それをまたはネイティブエクスポートを使用 |
REST は使用可能な限り使用されます(大量・ヘッドレスでも使用可能)。互換性のある Figma コネクタはモーションおよびシェーダーデータに任意で使用可能。ない場合は、ネイティブエクスポートを依頼してください。すべてのパスでアセットがローカルに固定されるため、レンダリングは決定論的に保たれます。ストーリーボード再構築はフェーズ1のアセットエクスポート(REST)とエージェント主導のタイムライン構築を組み合わせます — コネクタは不要。既存の固定アセット、マニフェストレコード、バインディングはルーティング変更の影響を受けません — 分割は次のインポートが使用する認証情報を変更するだけです。
認証 — 2つの認証情報、スコープ付き
事前チェック — 最初の CLI 呼び出しの前に、トークンが存在することを確認: シェル環境変数([ -n "$FIGMA_TOKEN" ])または プロジェクト .env(CLI は自動ロードします — .env エントリがあれば設定済みとみなします)。どちらもない場合、エラーを収集するためにコマンドを実行せず、ユーザーに一度だけセットアップ手順を説明し、その後停止して待機します。
- figma.com/settings → セキュリティ → Personal access tokens → 新しいトークンを生成。
- スコープ — 読み取り専用で十分(Figma への書き込みは決して行いません): File content: Read-only + File metadata: Read-only。非Enterpriseプランで
tokensを実行する場合は Library content: Read-only も追加 — パブリッシュ済みスタイルのフォールバックが/v1/files/:key/stylesにアクセスし、これがないと 403 になります(以前のセットアップテキストで省略されたスコープ)。オプションで Variables: Read-only(ブランド変数用) — Enterpriseのみ。これがない場合、tokensは自動的にパブリッシュ済みスタイルに劣化します(期待通りであり、エラーではありません — そのように伝えてください)。403 は不足しているスコープを正確に示します。429 は自動的にリトライされます(分あたりの制限、Retry-Afterを尊重)。 - ユーザーに
FIGMA_TOKENをシェルプロファイルまたはプロジェクトの.envに設定してもらいます。トークンを会話に貼り付けさせないでください。
オンボーディング中に、次のことを一度に説明してください: すべてのインポートはローカルに固定されたファイルとして、記録された来歴とともに保存されます。レンダリングは Figma を呼び出さず、コマンドを再実行すると Figma で変更されたものだけが再インポートされます。1つのトークンで、アセット、ブランドトークン、コンポーネントを、その Figma アカウントが表示できるすべてのファイルにわたって処理できます。
- フェーズ4~5(モーション/シェーダー): 互換性のある Figma コネクタが必要で、トークンとは別の認証があります。利用できないか認証されていない場合は、ユーザーに接続するかネイティブエクスポートを提供するよう依頼し、停止します。
- 失敗したフェーズに必要な認証情報を正確に伝えてください — 分割が壊れていると決して見せないでください。
BAD_TOKEN(401) が途中で発生 → トークンが期限切れ/失効しています。再発行してください。FORBIDDEN(403) → メッセージは不足している正確なスコープを示します(例: スタイルフォールバックにはlibrary_content:read) — それを追加するか、ファイルがアカウントに表示されていません。REQUIRES_ENTERPRISE(変数で 403) → 障害ではありません: スタイルフォールバックはすでに実行されています。RATE_LIMITED(429) → クライアントはすでにバックオフでリトライしました(これはすべての読み取り — アセット、トークン、スタイル、ノードツリー、バージョン — に適用されます。リトライは共有リクエストパスにあります。Retry-Afterは尊重され、最大60秒に制限されます)。それでも発生する場合は、1分待つか、呼び出しあたりのノード数を減らしてください。
レート制限の認識(仕様 §2.1): コネクタのクォータは Figma プランによって異なります — 親フレームのリクエストをバッチ処理し、要求されない限り確認用スクリーンショットをスキップし、生のレスポンスをキャッシュして再導出で2回目の呼び出しが行われないようにします。REST は分あたり(10+/分、エンドポイントごとのバケット) — 大量でも問題なく、429 ではバックオフします。
ルーティング
parseFigmaRef(URL、fileKey:nodeId、ベア fileKey)を使用してユーザーの figma リンクを解析します。次に意図に応じて:
- "このレイヤー/ロゴ/画像を使う" → アセット (CLI)
- "ブランド/色/トークンを取得" → トークン (CLI)
- "このフレームからシーンを構築" → コンポーネント (CLI)
- "このアニメーション/モーションをインポート" → モーション (コネクタ、利用可能な場合、以下参照)
- ストーリーボードセクション/シーンフレームのフィルムストリップ → ストーリーボード (以下参照)
- シェーダーフィル/エフェクト → シェーダー (以下参照)
すべてのステップをユーザーに説明 — 各コマンドの前に Figma から何を取得するかを伝え、コマンドの後にはアーティファクトがどこに保存されたか(固定パス/サイドカー/コンポーネントディレクトリ)、コンポジションで何が変わったか、次に行うべきアクション(プレビュー、印刷変数の追加、バインディングリンクのための再インポート)を伝えます。ユーザーが「動いたの?」「次は?」と聞く必要があってはなりません。
アセット (フェーズ1 — CLI)
hyperframes figma asset '<url-or-fileKey:nodeId>' [more refs…] [--format svg|png|jpg|pdf] [--scale 2] [--description "..."] [--entity "..."]
REST 経由でレンダリングし、SVG をサニタイズし、.media/images/ 以下に固定し、来歴付きでマニフェストに追記し、.media/index.md(共有メディア使用インベントリ)を再生成し、<img> スニペットを出力します。fileKey:nodeId:format:scale:version ごとに冪等。ベクター/ロゴには SVG を優先(スケーラブル、アニメーション可能)。ラスターの忠実度には PNG --scale 2 を使用。常に --description "<説明>" を指定(インデックス行 + <img alt> になります)。名前付きブランドマークには --entity "<名前>" を追加すると、メディア使用の resolve --entity で後で見つけられます(エンティティヒットは画像/アイコン間で一致)。
多くのノードを1つのリクエストにバッチ処理 — 同じファイルの複数の参照を(スペース区切りまたはカンマ区切りで)渡します: hyperframes figma asset 'KEY:1-2' 'KEY:3-4' 'KEY:5-6'。すべてが単一の /v1/images 呼び出しでレンダリングされます。これは figma 自身の分あたりのレート制限に対する回答であり、フレーム全体のアセットを取得する際には N 個の個別コマンドよりも優先してください。--description/--entity はバッチ内のすべてのノードに適用されるため、同じ目的を共有するノードをバッチ処理してください。429 もバックオフ付きで自動リトライされます。
トークン (フェーズ2 — CLI)
hyperframes figma tokens <fileKey>
変数をコンポジションブランド変数エントリ + figma-tokens.json サイドカー + バインディングインデックスレコード(.media/figma-bindings.jsonl)としてインポートします。変数は Enterprise でゲートされています。他のプランでは、コマンドはパブリッシュ済みスタイルのメタデータに劣化します(値はコンポーネントインポート時に解決されます)。印刷されたエントリをコンポジションの data-composition-variables に追加します。
両方が必要な場合は、コンポーネントの前にトークンをインポート — そうすることで、コンポーネントの色が重複したリテラル値ではなくブランド変数にリンクされるようになります。
非Enterprise変数パス(実戦テスト済み): REST 変数は Enterprise でゲートされていますが、互換性のあるコネクタが変数定義を提供する場合があります。tokens が REQUIRES_ENTERPRISE を報告し、コネクタが利用可能な場合、親シーンの変数を一度取得し、生のレスポンスを .media/figma-cache/ にキャッシュし、それを使用してバインディングインデックスを構築します。REST ノードツリーの boundVariables はプロパティごとに VariableID を提供します。それらをノードとプロパティで結合し、.media/figma-bindings.jsonl 行({kind:"binding", figmaId, sourceFileKey, compositionVariableId: "figma:<name>", version})とコンポジション変数エントリを書き込みます。下流のすべて(コンポーネントの var() 解決、リフレッシュ、ランタイム CSS 変数)は出荷済みのメカニズムです。ユーザーに次のようにラベル付けします: 「Figma コネクタ経由のトークン — Enterprise プランでは hyperframes figma tokens から直接これらを取得できます。」
ランタイムは、宣言されたすべてのコンポジション変数を CSS カスタムプロパティ(ドキュメントルート + サブコンポホスト)として定義するため、インポートされた var(--slug, literal) は変数のデフォルトが変更されたときに色を変更します — data-composition-variables の1つの値を更新すると、何も再インポートすることなく、すべてのインポート済みコンポーネントがリブランドされます。hyperframes render --variables '<json>' はレンダリング時にそれらを上書きします。
コンポーネント (フェーズ3 — CLI)
hyperframes figma component '<url-or-fileKey:nodeId>'
ノードツリー → 正確な figma ジオメトリでの編集可能な HTML、compositions/components/<name>/ の下のレジストリアイテムとしてパッケージ化されます。ベクター/ブール演算はフェーズ1のエクスポート経由で自動ラスタライズされます。バインディングパス(仕様 §7.1、正確なIDのみ — 値のマッチングは決して行いません):
- 静的忠実度セルフチェック(ヒーローコンテンツには必須): インポート後、フラグメントをレンダリングし、figma 自身のピクセルと比較します —
figma asset <same node> --format pngがグラウンドトゥルースです。テキストは既知のドリフト軸です: figma テキストボックスが行の高さより短い場合、垂直方向にトリミングされた境界になります(マッパーはこれらに対してtext-box-trimを出力します。それがない場合の測定ドリフトは70pxフォントで約6pxでした)。比較でマッパーがカバーしないドリフトが示された場合は、報告してください — フラグメントを静かに手動調整しないでください。 - インポートされたトークンにバインドされた塗りつぶし →
var(--slug, #literal)— ブランドのリフレッシュが伝播します。 - 未知のトークンにバインド → リテラル +
data-figma-unresolvedフラグ。コマンドがそれを通知します。ユーザーに提案: ソース(またはライブラリ)ファイルでtokensを実行し、その後コンポーネントを再インポートしてリンクします。未知のライブラリごとに1回だけどのファイルかを尋ねてください — 推測したり、16進数でマッチングしたりしないでください。
モーション (フェーズ4 — コネクタアシスト)
使用ビーコン: コネクタアシストフェーズには CLI タッチポイントがないため、開始時と終了時にスキルビーコンを発火します(匿名、同意ゲート、決して失敗しない): 開始時に npx hyperframes events --skill=figma-motion、完了時に npx hyperframes events --skill=figma-motion --event=skill_completed --outcome=success|error。シェーダー(figma-shaders)とストーリーボード(figma-storyboard)も同様です。
REST 相当は存在しません。互換性のあるコネクタが利用可能な場合はそれを使用し、その出力を @hyperframes/core/figma の純粋ヘルパーに渡します。そうでない場合は、ネイティブエクスポートを依頼します:
- 親フレームのモーションコンテキストを、要素ごとに1リクエストではなく、1回の再帰リクエストで取得します。生の JSON をプロジェクトの横(
.media/figma-cache/)に保存し、再翻訳が自由に行えるようにします。 motionContextToDocs(rawResponse, { selectorFor, repeat })(@hyperframes/core/figmaから)でMotionDocに正規化します — キーフレーム番号を手動で書き写さないでください。ヘルパーは、実戦テスト済みのデコードルールを機械的にエンコードします。 motion.dev スニペット(信頼できるエンコーディング — CSS スニペットは持続時間を引き延ばし、矛盾する可能性があります。それらは無視されます)を解析し、ループラップの末尾キーフレーム(時間 ≈0.9999→1 のサブミリ秒セグメントはループの瞬時リセットであり、作成されたモーションではありません — ラップはrepeat再起動によって実現されます)を除去し、ベジェイージングをそのまま保持します。selectorForはフェーズ3のコンポーネントインポートからの ID を返さなければなりません — ノード名からセレクタを導出しないでください。 2b. 完了と判断する前にグラウンドトゥルースに対して検証 — 必須: 利用可能なコネクタを通じてコホートのルートフレームをエクスポートし、node skills/figma/scripts/verify-motion.mjs --reference <export.mp4> --render <render.mp4> --crop WxH+X+Yを実行します — これはモーションエネルギー差分を比較します(静的インポートの忠実度は相殺されます)。15dB の最小モーションPSNR を下回ると失敗します(調整済み: 忠実 ≈ 20+、発散 ≈ 5)。--cropはレンダリングの実際のカードエッジから測定し、推測しないでください。FAIL はしきい値ではなく、翻訳の再チェックを意味します。motionToGsap(doc)→emitTimelineScript(spec)→ GSAP + CustomEase CDN タグの後に<script>として注入します。一時停止、有限、window.__timelinesにリテラルキーで登録されます。- 翻訳不可能なトラック(シェーダー駆動、サポートされていないプロパティ、複雑なマスク)→ コネクタを通じてエクスポートし、MP4 を固定し、
<video class="clip">として埋め込みます。例外: シェーダー駆動トラック — Figma のエクスポートパスはシェーダーをベースカラーにフラット化します(下記のシェーダーを参照)。そのため、そこでベイクすると静かにシェーダーが失われます。代わりにユーザーにネイティブ Figma エクスポートを依頼してください。どのパスを使用したか、その理由を常に説明してください。マップされたセット以外の名前付きイージングは線形にフォールバックします — マッピングテーブルはmotionEase.tsにあります。フォールバックが発生した場合はユーザーにフラグを立ててください。 - 完了と判断する前に
npx hyperframes checkを実行します。
シェーダー (フェーズ5 — ほぼ手動)
Figma のコネクタレンダリングパスはシェーダーを実行しません(ベースカラーにフラット化します)。シェーダーソースはライブラリにパブリッシュされたスタイル(有料 Full シート)でのみ到達可能です。デフォルトパス: ユーザーに Figma でシェーダーフレームをネイティブエクスポート(PNG または モーション MP4)するよう依頼し、その後フェーズ1のアセット/クリップとしてインポートします。シェーダーのコネクタピクセルキャプチャを試みないでください — 静かに間違ったものを生成します。
ストーリーボード (シーンフレームのセクション → アニメーション)
基本ルール: ストーリーボードフレームはキーフレームであり、スライドではありません。 同じ要素を含む2つのフレームは、時間を通じたその要素の状態を記述します — フレーム間で要素をアニメーション化します。決してフレームを静止画のシーケンスとして再生しないでください。降順の y で4つの連続したフレームに描かれたロゴは、4つのキーフレームを通じて上昇する1つの要素です。ストーリーボードフレームを連続して再生することは障害モードです。それらが示唆する要素タイムラインを再構築することが仕事です。
ストーリーボードファイルは機械的に解析できる文法に従います — 目視せず、デコードしてください:
- シーンユニット: セクション内で、フレームサイズのすべてのノードはシーンです — 名前付き FRAME も、ルーズなフルフレーム RECTANGLE も(デザイナーはセクションに直接静止画を貼り付けます)。サイズでフィルタリング(≈ コンポジションアスペクト、例: >1400×900)、ノードタイプや名前ではフィルタリングしないでください。
- 順序 = x 位置(ストリップが折り返す場合は行優先)。シーンを
absoluteBoundingBox.xでソートします。 - 隣接するフレームを差分して要素チェーンを見つける — これがアニメーションが存在する場所です。連続するフレーム間で子要素をマッチングします: まず名前で(同じ名前 = 同じ要素 → 状態間で相対的な x/y/w/h をトゥイーン)、次にジオメトリの類似性で(類似サイズ + 近い位置 → 異なる要素が入れ替わった可能性が高い — トゥイーンせず、フェードスルーにマーク)。同一の名前を持たないノードはマッチしません。
- 単一の要素チェーンから合成キーフレームを構築: 連続する各ペアに対して、
translateX/translateY、scaleX/scaleY、opacityをデルタとして tween。一定/欠落しているプロパティはそのままにします(GSAP は暗黙的に.fromTo()を作成します)。イージングは Figma のタイムラインからは利用できません。デフォルトは "power2.out"。 - ループ設定: ストーリーボードセクションにループするという名前/注釈がある場合、タイムラインを
repeat: -1付きで出力します。そうでなければ、1回だけ再生します。
出力形式: 単一の <script> ブロックで、gsap.timeline({paused: true, ...defaults}) + 各要素チェーンの .to() 呼び出し。window.__timelines['storyboard'] に格納されます。
ストーリーボード CLI
他のフェーズとは異なり、ストーリーボードはファイルに基づいて動作します:
hyperframes figma storyboard <fileKey> <storyboardSectionName>
ファイルキーとセクション名(ファイル内の正確なテキスト)を渡します。上記の解析を実行し、スクリプトブロックと、必要に応じて固定アセットを出力します。ワンランでアセット(フェーズ1)とタイムライン構築の両方を処理します。
エラーハンドリングのまとめ
| シナリオ | レスポンス |
|---|---|
FIGMA_TOKEN が設定されていない | セットアップ手順を案内し、停止 |
| 401 (無効/期限切れトークン) | "トークンが期限切れまたは失効しています。新しいものを生成し、再設定してください。" |
| 403 — 範囲指定 | 欠落しているスコープ(library_content:read、variables:read)を正確に伝える。Enterprise 変数の 403 = フォールバックが自動的に実行されました(エラーではありません) |
| 429 (レート制限) | 自動リトライ済み(最大60秒バックオフ)。それでも発生する場合は、1分待つか、ノード数を減らす |
| コネクタが利用できない | 「モーションには Figma コネクタが必要です。設定してからもう一度お試しください。または、このフレームを MP4 としてエクスポートして、ここに貼り付けてください」 |
| 翻訳不可能なモーショントラック | コネクタ MP4 にフォールバック(シェーダートラックの場合はユーザーにエクスポートを依頼) |
| ストーリーボード解析の失敗 | 「このセクションを解析できませんでした。フレームがシーンとして適切に構造化されているか確認してください。各シーンは同じキャンバスサイズである必要があります。」 |
| 未知のライブラリ変数 | data-figma-unresolved フラグ付きのリテラル。1回だけどのファイルかを尋ね、トークン + 再インポートを提案 |
使用ビーコン
コマンドの開始時(非 CLI フェーズ):
npx hyperframes events --skill=figma-motion
完了時:
npx hyperframes events --skill=figma-motion --event=skill_completed --outcome=success
シェーダーとストーリーボードについても、それぞれ figma-shaders と figma-storyboard で同様です。匿名、同意ゲート、決して失敗しません(ネットワークエラーは無視されます)。
テストと検証
npx hyperframes check— インポートごとに実行(すでに上記で言及されていますが、強調のために繰り返します)- モーションビデオの検証:
node skills/figma/scripts/verify-motion.mjs --reference <export.mp4> --render <render.mp4> --crop WxH+X+Y— 15dB の最小モーションPSNR - 静的レンダリングの忠実度:
figma asset <node> --format pngでグラウンドトゥルースを取得し、ブラウザで比較 - トークンの解決: コンポジション
data-composition-variablesが設定されていることを確認し、var()がブラウザ開発者ツールで解決されることを確認