mcpField
D
design-import

design-import

github.com/yonatangrossデザイン・UI29962 回インストール今日更新
リポジトリ

design-import について

design-importは、Claude DesignのハンドオフバンドルからReactコンポーネントのひな形を作成し、トークン調整、重複確認、プロベナンス記録を行うスキルです。既存プロジェクトへのデザイン取り込み向けで、PR作成やテスト実行は行いません。

主な機能

  1. 01ハンドオフURLまたはローカルファイルの受付
  2. 02ハンドオフバンドルの検証と正規化
  3. 03デザイントークンの調整
  4. 04既存コンポーネントの再利用または適応
  5. 05Reactコンポーネントのひな形生成
  6. 06インポートしたコンポーネントのプロベナンス記録

活用シーン

  1. 01Claude DesignのエクスポートをReactプロジェクトに取り込む
  2. 02ひな形作成前にトークンの差異を解決
  3. 03コードベース内の既存コンポーネントとの重複を回避

インストール

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

$npx skills add https://github.com/yonatangross/orchestkit --skill design-import

インストール後、Claude Code で/design-importを入力して読み込まれたか確認します。

詳細

デザインのインポート

Claude Design の引き継ぎバンドルを、出所情報と既存のコードベースとの重複排除を伴う、足場となる React コンポーネントに変換します。

design-import https://claude.ai/design/abc123      # From handoff URL
design-import /tmp/handoff-bundle.json             # From local file

使用するタイミング

claude.ai/design から引き継ぎバンドルをエクスポートした後に使用します。このスキルはエントリーポイントであり、PR の作成、テストの実行、デプロイは行いません。インポートからテスト、PR までのエンドツーエンドのフローには、代わりに design-ship を使用してください。

パイプライン

Handoff bundle (URL or file)
  │
  ▼
┌──────────────────────────────┐
│ 1. PARSE + VALIDATE          │  via claude-design-orchestrator agent
│    - Fetch bundle             │  Schema validation
│    - Compute bundle_id (sha)  │  Surface deviations
└──────────┬───────────────────┘
           │
           ▼
┌──────────────────────────────┐
│ 2. RECONCILE TOKENS           │  Diff bundle tokens vs project tokens
│    - Read project tokens      │  Conflicts → AskUserQuestion
│    - Apply additions          │  Additions → write to design-tokens.json
└──────────┬───────────────────┘
           │
           ▼
┌──────────────────────────────┐
│ 3. DEDUP COMPONENTS           │  For each proposed component:
│    Storybook MCP first        │   • exact match → reuse (skip)
│    21st.dev next              │   • similar match → adapt
│    Filesystem grep last       │   • no match → scaffold
└──────────┬───────────────────┘
           │
           ▼
┌──────────────────────────────┐
│ 4. SCAFFOLD                   │  Delegate to design-to-code per component
│    (skipped components        │  Use bundle's tsx_scaffold as seed
│     logged but not touched)   │  Apply project tokens
└──────────┬───────────────────┘
           │
           ▼
┌──────────────────────────────┐
│ 5. WRITE PROVENANCE           │  .claude/design-handoffs/<bundle_id>.json
│    Bundle → files → (PR)      │  PR field empty until design-ship
└──────────┬───────────────────┘
           │
           ▼
   Import manifest (stdout)

引数の解決

ARG = "$1"  # First positional argument

if ARG.startswith("http://") or ARG.startswith("https://"):
    bundle_source = "url"
    bundle_input = ARG
elif Path(ARG).exists():
    bundle_source = "file"
    bundle_input = ARG
else:
    AskUserQuestion(questions=[{
      "question": "I couldn't resolve that as a URL or file. What is it?",
      "header": "Bundle source",
      "options": [
        {"label": "Paste handoff URL", "description": "claude.ai/design URL"},
        {"label": "Paste file path", "description": "Local handoff JSON"},
        {"label": "Cancel", "description": "Abort import"}
      ],
      "multiSelect": False
    }])

フェーズ 1 — 解析と検証

オーケストレーターエージェントに委任します。エージェントは tarball を取得して展開し、README とチャットを読み込み、HTML プロトタイプを解析して、正規化されたペイロードを生成します。ここで解析を再実装してはいけません。実際の tarball に基づくスキーマはエージェントが管理します。

