design-import について
design-importは、Claude DesignのハンドオフバンドルからReactコンポーネントのひな形を作成し、トークン調整、重複確認、プロベナンス記録を行うスキルです。既存プロジェクトへのデザイン取り込み向けで、PR作成やテスト実行は行いません。
主な機能
- 01ハンドオフURLまたはローカルファイルの受付
- 02ハンドオフバンドルの検証と正規化
- 03デザイントークンの調整
- 04既存コンポーネントの再利用または適応
- 05Reactコンポーネントのひな形生成
- 06インポートしたコンポーネントのプロベナンス記録
活用シーン
- 01Claude DesignのエクスポートをReactプロジェクトに取り込む
- 02ひな形作成前にトークンの差異を解決
- 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 の前に、すべての足場生成エージェントの完了を待ちます。それぞれについて、次の手順を実行します。
- ワークツリーがクリーンであることを確認します。
git -C <worktree> status --porcelainが 何も出力しないことを確認します。ファイルが出力された場合は、そこでコミットし、レポートに記載します。 - そのブランチを現在のブランチにマージします。競合は、2 つのコンポーネントが 同じファイルを書き込んだことを意味します。そこで停止し、両方のパスを報告します。
- マージ後に
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はそのまま保持されます。リポジトリ内に必要な場合は、別途同期の手順を実行してください。