Communitygithub.com

Yosegi — ホストのコンポーネントから画面を組み立てる

既存のStorybookコンポーネントからエージェント主導で画面を組み立てるCLI、MCPサーバー、エージェントスキル。GUIはありません。

Yosegi — ホストのコンポーネントから画面を組み立てる とは?

Yosegiは、ホストプロジェクトのReactコンポーネントを事実(fact)として扱い、それらを組み合わせて画面をStory(CSF)として出力するエージェントスキルです。GUIや独自のレンダリング環境を持たず、出力結果はホストのStorybook上で確認します。Storybookがない場合は、代わりにプレーンなReactコンポーネントファイルを生成します。 このスキルは、CLI(`npx yosegi`)とMCPツールの両方で利用可能で、Node.js 20以降、React + TypeScriptのホストプロジェクトに対応しています。主なユースケースは、既存のデザインシステムから画面のモックやプロトタイプを素早く作成し、コードレビュー可能な形でStorybookに追加することです。また、ホストが持つコンポーネントとその実際のPropsを調査するための`component inspect`などの強力な調査機能も提供します。 Yosegiの核心は、コンポーネントのPropsに関する真実の情報源として機能するレジストリにあります。このレジストリは、TypeScript型定義から自動生成され、実際のプロパティ名、列挙型の選択肢、必須・任意の区別、子要素(children)と名前付きスロット(slot)の違い、関数プロパティのシグネチャなどを正確に把握します。これにより、開発者はライブラリの知識や推測に頼らず、ホスト固有のコンポーネントの実態に基づいた画面構築が可能になります。 ワークフローは大まかに3ステップで構成されています。Step 1ではレジストリを構築し、Step 2では使用予定の全コンポーネントを`inspect`コマンドで詳細に調査します。Step 3では、それらの情報を基にStory(またはコンポーネントファイル)を生成します。さらに、データコントラクトの確認や既存画面の調査、`git status`による作業ツリーの確認など、品質を高めるための事前チェックも重視しています。

対応✓Claude Code~Codex CLI~Cursor
npx skills add yosegi-dev/yosegi

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

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

ドキュメント

Yosegi — ホストのコンポーネントから画面を組み立てる は何をしますか?

バージョン: 2026-08-13. エージェントハーネスは古いスキルのコピーを読み込む可能性があります。この日付がリポジトリの skills/yosegi/SKILL.md のものより古い場合、古いコピーを読んでいます — 先に進む前に再インストールしてください。

Yosegiは、ホストプロジェクトのコンポーネントを、画面を構築できる事実(ファクト)に変換し、画面をStory(CSF)として出力します。この出力は、何かを実装する前にレビューするためのものです。自身のレンダリング環境やGUIは持たず、見た目はホストのStorybookで確認します。Storybookがないホストでは、成果物はプレーンなReactコンポーネントファイル(--target component)になります — 以下のステップ1のブランチで、手順がどのように変わるかを説明します。

このドキュメントは手順そのものであり、あなたはそれを実行する主体です。CLI(および同等のMCPツール)は、その手順が利用する道具です。

使用するタイミング

  • 既存のデザインシステムから、レビュー可能な形で画面の提案やUIモックを構成する。
  • 新しい画面の最初のドラフトを、実装前にStorybookで確認できるようにする。
  • ホストがどのコンポーネントを持ち、それらが実際にどんなPropsを受け取るのか、UIを書き始める前に調査する。
  • 承認されたモックStoryを実際のページに書き起こす。ステップ1と2を実行し、ステップ5に進んでください。

以下の用途には適しません: 単発のコンポーネント変更。

価値の源泉

レジストリの役割は狭く定義されています。それは、コンポーネントのPropsに関する真実の情報源です — 実際のプロパティ名、実際の列挙型の選択肢、必須のもの、スロットとchildrenの違い、関数プロパティの呼び出しシグネチャ。ホストのコンポーネントは、それらがフォークされた元のライブラリとは異なります。バリアントの列挙型は名前が変更されており、サイズのスケールは兄弟間で異なり、アイコンのPropsは要素ではなくコンポーネント参照を受け取り、ReactNode型のPropsはchildrenではなく名前付きスロットであり、3つの異なるコンポーネントが同じエクスポート名を共有しています。これらのどれも、Reactや上流のライブラリに精通していることから導き出すことはできません。そして、これらのそれぞれが、レジストリが存在すると言っているPropsではなく、自分が期待するPropsを記述した場合に、あなたが出荷することになる欠陥です。これが、ステップ1と2のinspect呼び出しの目的であり、それらをスキップすることは、もっともらしいモックに欠陥を出荷する方法です。

