Communitygithub.com

gslvly/sketch-inspector

AIフレンドリーなSketchデザインパーサー。Sketchドキュメントを構造化JSON、書き出しアセット、実装可能なLayoutIR(flex/grid/absolute/leaf)に変換し、LLMエージェントがSketchデザインをHTML/CSS、React、Vueに変換できるようにします。Claude Code、Cursor、opencodeと互換性のあるエージェントスキルです。

sketch-inspector とは?

このスキルは、AIエージェントがSketchデザインファイルを解析し、実装可能なコードに変換するための強力なツールです。Sketchドキュメントから構造化JSON、書き出しアセット、そしてLayoutIR(flex/grid/absolute/leaf)を生成することで、デザインのレイアウト情報を正確に抽出し、HTML/CSS、React、Vueなどのフロントエンドコードへの変換を支援します。主なユースケースは、Sketchデザインからのページ実装で、スキャン、パス決定、アセット書き出し、レイアウト推論、そしてファイルサイズに応じた実装フロー(小ファイルは直接実装、大ファイルは分割実装)を厳格に踏む必要があります。このスキルはClaude Code、Cursor、opencodeなどの主要なAIエージェントプラットフォームと互換性があり、Sketch MCPサーバーを介して動作します。特に、3000行を超える大きなJSONファイルを効率的に処理するための分割フローを備えており、大規模なデザインデータでも確実に実装できます。

対応✓Claude Code~Codex CLI✓Cursor✓OpenCode
npx skills add gslvly/sketch-inspector

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

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

ドキュメント

Sketch インスペクター

Sketchデザインを構造化データ、画像リソース、実装可能なページセクションに変換します。

使用シナリオ

  • 開かれているSketchドキュメントまたは特定のレイヤーを検査する
  • 構造、スタイル、テキスト、色、レイアウト、リソース情報を抽出する
  • Sketch領域に基づいてHTML/CSS、React、Vue、またはその他のページを実装する

前提条件

  • Sketchが実行中であり、対象のドキュメントが開かれている
  • Sketch MCPが有効になっている:General -> Allow AI tools to interact with open documents
  • MCPサービスアドレス:http://localhost:31126/mcp
  • Sketch Run CodeはJavaScriptCore/CocoaScript環境で動作し、通常のNode.jsではない

ページ実装の強制フロー

Sketchからページを生成する際には、以下のフローを厳密に実行する必要があります。これが唯一最速でタスクを完了する方法であり、いずれかのステップが欠けると失敗と見なされます。

1. スキャン

ページまたはターゲットコンテナの浅い輪郭を抽出し、ルートノードの layerId を確認します。

2. パスの決定

  • imageOutputDir:プロジェクトの画像ディレクトリ。既存の images/、assets/images/、public/images/ などを優先的に使用します
  • workTmpDir:一時ディレクトリ。少なくとも result.json を配置します。大きなファイルを分割する場合は、manifest.json、セクションJSON、セクションHTMLも配置します

3. 書き出し

sketch_run_code で書き出しスクリプトを実行します。

const sketch = require('sketch');

// パラメータ準備
const layerId = '<ターゲットレイヤーのlayerId>'; // ステップ1のスキャンで取得したターゲットルートノードID
const outputDir = '<imageOutputDirの絶対パス>';  // 例: '/Users/edy/project/images'
const outputJsonPath = '<workTmpDir/result.jsonの絶対パス>';  // 例: '/Users/edy/project/tmp/result.json'

// 書き出しスクリプトを実行
const exportScript = require('@scripts/export-text-split-assets.js');
const result = exportScript.runExportTextSplitAssets({
  layerId: layerId,
  outputDir: outputDir,
  outputJsonPath: outputJsonPath
});

// 結果を出力(デバッグ用)
console.log(JSON.stringify(result, null, 2));

戻り値:

  • 成功:書き出し統計情報を返す
  • 失敗:エラー情報を返す。layerId が有効か、パスに書き込み権限があるかを確認する

注意:

  • スクリプトはSketch JavaScriptCore環境で動作し、通常のNode.jsではない
  • パスは絶対パスである必要がある
  • 出力ディレクトリは事前に存在している必要があり、スクリプトが自動で作成することはない

4. レイアウト推論と result.json の上書き

シェルで実行:

