sb-health について
sb-healthは、デザインシステムのトークンやスタイルを検査し、Storybook表示用の指摘を出力するスキルです。エラーと情報レベルの兆候を区別し、任意でプロパティとトークンファミリーのルールも検証できます。
主な機能
- 01生のカラー値と未定義トークンの検出
- 02トークン使用状況とスケール間隔の確認
- 03CSSトークンとDESIGN.mdの記述の照合
- 04任意のプロパティ・トークン分類ルール検査
- 05Storybook表示用の指摘を出力
活用シーン
- 01トークンに置き換えるハードコード色の特定
- 02未宣言トークンを参照するコンポーネントの確認
- 03設計ブリーフとコードのずれの確認
- 04デザイナー定義のプロパティ・トークン規則の検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ strongeron/ storybook-workbench --skill sb-healthインストール後、Claude Code で/sb-healthを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
CONTEXT.mdagents/openai.yamldecorators/withLayoutFrame.tsxreferences/colors.example.jsoncolors.schema.jsonscripts/check-property-tokens.pyscaffold-wrapper.shvalidate-design-system.shwrappers/DesignSystemHealth.tsxicons.tsxReportIntro.tsxresolve-paint.tsusage-index.tsxusage-stamp.tsx詳細
sb-health — デザインシステムのヘルスゲート
ブラウザーからシェルコマンドを実行できないため、スクリプトがチェックを実行して JSON を書き出し、ラッパーがそれをレンダリングします。
design-system-health.json はレンダリング済みの出力(Health Docs + DesignSystemHealth/TokenMatrix)です。そのため、
refresh-usage.sh はほかのレンダリング済み抽出ツールとともに、このチェックを再実行します。詳しくは CONTEXT.md §STORAGE MAP を参照してください。
実行方法
SKILL=${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}
CORE=${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}
"$SKILL/scripts/validate-design-system.sh" # → .storybook/design-system-health.json
# --emit-prompt also outputs an LLM sub-agent prompt for semantic checks
# (naming drift, semantic-vs-presentational, scale clarity)
"$CORE/scripts/scaffold-wrapper.sh" DesignSystemHealth # → .storybook/wrappers/ (+ icons.tsx)
# Opt-in property→token-family check (off until a designer authors the rules file):
"$SKILL/scripts/check-property-tokens.py" --init # scaffold design-system/lint/colors.json (+ schema)
チェック項目
- raw-color — コンポーネント内の hex/rgba/hsl リテラル(トークンを使うべき箇所)。リテラルの値が既存トークンの解決後の値と一致する場合(例:兄弟要素で
bg-secondaryを使っているタイルの#005596→--secondaryは#005596に解決される)、修正方法は新しいトークンを作ることではなく、その一致するトークンを採用することです。該当するトークンを解決できる場合、検出結果にその名前が表示されるため、修正は「トークンを追加する」ではなく「--xに置き換える」です。 - undefined-token — コンポーネントが、宣言されていない
--fooを参照している - scale-gap — スペーシング/タイポグラフィのスケールに予期しない間隔がある
- unused-token — 宣言されているものの、一度も参照されていない(var、Tailwind ユーティリティ、またはカスタムの
@utility)。ここでは再スキャンせず、sb-inventory の単一のソース(.storybook/project-inventory.json→tokens.map)から読み取ります。これにより、ヘルスチェック、インベントリ、トークンビューの内容が食い違うことはありません。まずsb-inventoryを実行してください。ファイルがない場合、このチェックはスキップされます。 - design-md —
DESIGN.md(Google Labs の YAML トークン+Markdown 形式。エージェントにビジュアルアイデンティティを伝える方法として、ますます一般的になっています)は事実ではなく主張です。AGENTS.mdと同様、コードの変更に伴って内容が古くなったり、最初から誤っていたりすることがあります。スクリプトはこれを検出し、そこに記載された色とコードの CSS トークンで実際に宣言されている色を照合し、コードで定義されていない各色についてdesign-md-driftを出力します。存在するDESIGN.mdは、整合性を確認するまで信頼できないものとして扱ってください。 - property-token-family (オプトイン) — 有効で、宣言済みのトークンが、誤ったプロパティファミリーで使われている場合(例:
color: var(--color-container)— テキスト色としてコンテナ用トークンを使っている)。raw-color は「トークンがない」ケースを検出し、undefined-token は「トークンが存在しない」ケースを検出します。このチェックは「実在するトークンだが、スロットが間違っている」ケースを検出します。デザイナーがdesign-system/lint/colors.jsonを作成するまで無効です(下記参照)。そのため、初期設定のままでも設定不要で使えます。検出結果はwarning/infoのみです。オプトインしても、成功している CI ビルドが失敗に変わることはありません。 stylelintが設定されている場合は実行します
summary(エラー/警告/情報の件数)と主な検出結果を報告します。DesignSystemHealth ラッパーは共通のアイコンセットを使って重大度を表示します(絵文字は使いません)。
書き出される JSON の形式(このフィールドを読み取り、再計算しないでください)。各検出結果は
{kind, severity, message, file?, line?, fix?} で、件数の集計は summary に含まれます。
{
"findings": [
{ "kind": "raw-color", "severity": "error", "file": "Button.tsx", "line": 42, "message": "#3b82f6 literal", "fix": "use --color-primary" },
{ "kind": "undefined-token", "severity": "error", "file": "Card.tsx", "line": 11, "message": "--surface-2 not declared" },
{ "kind": "design-md-drift", "severity": "warning", "message": "DESIGN.md claims #1e90ff; no token declares it" },
{ "kind": "unused-token", "severity": "info", "message": "--legacy-accent declared, never referenced" },
{ "kind": "scale-gap", "severity": "info", "message": "spacing jumps 16px → 48px" },
{ "kind": "property-token-family", "severity": "warning", "file": "Card.css", "line": 3, "message": "background uses --color-content — not allowed for 'background*' (expects --color-container / --color-canvas)", "fix": "Use one of --color-container, --color-canvas, or remap with /* color-lint-alias: … */" }
],
"summary": { "total": 6, "errors": 2, "warnings": 2, "info": 2, "checksRun": ["raw-color", "undefined-token", "..."] }
}
プロパティ→トークンファミリーのルール(任意設定、デザイナーが管理)
どのプロパティにどのトークンファミリーを割り当てるかはデザイン上の意図なので、スクリプトではなく、デザイナーが編集できるルールファイルに記述します。ルールはデザイナーが管理し、リンターは開発者が管理します。最初に一度だけひな形を作成します(ファイルと、どのエディターでも内容がわかるよう自己文書化された JSON Schema の両方が書き出されます)。
"$SKILL/scripts/check-property-tokens.py" --init # → design-system/lint/colors.json (+ colors.schema.json)
// design-system/lint/colors.json — owned by the designer
{
"$schema": "./colors.schema.json",
"propertyTokens": {
"color": ["--color-content"], // exact property
"background*": ["--color-container", "--color-canvas", "--color-backdrop"], // family (trailing *)
"box-shadow": ["--color-border", "--color-shadow"],
"border*": ["--color-border"] // values are token PREFIXES
}
}
対象となるのは、ルールに記載されたプロパティだけです(プロパティを1つずつ有効にします)。回避策は優先順に以下のとおりです。どちらもソースファイルから読み取られます。
/* color-lint-alias: --color-theme --color-container */ /* file-level prefix remap: a token is
semantically right but lives in the "wrong"
family — treat this prefix as that one */
color: var(--color-theme-fg); /* color-lint-ignore */ /* per-line suppression — counted, and the
report nudges a refactor past 10. The number
growing is the signal: mute fast, fix slowly. */
ルールファイル自体も、DESIGN.mdと同様に事実ではなく主張です。ルールで許可されたトークンプレフィックスに一致する宣言済みトークンがない場合、スクリプトはproperty-rules-driftを出力します。これにより、古い設定が問題なく通過したり、誤ったフラグが出たりするのを防げます。
トリアージの順序 — 判定を左右するのは件数ではなく重大度です: まずerrorを修正します(raw-color → 既存のトークンにマッピングする、undefined-token → トークンを宣言するか、タイプミスを修正する)。次にwarningを整合させます(design-md-drift → design-mdに引き継ぐ、property-token-family → 許可されたトークンに置き換える。トークンが本当に適切な場合はcolor-lint-aliasを追加する、property-rules-drift → ルールファイルを修正する)。そして、infoはそのまま報告します(unused-token/scale-gap/property-lint-suppressionsは確認が必要なシグナルであり、自動修正の対象ではありません。「禁止事項」を参照)。エラーが0件でinfoが20件のリポジトリは健全です。
禁止事項(および、見落としがちな理由)
unused-tokenを見つけても、絶対にすぐ削除しないでください — これはerrorではなくinfoです。静的スキャンでは、Tailwindユーティリティ(bg-[--brand])で使われているトークン、文字列結合で実行時に組み立てられるvar()、モノレポ内の別のアプリで使われているトークンを検出できません。「未使用」とは「参照が見つからなかった」という意味であり、「安全に削除できる」という意味ではありません。scale-gapを修正対象の不具合として扱わないでください — これはinfoです。実際のスケールには意図的な間隔があります(本文サイズから大きく離れたディスプレイサイズなど)。「滑らかに」しようとすると、誰も求めていないトークンが作られ、デザイナーが選んだリズムが崩れます。DESIGN.mdを事実として信頼しないでください —AGENTS.md/CLAUDE.mdと同様に、これは主張であり、実態とずれることがあります。まずdesign-md-driftとの整合を取ってください。未整合のDESIGN.mdは、コードで定義されていない色について、確信を持って誤った説明をすることがあります。raw-colorを、新しいトークンを作って「修正」しないでください — 既存のトークンにマッピングします。リテラル値ごとに新しいトークンを作ると、混乱をトークンレイヤーに移すだけです(次回の実行でundefined-tokenのノイズがさらに増えます)。- 再度grepして、このJSONを手作業で計算し直さないでください — ブラウザーからシェルを実行できないため、情報源はスクリプトだけです。各フィールドを参照してください。目視で再計算すると、ラッパーが表示する件数とずれてしまいます。
後回しにする場合
抽出(混乱したコードベースをトークンとコンポーネントに変換する作業)では、このスキルは測定のみを行います。実際に抽出するには、/ds-runbook → /ds-audit → /ds-token-extract → /ds-component-extractを実行してから、ここに戻って健全性を確認し、sb-storiesでキャプチャしてください。
ずれが生じた**DESIGN.mdを扱う場合(または、コードで実際に使われているトークンをもとに新規作成/再生成する場合)は、design-md**スキルに引き継いでください。このスキルはGoogle LabsのDESIGN.md形式を構成、抽出し、詳細に監査します。sb-healthはずれを検出するだけですが、design-mdは概要を整合させるか、書き直します。
次の手順
健全性に問題があり、プロジェクトが移行中であれば、ストーリーを作成する前にトークンを修正するか、ds-*スキルに引き継いでください。それ以外の場合は、検出結果を追記してsb-storiesに進みます。