@tabula-css/cli
tabula コマンドラインツール: build、build --check、check:css、scan、migrate、except add、eject、doctor、explain、canary。
インストール
npm install --save-dev @tabula-css/cli開発時依存です — tabula はビルド時および CI 用のツールです。@tabula-css/core、@tabula-css/tokens、@tabula-css/registry、@tabula-css/preset、@tabula-css/stylelint-plugin を依存関係としてバンドルしているため、CLI 単体をインストールするだけで以下のすべてのコマンドを実行できます。@typescript-eslint/parser は通常の依存関係として同梱されます。eslint は任意のピア依存で、tabula canary にのみ必要です。
概要
tabula は、ほとんどのプロジェクトが使用するエントリーポイントです。tabula build はトークンと tabula.config.json を読み込み、生成される .tabula/ アーティファクト一式全体を導出します — これは、フラットなトークンプロファイルを、他のすべて(@tabula-css/merge、ESLint プラグイン、MCP サーバー)が読み取る閉じた語彙へと変換するステップです。他のコマンドは、その出力にドリフトがないか再チェックしたり、語彙外のクラスがないかソースファイルをスキャンしたり、CSS ガバナンスを強制したり、既存のコードをプロファイルへ移行したり、スコープ付きの例外を登録したり、診断コードをオフラインで説明したりします。
すべてのコマンドは 1 つの終了コード契約(packages/cli/src/types.ts)を共有します: 0 プロジェクトはクリーン、1 プロジェクトが契約に違反している(ツールは正しく動作したが、スタイリングが誤っている)、2 ツール自体が実行できなかった(不正な入力、プロジェクトが見つからない、内部エラー)。--format=json は、標準出力に機械可読なエンベロープ { tabula, ok, inputsHash, diagnostics } だけを出力し、先頭に人間向けのログが付くことはありません — これは、tabula build --format=json を JSON パーサーにパイプするエージェントが依拠する不変条件です。
build
npx tabula build
npx tabula build --checktokens/*.tokens.json と tabula.config.json を読み込み、アーティファクト一式全体を導出し、それをアトミックに .tabula/ へ書き込みます(検証に失敗した場合は何も書き込まれません)。アーティファクトの一覧とビルドの inputsHash を出力します。
| Flag | Default | Meaning |
|---|---|---|
--check | off | メモリ上で再生成し、コミット済みの .tabula/ とバイト単位で差分比較します。scan ゲートと CSS ガバナンスゲートも実行します。ディスクには何も書き込みません。ドリフトまたはゲートの検出があれば exit 1。 |
--backend a|b|conform | b | レジストリバックエンド: a(デザインシステム API)、b(PostCSS プローブシートウォーク)、または conform(両方を実行し、一致することを表明)。 |
--out <dir> | .tabula | 出力ディレクトリ。 |
--no-scan | off | --check と併用時、scan ゲートをスキップ(ドリフト比較のみ)。 |
--no-css | off | --check と併用時、CSS ガバナンスゲートをスキップ(ドリフト比較のみ)。 |
--css-entry <path> | — | 繰り返し指定可能。CSS ガバナンスゲート向けの追加の許可されたエントリスタイルシート。check:css に引き渡されます。 |
--css-ignore <dir> | — | 繰り返し指定可能。.css ファイルを探索する際にスキップする追加のディレクトリ名。 |
--check は、この順序でドリフト比較 → scan ゲート → CSS ガバナンスゲートを実行します — そのため、--check の下での scan または CSS の検出は常に「ソースが誤っている」ことを意味し、「レジストリが古かった」ことを意味することは決してありません。マニフェストが名前を挙げていない .tabula/ 内の迷子ファイルもドリフトとしてカウントされます。
npx tabula build --check --backend conformcheck:css
npx tabula check:cssすべてのプロジェクト .css ファイル(scan のソース glob だけでなくツリー全体を歩き、固定の無視リストを除く)と .tabula/ 内の出力済みスタイルシートをパースし、@tabula-css/stylelint-plugin のカーネルにある 5 つの CSS ガバナンスルールを実行します — エディタプラグインが実行するのと同じルールコードなので、両者が食い違うことはありません。検出があれば exit 1。
| Flag | Default | Meaning |
|---|---|---|
--out <dir> | .tabula | 出力済みスタイルシート(theme.css、profile.css、source.css)を読み込む場所。 |
--css-entry <path> | 慣例的なリスト(src/app.css、src/index.css、app/globals.css など) | 繰り返し指定可能。許可されたエントリスタイルシートを指定します。手書きルール禁止からのみ除外されます。 |
--css-ignore <dir> | node_modules、dist、build、coverage、.git、.next、.turbo、.vitest、var | 繰り返し指定可能。探索の際にスキップする追加のディレクトリ名。 |
このコマンドが強制する 5 つのルール(TAB-E221–TAB-E225)については @tabula-css/stylelint-plugin を、このゲートがカバーする範囲としない範囲については CSS governance を参照してください。
scan
npx tabula scanプロジェクトのソース glob に対して Tailwind 自身のスキャナー(@tailwindcss/oxide)を実行します — CSS ビルドが使うのと同じ抽出です — そして、未登録かつユーティリティ形状(解決可能なバリアントチェーン、登録済みファミリープレフィックス、禁止リストへのヒット、または任意値/任意プロパティ構文)であるすべての候補を file:line とともに報告します。このフィルターが存在するのは、スキャナーがファイル内のあらゆる単語形状のまとまり(通常のプローズを含む)を抽出するためです。そのすべてを報告すると、このゲートは使い物にならなくなります。検出があれば exit 1。
| Flag | Default | Meaning |
|---|---|---|
--strict | off | tabula/ ルールを名指しした eslint-disable コメントの数が budgets.maxSuppressions を超えた場合にも失敗させます(TAB-W900)。 |
--out <dir> | .tabula | registry.json を読み込む場所。 |
サプレッション数は、--strict がなくても常に出力されます — 誰にも見えない予算は予算ではありません。
解決はするものの、その製品が宣言されていないバリアントチェーンは TAB-E230(「登録済みの集合の外にあるため、CSS を一切生成しない」)として報告されます — v0.2 のバリアント閉包ゲートです。この fix-it は、抜け出す 2 つの方法を名指しします:製品を variants.products に宣言してリビルドするか、チェーンを正規の昇順ランクの順序へ書き換えるかです。パラメトリックな aria-*/data-*/group-*/peer-* バリアントは v0.1 では未サポートであり、ゲートの対象外です。
migrate <what>
npx tabula migrate logical
npx tabula migrate spacing --write
npx tabula migrate merge
npx tabula migrate darkプロファイルへのコードモッドです。デフォルトはドライラン — --write を渡さない限り、ディスク上の何も変わりません。支配的なルール: 証明可能に 1 対 1 であるものだけを書き換え、それ以外はすべて、推測するのではなく、位置と説明を伴う TODO コメントでフラグを立てます。
| Subcommand | What it does |
|---|---|
logical | pl-/pr-/ml-/mr-/left-/right-/border-l-/border-r-/text-left/text-right → 論理形式(ps-、pe-、ms-、me-、start-、end-、border-s-、border-e-、align-start、align-end)。1 対 1 で、クラスのシンク内でのみ。軸だけを修正し、値は修正しません — その後の tabula scan が、未登録のターゲット値を捕捉します。ビルド済みレジストリは不要です。 |
spacing | space-x-*/space-y-* → gap-x-*/gap-y-*。ただし、要素が対応する flex 方向(flex-row/flex-col)を証明可能に持ち、かつターゲットクラスが登録済みである場合に限ります。grid コンテナ、負の値、space-*-reverse、バリアント付きクラス、証明不能な軸については(TODO とともに)拒否します。ビルド済みレジストリが必要です — なければ exit 2。 |
merge | clsx / classnames / tailwind-merge の twMerge / 外部の cn インポートを @tabula-css/merge の cn に書き換えます。インポートのみで、呼び出し箇所は変更されません(ローカルの束縛名は import { cn as clsx } from '@tabula-css/merge' によって保持されます)。単一の指定子のみが対象です — 混在するインポートはフラグが立てられるだけで、分割はされません。twMerge は書き換えられますが常にフラグが立ちます: twMerge は名前形状のヒューリスティクスでマージするのに対し、cn はレジストリで宣言されたスロット所有権でマージするため、すべての呼び出し箇所にレビューが必要です。 |
dark | --write を指定してもレポートのみ。 dark:/light:/[data-theme=…]: の使用箇所をすべて file:line とともに列挙し、なぜそれがコードモッドではなくトークン軸を必要とするのかを示します — トークンのもう一方のテーマリテラルは作者のデザイン意図の中にしか存在せず、自動的に導出することはできません。 |
| Flag | Default | Meaning |
|---|---|---|
--write | off | 書き換えを適用します。指定しない場合、統合 diff が出力されるだけで、何も変わりません。 |
--out <dir> | .tabula | registry.json を読み込む場所(migrate spacing のみ)。 |
終了コードはサブコマンドを意識したものです: 0 何もすることがない、または --write によってすべての検出が適用された; 1 移行作業が残っている(保留中の書き換えがあるドライラン、または TODO フラグの立った検出 — したがって、使用箇所が 1 つでもある migrate dark は常に 1); 2 ツール自体が壊れているか誤って使われている(未知のサブコマンド、読み込めないプロジェクト、必要な箇所でレジストリが見つからない)。
except add
npx tabula except add \
--name card-shadow --type dimension --value 347px --families w \
--reason "Figma spec requires this exact width; no token is within 5%." \
--owner @design-systems --expires 2026-12-31 --allowed-in "src/marketing/**"提案された語彙例外を、実際のトークンドキュメントに継ぎ足し、実際の @tabula-css/tokens バリデーターを実行することで検証し、トークンファイルのパッチを出力します。--apply を渡さない限り何も書き込みません。
| Flag | Required | Meaning |
|---|---|---|
--name | yes | 例外のトークン名。 |
--type | yes | DTCG の $type(dimension、color、duration など)。 |
--value | yes | リテラルの CSS 値。dimension/duration の値は { value, unit } に強制変換されます。 |
--families | yes | 繰り返し指定/カンマ区切り。例外が発行できるファミリープレフィックス(w、h、p など)。 |
--reason | yes | 登録済みのトークンではだめな理由。 |
--owner | yes | この例外に責任を持つチームまたは個人。 |
--expires | yes | YYYY-MM-DD。名前付き例外は最大 12 か月先まで、--literal エスケープは 90 日以内に期限が切れなければなりません。 |
--allowed-in | yes | 繰り返し指定可能。この例外のクラスが出現してよい glob。 |
--literal | no | このエスケープを、名前付き例外ではなくレーン 2(90 日の圧力弁)としてマークします。 |
--chain | no | 一回限りのバリアントチェーン(hover:bg-accent-hover)を、値を発行する代わりに例外として登録します — 詳細は以下を参照してください。--type/--value/--families ではなく、書類系のフラグを取ります。 |
--apply | no | exception 名前空間を所有するトークンファイルにパッチを書き込みます(存在しなければ tokens/exceptions.tokens.json を作成します)。再ビルドは行いません — tabula build を実行するまで .tabula/ は古いままです。 |
--ticket、--description | no | パッチに引き継がれる追加のメタデータ。 |
成功時、要求された寸法値の約 5%/2px 以内に既存のトークンがあれば、それを出力し(TAB-W401)、新しい語彙を発行するのではなく再利用するよう促します。
チェーン例外(--chain)
npx tabula except add --chain hover:bg-accent-hover \
--reason "One-off hover state the interaction preset does not cover." \
--owner @design-systems --expires 2026-12-31 --allowed-in "src/marketing/**"バリアント閉包の対応物(v0.2):値の形式が新しいクラスを発行するのに対し、--chain は、宣言済みプロダクトのモデル(variants.products)であればスキャン時に拒否していたであろう(TAB-E230)、すでに登録済みのユーティリティに対する単一のバリアントチェーンをホワイトリストに登録します。これは同じ例外メカニズムに乗ります――--apply なしでは何も書き込まず、実際のトークンバリデーターを実行し、--reason、--owner、--expires、--allowed-in を要求します(同じ有効期限の範囲で:名前付き例外は 12 か月、--literal では 90 日)。--name はデフォルトでチェーンの DTCG セーフなスラッグになります。--type、--value、--families は使用されません。パラメトリックバリアント(group-*/peer-*/aria-*/data-*)は拒否されます――v0.1 では未サポートです。チェーンはレジストリの chainExceptions に格納され、リーダーは hasChainClass() を通じてそれに答えます。
eject
npx tabula eject
npx tabula eject --to tabula-frozen --yes --write-imports実験的機能です。 イジェクト(凍結と --report の逆引きマップ分析の両方)は v0.3.0 では実験的機能として提供されます――コマンドは動作し、テストもされていますが、そのサーフェス(フラグ、レポートの形式、ティア表)は将来のマイナーリリースで変更される可能性があります。
検証済みの .tabula/ を、クラスの変更なしに標準の @tailwindcss/cli でコンパイルできる、プロジェクト所有のディレクトリへコピーし、トークンパイプラインがそこへ流れ込むのを止めます――一方通行の凍結です。デフォルトはドライラン: --yes がなければ、eject は完全な計画(コピーするすべてのファイル、パーミッションの変更、見つかった @import の書き換え、有効期限の警告、一方通行のドアのバナー、そして cn() のポリシー注記)を出力するだけで、何にも触れません。実行すると、各コピーを 0644 で、そして EJECTED.md というプロヴェナンスファイルをターゲットに書き込みます。全体の流れと、それが対処する 4 つのハザードについては イジェクト を参照してください。
| Flag | Default | Meaning |
|---|---|---|
--to <dir> | tabula-frozen | 凍結対象のディレクトリ。プロジェクトルート配下。 |
--yes | off(dry run) | 実行します。指定しない場合、eject は計画を出力するだけで、何にも触れません。 |
--force | off | すでにファイルを含んでいるターゲットを許可します。指定しない場合、空でないターゲットは拒否されます(TAB-E240)。 |
--write-imports | off | .tabula/source.css を指しているプロジェクトの CSS の @import 行を、凍結されたコピーを指すように書き換えます。指定しない場合、eject は見つかったファイルと、正確な新しい import 行を出力するだけです。 |
--report | off | 分析専用、凍結なし: ソースが実際に使用するすべての class を、素の (vanilla) Tailwind v4 に対する移植性のティア A/B/C/D に分類し、tabula-eject-report.md を書き込みます。レポートのティア を参照してください。 |
--theme-port | off | レポートのシナリオ切り替え: --tb-* テーマの名前空間が vanilla の名前空間(--color-*、--spacing-* など)へ移植されたものとして分類し、レポートに移植手順を含めます。 |
--format=json | md | --report と併用: レポート文書を Markdown ではなく JSON(トップレベルに experimental: true)として出力します。 |
--write | off | --report と併用: 証明可能に 1 対 1 なティア B のリネームのみを、コードモッドエンジンを通じて適用します(migrate と同様、まずドライラン diff)。ティア C/D の class は決して書き換えられません。 |
前提条件は、この順序でフェイルクローズします:読み込み可能なプロジェクト(TAB-E901);既存の、陳腐化しておらず、手編集もされていない .tabula/(doctor が使うのと同じドリフトゲートで、欠落/陳腐化には TAB-E303、手編集または未カバーには TAB-E601);そして、使用可能なターゲット(TAB-E240。これは終了コード 2 です――ツールが先に進めない状態であり、スタイリングが誤っているわけではありません)。期限切れの、または 90 日以内に期限切れとなる例外は、ブロックするのではなく警告します(TAB-W402):eject の後にはリビルドがないため、通常の期限切れ時のハードエラー(TAB-E141)は二度と発火しえないからです。cn() は依然として @tabula-css/merge とコピーされた registry.json を必要とします。それを tailwind-merge に置き換えると、描画される出力が変わり、EJECTED.md はそのことを文書として書き残します。
doctor
npx tabula doctorローカルでのトリアージを、この順序でチェックします: 陳腐化(現在の入力ハッシュ対マニフェストのもの)、手編集されたアーティファクト(sha256 の不一致、TAB-E601)、ディレクトリのカバレッジ(迷子ファイル、またはマニフェストに記載のないアーティファクト)、期限切れ間近/期限切れの例外(TAB-W401/TAB-E141)、@tabula-css/*/Tailwind のバージョンのずれ(TAB-E302)、エスケープ予算。重大な失敗があれば exit 1、それ以外は警告を出力しつつ exit 0。
| Flag | Default | Meaning |
|---|---|---|
--out <dir> | .tabula | マニフェストとアーティファクトを読み込む場所。 |
doctor は認証された整合性チェックではありません — マニフェストは自分自身をハッシュ化できないため、一貫した編集(アーティファクトとその記録済みハッシュの両方を変更する)はここを通過します。権威となるのは tabula build --check です: これはトークンと設定からすべてのアーティファクトを再導出し、マニフェストを含む一式全体をバイト単位で比較します。これが、CI が doctor ではなく --check を実行しなければならない理由です。
explain <TAB-Exxx>
npx tabula explain TAB-E113診断コードの原因、そのルールが存在する理由、そしてその修正方法を、@tabula-css/core の凍結された ERROR_CATALOG から完全にオフラインで出力します — これは、他のすべての診断がフォールバックする修正のフロアです。認識できないコードには、編集距離 2 以内の候補が最大 3 つ提示されます。
canary
npx tabula canarystrict プリセットが提供するすべての ESLint ルールに違反するよう設計されたフィクスチャを生成し、プロジェクト自身のビルド済みレジストリに対してプログラム的に lint を実行し、期待されるルールのいずれかが発火しなかった場合に失敗します(TAB-E201)— これは、配線されていないプラグイン、脱落した設定、あるいは fail open してしまったレジストリを捕捉するもので、通常のテストスイートでは気づかれません。eslint と @typescript-eslint/parser がインストールされている必要があります。なければ exit 2。
| Flag | Default | Meaning |
|---|---|---|
--out <dir> | .tabula | registry.json を読み込む場所 — canary の実行前に存在していなければなりません。 |
グローバルフラグ
| Flag | Meaning |
|---|---|
--format=json | 機械可読なエンベロープ { tabula, ok, inputsHash, diagnostics } を標準出力に出力します。このモードでは、他には何も標準出力へ出力されません。 |
--help | 使用方法を出力します。 |
関連パッケージ
@tabula-css/registry—buildが導出し、他のすべてのコマンドが読み取るアーティファクト。@tabula-css/stylelint-plugin—check:cssがエディタプラグインと共有するルールカーネル。@tabula-css/eslint-plugin—canaryがそのフィクスチャを lint する対象のstrictプリセット。- Getting started — ビルド → lint → CI の一連のウォークスルー。
- CSS governance —
check:cssがチェックする内容と、まだチェックしない内容。 - Migration — shadcn の移行パスも含め、コードモッドについてのより詳しい説明。
- イジェクト —
tabula ejectの全体の流れ、4 つのハザード、そして一方通行のドアのポリシー。