Agent(
  subagent_type="ork:claude-design-orchestrator",
  description="Parse and normalize handoff bundle",
  prompt=f"""Parse the Claude Design handoff bundle at {bundle_input}.

  This is a gzipped tarball (NOT a JSON manifest). Layout:
    <project>/README.md          ← read first
    <project>/chats/*.md         ← read all (load-bearing)
    <project>/project/*.html     ← prototypes (may be absent if incomplete)

  Tasks:
  1. Fetch the bundle (WebFetch if URL → saved .bin path; Read if local file)
  2. Extract: `tar -xzf <bin> -C /tmp/<scratch>/`
  3. Read README.md, then every chats/*.md (intent + clarifications live here)
  4. Compute bundle_id = sha256(canonical bundle URL or absolute path)
  5. If project/ is MISSING → return status="incomplete" with the assistant's
     last unanswered question; do NOT crash. Surface "what user should do".
  6. If project/ exists → pick primary HTML:
     - Prefer the file matching the URL's ?open_file= query param
     - Else first alphabetical
  7. From the primary HTML, extract:
     - Inline `:root { --... }` CSS custom properties as design tokens
     - Component sections (named via class/id/data-screen-label)
     - Asset references (<link>, <img>) — keep as URLs, do not download
     - EDITMODE JSON block (design-time state — capture as ANNOTATION only)
  8. Produce normalized output payload (see agent spec)
  9. Write provenance to .claude/design-handoffs/<bundle_id>.json:
     - bundle_url, bundle_id, fetched_at, status, components: [], pr: null
  10. Return the normalized payload as JSON

  Surface any deviations from the expected tarball layout explicitly.
  Never expect a JSON `components[]` field — that was the old (wrong) shape.
  """
)

フェーズ 2 — トークンの調整

エージェントのペイロードから正規化された token_diff を読み込みます。

差分フィールド操作
addedプロジェクトの design-tokens.json(または Tailwind 設定)に追加します。確認は不要です。追加は安全です。
modified差分を表示します。AskUserQuestion で、プロジェクトの値を維持するか、バンドルの値を採用するか、エディターを開くかを尋ねます。
conflicts足場の生成をブロックします。続行する前に、AskUserQuestion で解決します。
if token_diff["conflicts"]:
    AskUserQuestion(questions=[{
      "question": f"Token conflict on {conflict.path}. Project says {conflict.project}, bundle says {conflict.bundle}. Resolve?",
      "header": "Token conflict",
      "options": [
        {"label": "Keep project value", "description": "Bundle adapts to project"},
        {"label": "Accept bundle value", "description": "Project adapts to bundle (writes new token)"},
        {"label": "Both — namespace bundle's", "description": f"Add as {conflict.path}.imported"}
      ],
      "multiSelect": False
    }])

フェーズ 3 — コンポーネントの重複排除

エージェントはコンポーネントごとに component-search をすでに実行しています。正規化されたペイロードから判断を読み込みます。

decision動作
reuse「スキップ(既存: )」と記録します。ディスク上では何もしません。
adapt--adapt-from <existing-path> のコンテキストを付けて、ork:design-to-code に渡します。
scaffoldバンドルの tsx_scaffold をシードとして、ork:design-to-code に渡します。

フェーズ 4 — 足場の生成