レジストリは、画面のスケルトン、構成イディオム、レイアウトを提供しません — DataGridを駆動するグリッドライブラリのフック呼び出し、{ stickyHeader: true } のようなホスト固有のmeta、コンポーネントが期待するラッパー。これらはホスト自身のStories、および(ページ/ルートジェネレーターを持つホストの場合)そのExampleテンプレート(ステップ2)から得られます。ホストのテンプレートとStoryのカバレッジが豊富であればあるほど、画面を構築するために実際に必要なもののうち、レジストリが占める割合は小さくなります — そしてそれは欠陥ではありません。レジストリとホスト自身の例は異なる質問に答え、それぞれが答える質問に対して重要な役割を担っています。

リファレンス

以下の手順が参照を指示した場合にのみ開いてください。事前に開く必要はありません。3aのルート(Storyを直接書く)では、決して開かないかもしれません: registry statusとcomponent inspectの出力とこのファイルの本文だけで、通常は画面全体を構築するのに十分です。ただし、一度必要になったら、このファイルだけの記憶に頼らず、リファレンスから作業してください — このファイルに詳細は繰り返されていません。

ファイル読むタイミング
references/registry.mdinspectの出力に解釈できないものがある場合 — 不明瞭なPropsのshape: / signature:行、ドキュメント化されていないProps、間違っているように見えるインポート指定子
references/cli.md上記でカバーされていないコマンドやフラグがある場合、CLIが実行されない場合、またはMCP相当のものがが必要な場合
references/screen-json.mdScreen JSONルート(3b)を採用した場合のみ。そのフォーマットと、表現できないもの
references/errors.mdコマンドがエラーまたは警告を出力した時。すべてのコードとその修正方法
references/implementation.mdステップ3のメタテンプレート用、およびステップ5の前

ステップ1. レジストリを構築する

Yosegiはホストから読み取り可能なtsconfig.jsonを必要とします(PropsはTypeScriptの型から取得され、それだけで十分です)。StorybookはStoryの出力先であり、レンダリング結果を確認する場所ですが、必須要件ではありません。

Storybookを検出できない場合 — .storybook/(または同等の)設定ディレクトリがない、ホストのpackage.jsonにstorybookスクリプトがない、--indexで指定するindex.jsonがない — 出力はStoryではなくプレーンなReactコンポーネントファイルになります (screen generate --target component、references/cli.md)。出力場所や確認方法を自分で決めないでください。何かを構築する前に、ユーザーに (a) コンポーネントファイルの出力先、および (b) 結果を確認する方法(ホストアプリのスクラッチルートでレンダリングするなど)を尋ねてください。Yosegiは確認手段を規定しません。どちらかの答えを推測することは、Propsを推測するのと同じルール違反です。これらの答えがあれば、以下の手順は同じですが、3つの違いがあります: registry buildは--index / --storybook-urlなしで実行されます(キュレーションは失われますが、それ以外は変わりません)。3aのルートでは、ユーザーが指定した場所にコンポーネントファイルを記述します。3bのルートでは、--target component --out <その場所>.tsx を渡します。そしてステップ4のStorybookチェックは、ホストの型チェックとユーザーが指定した確認方法に置き換えられます。

  1. CLIを実行できますか? npx yosegi(またはpnpm yosegi、yarn yosegi、bunx yosegi)を引数なしで実行すると、すべてのコマンドが表示されます。ただし、@yosegi/yosegiがすでにホストの依存関係にある場合に限ります — ない場合は最初にインストールしてください(references/cli.md)。Node.js 20以降、React + TypeScriptホストが必要です。コマンドが失敗する場合は、references/cli.mdの「CLIが実行されない場合」を参照してください。最も有用な方法の一つは、以前のセッションからレジストリが既に存在する場合、<data-dir>/registry.jsonのbuiltWithCliPathを読むことです。
  2. 今すぐ--data-dirを設定し、すべてのコマンドに同じものを渡してください。ホストのパッケージルートの下の.yosegiを使用してください。これはデフォルトでもあります。以下の例ではまだ明示的に記述しています。なぜなら、デフォルトはカレントワーキングディレクトリに従い、別の場所から実行されたコマンドは構築したものを見つけられないからです。
  3. レジストリは既に存在しますか、そしてそれは最新ですか? 最初に yosegi registry status --data-dir .yosegi を実行してください。これは記録された入力からレジストリのバージョンを再計算し、source: current または source: stale を正確な再構築コマンドとともに報告します。component listのヘッダーを目視で確認する必要はありません。「Registry not found」は初回実行であることを意味します。そのStorybookインデックス部分はベストエフォートであり、インデックスが到達不能でもソースの判定は有効です。その半分は「確認できなかった」と読み、「古い」や「最新」とは読まないでください。また、開発サーバーが到達不能でも、currentというソース判定を信頼することを妨げさせないでください。statusがstaleを報告した場合、REGISTRY_VERSION_MISMATCHが表示された場合、またはstatusがsource: unknownを報告した場合(レジストリが記録された入力を先行しているため built: not recorded となる — そこから再計算できるものは何もないため、経過時間が唯一のシグナルです)は、再構築してください。また、コマンドが、レジストリが現在実行しているものとは異なるYosegiバージョンで構築されたことを警告した場合も再構築してください。古いYosegiは、現在のYosegiが出力できるフィールド(例えば関数プロパティの呼び出しシグネチャ)を出力できません。そして、このギャップを示す他のシグナルはありません。バージョン文字列はコンテンツハッシュであるため同一のままなので、変更されていないホストから再構築されたレジストリは同じバージョンを維持します。レジストリはスナップショットであり、古いものはないより悪いです。