npx tsx @scripts/sketch_layout_ir_inference.ts \
  <workTmpDir>/result.json \
  <workTmpDir>/result.json

このステップでは、書き出された元の構造を直接実装可能な統一レイアウトJSONに変換し、元の result.json を上書きします。

出力される統一 result.json の構造:

  • kind: flex | grid | absolute | leaf
  • direction: row | column(flexのみ)
  • gap: 子要素の間隔
  • padding: 内側の余白 { top, right, bottom, left }
  • justifyContent: flexの配置方法
  • alignItems: 交差軸の配置方法
  • hasAbsoluteChildren: flex/grid コンテナに直接の absolute 子ノードがある場合 true
  • css.position: "relative":flex/grid コンテナに直接の absolute 子ノードがある場合に明示的に出力
  • columns / rows: グリッドの列数/行数(gridのみ)
  • source: 現在のレイアウトノードに対応する実装補足データ。sourceClass / asset / background / style / decision / backgroundLayers / derivedFrom などの非レイアウトフィールドのみ保持

5. レイアウト推論後の分岐判断

レイアウト推論が完了したら、感覚で実装方法を決めてはいけません。統一された result.json の実際の行数に基づいて分岐する必要があります。

  • result.json の行数が 3000 以下:result.json 全体を読み込んで実装を完了し、分割は行わない
  • result.json の行数が 3000 を超える:「大ファイル分割フロー」に進む必要があり、JSON全体をそのまま後続の実装ステップに渡すことは禁止

行数確認の例:

wc -l <workTmpDir>/result.json

6. 小ファイルのメインフロー:直接実装

適用条件:result.json の行数 <= 3000

コアルール(MUST FOLLOW):

  1. 通常のレイアウトにabsoluteを使用してはならない:kind: "absolute" のノードのみ絶対配置を許可
  2. 直接のabsolute子ノードがある場合、result.json の位置情報を信頼する必要がある:ノードが hasAbsoluteChildren: true または css.position: "relative" を出力している場合、実装時にその親コンテナに位置指定状態を設定しなければならず、無視してはならない

生成フロー:

  1. 完全な result.json を読み込む
  2. レイアウトツリーを再帰的に走査する
  3. kind に応じて対応するCSSを生成する:
    • flex: display: flex; flex-direction: {direction}; gap: {gap}px; ...
    • grid: display: grid; grid-template-columns: repeat({columns}, 1fr); ...
    • absolute: position: relative; 子要素 position: absolute;
    • leaf: レイアウトなし、内容をレンダリングするのみ
  4. 現在のノードの source を直接使用して、テキスト、画像、背景、スタイル、決定事項を実装し、古い構造JSONを再参照しない

7. 大ファイルのメインフロー:分割 -> 単一セクション実装 -> 差し戻し集約

適用条件:result.json の行数 > 3000

7.1 JSONの分割

シェルで実行:

node @scripts/split-result-json.js \
  --inputJsonPath=<workTmpDir>/result.json \
  --outputDir=<workTmpDir> \
  --assetBasePath=images/ \
  --splitStrategy=auto

出力:

  • <workTmpDir>/manifest.json
  • 複数のセクションJSON
  • 取り決められた implementationPath、htmlMarker、cssMarker
  • manifest.json.root.layoutIR:ページのメインレイアウトセマンティクス概要
  • manifest.json.sections[].layoutIR:セクションノード自身のレイアウトセマンティクス概要

7.2 単一セクションの実装

各セクションは自身の jsonPath のみを読み取り、manifest.json に従って自身の implementationPath に書き込む必要があります。

強制ルール:

  • 単一セクションの実装フローは @references/single-section-workflow.md を参照
  • セクションファイルはフラグメントである必要がある:1つの <section> + 1つの <style>
  • セクション内では内部構造と内部スタイルのみを記述し、メインレイアウトコンテナの外側のマージンを定義しない
  • 非ルートセレクターは className でスコープ分離を行う必要がある
  • 深い検査が必要な場合のみ @scripts/inspect-single-section.js を使用する

7.3 差し戻し集約

すべてのセクションの実装が完了したら、各セクションフラグメントをメインレイアウトファイルに差し戻す必要があります。マーカーコンテンツを手動でコピー&ペーストしてはいけません。