scaffold または adapt と判断された各コンポーネントについて、design-to-code を呼び出します。 スピンアップは同時にバックグラウンドで実行されるため、それぞれが専用の ワークツリー(isolation="worktree"、#4557)を取得します。ork エージェントには frontmatter の isolation がなく、それがなければすべてのコンポーネントが同時にツリーへ書き込みます。

for component in payload["components"]:
    if component["decision"] in ("scaffold", "adapt"):
        # Compose, don't reimplement — design-to-code owns the EXTRACT/MATCH/ADAPT/RENDER pipeline
        Agent(
          subagent_type="ork:frontend-ui-developer",
          name=f"scaffold-{component['name']}",
          description=f"Scaffold {component['name']} from bundle",
          prompt=f"""Use the design-to-code skill to scaffold this component.

          Source: handoff bundle {payload['bundle_id']}
          Component: {component['name']}
          Target path: {component['target_path']}
          Bundle scaffold seed:
          ```tsx
          {component['tsx_scaffold']}
          ```
          Resolved tokens: {component['tokens_resolved']}
          Decision: {component['decision']}
          {f"Adapt from: {component['existing_match']}" if component['decision'] == 'adapt' else ''}

          Write the component, mirror existing project file structure, use project tokens.
          Commit it in your worktree before you return, and end your reply with
          your branch name and commit sha. Uncommitted files are not merged.
          """,
          run_in_background=True,
          isolation="worktree",
          max_turns=25,
        )
コンポーネントのワークツリーを回収してマージする

フェーズ 5 の前に、すべての足場生成エージェントの完了を待ちます。それぞれについて、次の手順を実行します。

  1. ワークツリーがクリーンであることを確認します。git -C <worktree> status --porcelain が 何も出力しないことを確認します。ファイルが出力された場合は、そこでコミットし、レポートに記載します。
  2. そのブランチを現在のブランチにマージします。競合は、2 つのコンポーネントが 同じファイルを書き込んだことを意味します。そこで停止し、両方のパスを報告します。
  3. マージ後に component['target_path'] が存在することを確認します。エージェントが失敗したコンポーネント、 または別の場所に書き込んだコンポーネントは failed_components に入れます。書き込み済みとして記録せず、 報告します。

フェーズ 5 — 出所情報

実際に書き込まれたファイルパスで、出所情報ファイルを更新します。

provenance = Read(payload["provenance_path"])
provenance["components"] = [
    {"name": c["name"], "decision": c["decision"], "path": c["target_path"]}
    for c in payload["components"]
    if c["name"] not in failed_components  # from "Collect and merge" step 3
]
provenance["imported_at"] = now()
Write(payload["provenance_path"], provenance)

出力 — インポートマニフェスト

簡潔な概要を出力します(JSON の羅列にはしません)。

Imported bundle <bundle_id>
  Source: <bundle_url>
  Provenance: .claude/design-handoffs/<bundle_id>.json

Components:
  ✓ PricingCard          scaffold  src/components/pricing/PricingCard.tsx
  ↻ Button               reuse     existing: src/components/ui/Button.tsx
  ⤳ Hero                 adapt     adapted from: src/components/Hero.tsx

Tokens:
  + 3 new (added to design-tokens.json)
  ~ 1 modified (user accepted bundle value)
  ✗ 0 conflicts unresolved

Next: design-ship <bundle_id>   # to open PR
      expect                     # to verify

フック

  • 完了後、post-design-import フックが expect を推奨します(ブロッキングではありません。詳細はフックを参照してください)。

構成

スキル役割
design-to-code足場生成パイプライン(EXTRACT/MATCH/ADAPT/RENDER)を実際に担当します。このスキルはコンポーネントごとに処理を委任します。
component-search重複排除のためにオーケストレーターエージェントが使用します
design-context-extractバンドルに design_tokens ブロックがない場合に使用します
design-system-tokensトークン調整のリファレンス
remember / memory出所情報と過去のインポートの検出

このスキルの担当外

対象担当
PR の作成design-ship
テストの実行post-design-import フック → expect
Storybook ストーリーの生成cover(design-ship から呼び出されます)
Claude Design への再プロンプトまだ未対応 — 公開 API がありません

制限事項

  • Claude Design の公開 API はまだありません:バンドルは一度限りのエクスポートです。反復するには、claude.ai/design から再エクスポートして再インポートしてください。逆方向の処理(差分検出+改良プロンプト)は M124 — Claude Design Drift Sync (Bet B):#1391、#1393、#1394、#1395、#1397 で追跡されています。
  • スキーマは暫定的です:Claude Design は安定したバンドルスキーマを公開していません。オーケストレーターエージェントは差異に対応しますが、形式が安定するにつれて更新が必要になる場合があります。
  • アセット URL は参照されるだけで、ダウンロードされません:バンドルの asset_urls はそのまま保持されます。リポジトリ内に必要な場合は、別途同期の手順を実行してください。

コメント