yosegi registry build \
  --source "app/components/**/*.tsx" \
  --tsconfig <host>/tsconfig.json \
  --index http://localhost:6006/index.json \
  --storybook-url http://localhost:6006 \
  --report tmp/registry-report.json \
  --data-dir .yosegi

上記の6006はStorybook自身のデフォルトであり、これが初回ビルドで他に情報がないために使用されています — 必ずしもホストのポートではありません。実行する前に、ホストのpackage.jsonのStorybookスクリプトを確認する(または尋ねる)して、実際に使用されているポートを確認してください。最初のビルド以降のすべての再ビルドは、推測よりも優れた情報源を持っています: component listのヘッダーには、レジストリが最後に構築されたときに使用された正確な--storybook-urlを保持するrebuild:行が出力されます(references/cli.md)。

フラグとデフォルトはreferences/cli.mdにあります。--indexは前提条件がある唯一の部分です: 開発サーバーのURLは、ホストのStorybookが既に実行されている必要があることを意味します。それがなければ、Storyから派生したカテゴリとrecommendedマークが失われるだけで、他には影響しません。

出力される統計情報を読んでください:

  • files: 0 → グロブが何にもマッチしませんでした。コマンドは成功し、3つの合成プリミティブのみを保持するレジストリを書き込みますので、「Wrote 3 components」を成功と読まないでください。
  • filesが正の値でcomponentCandidates: 0、またはanyShapedPropsが多い状態でwithNodeSlots: 0 → ビルドは成功したにもかかわらず劣化しています。前者はグロブがReactコンポーネントをカバーしていないことを意味します。後者は@types/reactが解決されず、すべてのReactNode Propsがjsonにフラット化され、スロットが検出されなかったことを意味します。Warning:行は両方の場合の修正方法を示しています — 解決してから再構築してください。
  • extractedComponentsに比べてpropsUnreadableが多い → tsconfigがおそらく間違っています。今すぐ解決してください(references/cli.md、registry metadata)。その状態のコンポーネントは、後で完全に有効なPropsを拒否します。

ステップ2. 使用する予定のすべてのコンポーネントを調査する

ページ/ルートジェネレーターのExampleテンプレートが、構築しようとしている画面に最も近い場合、それを最初に、または以下のコマンドと並行して読んでください。それがスケルトンと構成イディオムを決定し、レジストリはテンプレートが未定義のままにしている正確なPropsを確認します。

yosegi component list --category app/components/ui --data-dir .yosegi
yosegi component list --query card --data-dir .yosegi
yosegi component inspect "app/components/ui/button#Button" --data-dir .yosegi