メインレイアウトファイルは事前に以下を満たしている必要があります:

  • htmlMarker がページ構造内でセクションを挿入する位置にある
  • cssMarker がメインレイアウトファイルの <style> ブロックの内部に配置されている必要があり、他のタグ、コメントブロックの外側、または本文構造内にあってはならない
  • HTMLとCSSが別ファイルの場合、cssMarker は cssLayoutPath が指すCSSファイルに配置されている必要がある

シェルで実行:

node @scripts/replace-section-placeholder.js \
  --layoutPath=/path/layout.html \
  --sectionPath=/path/01-section.html \
  --htmlMarker="<!-- 01-section HTML -->" \
  --cssMarker="/* 01-section CSS */"

HTMLとCSSが異なるファイルの場合は、追加で --cssLayoutPath を渡します。

8. 実装チェックリスト

実装前に確認:

  • result.json を完全に読み込んだ
  • 各ノードの kind フィールドを確認した
  • meta.background の背景レイヤー情報を確認した
  • テキスト、画像、レイヤー関係を確認した
  • ブランドアセットと複雑なビジュアルグループを特定した

9. 納品

客観的な成果物を報告します:

  • レイアウトの輪郭とターゲット領域ID
  • result.json のパスと実際の行数
  • 「小ファイル直接実装」と「大ファイル分割フロー」のどちらを使用したか
  • 分割フローを使用した場合:manifest.json のパス、セクション数、差し戻し対象ファイルのパス
  • レイアウトタイプの統計(flex/grid/absolute/leafの数)
  • 書き出しリソースの一覧
  • 生成されたHTML/CSSファイルのパス

「視覚的に確認済み」など、機械では判断できない結論を出力しないでください。

固定スクリプト

スクリプトのパラメータと戻り値の構造は @references/script-api.md を参照してください。

  • @scripts/export-text-split-assets.js:画像とJSONを書き出します。必須パラメータは layerId、outputDir
  • @scripts/sketch_layout_ir_inference.ts:レイアウトを推論し、統一された result.json を出力します
  • @scripts/split-result-json.js:大ファイルメインフロースクリプト。manifest.json と複数のセクションJSONを生成します
  • @scripts/replace-section-placeholder.js:大ファイルメインフロースクリプト。セクションの実装をメインレイアウトファイルに差し戻します
  • @scripts/inspect-single-section.js:セクション情報が不足している場合に部分的な深い検査を行います

禁止:書き出しスクリプトを自作する、スクリプトのソースコードをコピーする、走査ロジックを再実装する。

LayoutIR タイプ説明

type LayoutKind = 'leaf' | 'flex' | 'grid' | 'absolute'

interface FlexIR {
  kind: 'flex'
  direction: 'row' | 'column'
  gap: number
  padding: { top, right, bottom, left }
  justifyContent: 'flex-start' | 'center' | 'flex-end' | 'space-between'
  alignItems: 'flex-start' | 'center' | 'flex-end' | 'stretch'
  children: LayoutIR[]
}

interface GridIR {
  kind: 'grid'
  columns: number
  rows: number
  columnGap: number
  rowGap: number
  padding: { top, right, bottom, left }
  children: LayoutIR[]
}

interface AbsoluteIR {
  kind: 'absolute'
  children: LayoutIR[]  // 子要素は絶対配置が必要
}

interface LeafIR {
  kind: 'leaf'
  text?: string
  css: { width?, height? }
}

リソース書き出しルール

  • 画像は imageOutputDir に出力し、一時JSONは workTmpDir に配置する
  • 画像ファイル名はMD5の最初の8文字を使用し、同じ画像は再利用する
  • asset/exports は path、src、x、y、width、height のみ保持する。コード生成時は path ではなく src を参照する
  • JSONからは空の値および値が 0 のstyleフィールドを削除する
  • デフォルトで非表示レイヤーはフィルタリングする
  • 実際のテキストを含むノードは分割する必要があり、画像として一括書き出ししてはならない
  • 通常の背景Rectangleはコードで再構築する。ブランドアセットや複雑なビジュアルグループは、忠実度を優先して書き出す

参照インデックス

  • @references/export-assets.md:リソース書き出しルール
  • @references/script-api.md:スクリプトのパラメータと戻り値の構造
  • @references/single-section-workflow.md:単一セクションの実装フロー

関連スキル