レジストリは数百のエントリに及ぶ可能性があるため、--category / --queryで絞り込み、サマリーで見当をつけてから、記述しようとしているすべてのコンポーネントをinspectしてください。inspectが信頼できる情報源であり、あなたのフレームワーク知識はそうではありません。 references/registry.mdを読んで、それが提供するもの — 列挙型の選択肢、不明瞭なPropsの下のshape:とsignature:行、ホストが実際に記述するインポート指定子、ドキュメント化されていないPropsの意味 — を解釈する方法を学んでください。

recommendedとマークされたコンポーネントを優先してください。それらは独自のStoryを持っています。

次に、ホストの規約を収集します。Storyはホストのリポジトリに配置され、ホストのコードとしてレビューされます。これをスキップすると、動作するUIが生成されても、差し戻されることになります。

  • データ契約が既に存在する場合はそれを見つけてください — OpenAPI/JSON Schema定義、GraphQLスキーマ、APIレスポンス用の手書きTypeScript型、ホストのデータレイヤーが使用する任意の形式。モックデータをでっち上げる前に読んでください。それはコンポーネントPropsよりも多くのことを決定します: どのフィールドが必須でどのフィールドがnull許容か、そして特定のフィールドにとってnullが何を意味するか(nullの制限は「無制限」を意味する場合があり、「不明」ではありません)、どのフィールドが相互に排他的か、そして同様に有用なことに、何が存在しないか(契約にソートや検索フィールドがない場合、画面もそれを発明すべきではありません)。これがモックをルックアンドフィールの提案から、実際のデータ形状を反映するものに変えます。その場所はホストによって異なります(openapi/schemas/、.graphqlファイル、生成されたtypes.ts)。このドメインに存在するものを見つけ、もっともらしそうな推測よりもそれに従ってください。
  • ホストのルート/ページディレクトリ(app/routes/、またはページを提供する場所)を検索して、同じドメインの既存の画面を探してください。成熟したプロダクトではしばしば存在し、それを見つけることでタスク全体を再構成できる可能性があります。例えば、既存のbookings.calendar._indexルートは、「予約画面を作成する」を「既存の予約フローに対する横断的なリストを提案する」に変えるかもしれません。これは、あなたが依頼されたモックがそもそも構築すべき正しいものかどうかを判断します。そのため、以下のチェックポイントの前に行い、そこで尋ねる質問を形作るようにしてください。
  • git statusを実行し、何かを構築する前に出力ディレクトリを確認してください。 同じ画面の以前のコミットされていない試みが、既にワーキングツリーに存在する可能性があります — コンテキストリセットと再発行されたリクエストの後によくあることです。その隣に重複を作成するのではなく、それと調整してください。既に存在するファイルをやり直す場合 — ホストジェネレーターがターゲットパスが存在する場合に拒否する、または以前の試みを置き換える必要がある場合 — 削除するのではなく、脇に移動(リネーム)してください。削除はあなたに利用できない可能性があり、リネームはいずれにせよパスをクリアします。
  • ホストに新しいページや画面用のジェネレーターがあるかどうかを確認してください — plop/hygenジェネレーター、bun add-routeスタイルのスクリプト。多くの場合、ホストのAGENTS.mdまたはpackage.jsonスクリプトに文書化されています。これがあるホストでは、新しい画面ファイルをゼロから手書きすることは間違っています。ジェネレーターは承認されたテンプレートをクローンし、ファイルと命名規則を強制するため、自分でファイルを作成する代わりにそれを実行してください。これにより、ステップ3の選択(インラインツリーのStoryか、ページモジュールと薄いラッパーStoryか)も決まります。このようなジェネレーターを持つホストは、ほとんどの場合後者を望みます。
  • リポジトリルートから出力ディレクトリまでのすべてのレベルでAGENTS.md / CLAUDE.mdを読み、それらが指すドキュメントに従ってください。
  • 出力場所の近くにある1つか2つの既存のStoryを読んでください。複数のコンポーネントを組み合わせた構成例は、ページのスケルトン、間隔、コンポーネント選択を模倣する価値があります。構成イディオム — コンポーネントがどのように実際に組み立てられるか、単にどのPropsを受け取るかだけでなく: DataGridを駆動するグリッドライブラリのフック呼び出し、{ stickyHeader: true } のようなホスト固有のmeta、コンポーネントが期待するラッパー — 既存のStoryが真実の情報源であり、レジストリはそうではありません。 レジストリは component inspect の meta フィールドにStoryメタデータを含めますが、それはStoryファイル自体に直接アクセスする代わりにはなりません。

チェックポイント。あなたは画面を構築する準備ができていますか?

ステップ2の調査結果を1〜2文に要約し、以下の点を確認してください:

  • あなたが inspect を使用したかどうか(「はい、すべての候補を調べました」または「Storyを読んだだけで、Propsは明確でした」)。
  • あなたが見つけたデータ契約(「見つかりませんでした — ダミーデータを使用します」は許容されますが、明示的に言及してください)。

これがこの手順のゲートです。ここで停止しても構いません。停止した場合、次のように言ってください: 「必要なものはすべて揃っています。[number]のコンポーネントを調査し、スケルトンを特定しました。[Story / データ契約 / 既存画面] を読みました。準備ができたら、ステップ3に進むように言ってください。」

ステップ3. 画面を生成する

ここには2つのルートがあります。どちらかを選択し、もう一方は無視してください。

ルート3a(推奨): 自分でStoryを書く

ルート3aでは、Storyファイルを直接記述します。以下の内容を使用します:

yosegi component inspect --list-write app/components/ui/button#Button,app/components/ui/card#Card,app/components/data-table/DataTable#DataTable --data-dir .yosegi

--list-writeは、指定された各コンポーネントの完全なinspect出力をファイルに出力します。これにより、Propsの詳細を簡単に参照しながらStoryを記述できます。

Storyファイルを作成する際は、以下のテンプレートに従ってください:

import type { Meta, StoryObj } from '@storybook/react';
import { Button } from 'app/components/ui/button';
import { Card } from 'app/components/ui/card';
import { DataTable } from 'app/components/data-table/DataTable';

const meta = {
  title: 'Screens/MyNewScreen',
  component: MyNewScreen,
  parameters: {
    layout: 'fullscreen',
  },
} satisfies Meta<typeof MyNewScreen>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
  args: {
    // ここにPropsを記述。inspectの出力を参照。
  },
};

MyNewScreenコンポーネントは、画面全体をレンダリングする関数コンポーネントであり、Storyファイル内で直接定義されます。このコンポーネントは、調査したコンポーネントを使用して完全な画面レイアウトを構築します。

ルート3b(代替): Screen JSONを使用する

yosegi screen generate --screen screen.json --data-dir .yosegi

Screen JSON形式の詳細については、references/screen-json.mdを参照してください。このルートは、画面の構造をJSONで定義し、YosegiにStoryの生成を完全に任せたい場合に適しています。

ステップ4. 結果を確認する

生成されたStoryをホストのStorybookで開いて確認してください。npx storybookまたは同等のコマンドでStorybookサーバーを起動し、作成したStoryが正しくレンダリングされ、すべてのコンポーネントが期待通りに動作することを確認します。

Storybookがない場合の確認方法: ユーザーが指定した確認方法に従ってください(例: ホストアプリのスクラッチルートにコンポーネントをレンダリングする)。

ステップ5. 実装に進む(オプション)

承認されたモックStoryを実際のページに書き起こす場合:

  1. 実装の詳細についてはreferences/implementation.mdを参照してください。
  2. Storyファイルを、ホストのルーティングシステムに対応する実際のページコンポーネントに変換します。
  3. データ契約に基づいて、実際のデータフェッチロジックを追加します。
  4. 承認されたStoryの構造とPropsを厳密に守ってください。

エラー処理

コマンドがエラーや警告を出力した場合、最初にreferences/errors.mdを確認してください。すべてのエラーコードとその修正方法が文書化されています。

最も一般的な問題:

  • REGISTRY_VERSION_MISMATCH: レジストリを再構築してください。
  • CLIが実行されない: references/cli.mdの「CLIが実行されない場合」を参照。
  • TypeScriptエラー: tsconfigのパスが正しいことを確認してください。

ベストプラクティス

  • 常に--data-dirを設定し、すべてのコマンドで同じものを使用してください。
  • inspectを信頼し、フレームワークの知識による推測を避けてください。
  • データ契約、既存の画面、AGENTS.md / CLAUDE.mdを常に確認してください。
  • --reportフラグを使用して、レジストリビルドの詳細なレポートを生成し、潜在的な問題を早期に発見してください。
  • --no-progressフラグを使用して、出力をクリーンに保ち、パイプ処理を容易にしてください。

関連スキル