Skip to content

@tabula-css/cli

tabula 커맨드라인 도구: build, build --check, check:css, scan, migrate, except add, eject, doctor, explain, canary.

설치

bash
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는 일반 의존성으로 포함되며, eslinttabula canary에서만 필요한 선택적 피어(peer)입니다.

개요

tabula는 대부분의 프로젝트가 사용하는 진입점입니다. tabula build는 여러분의 토큰과 tabula.config.json을 읽어 생성된 .tabula/ 아티팩트 전체 집합을 도출합니다 — 이는 평평한 토큰 프로파일을 다른 모든 것(@tabula-css/merge, ESLint 플러그인, MCP 서버)이 읽는 닫힌 어휘로 바꾸는 단계입니다. 나머지 명령들은 그 출력을 드리프트에 대해 다시 검사하고, 어휘 밖의 클래스를 소스 파일에서 스캔하고, CSS 거버넌스를 강제하고, 기존 코드를 프로파일로 마이그레이션하고, 범위가 지정된 예외를 등록하고, 오프라인으로 진단 코드를 설명합니다.

모든 명령은 하나의 종료 코드 계약(packages/cli/src/types.ts)을 공유합니다: 0 프로젝트가 깨끗함, 1 프로젝트가 계약을 위반함(도구는 정상 동작했고, 스타일링이 틀림), 2 도구 자체가 실행될 수 없었음(잘못된 형식의 입력, 프로젝트 누락, 내부 오류). --format=json은 표준 출력에 오직 기계용 봉투(machine envelope) { tabula, ok, inputsHash, diagnostics }만 방출하며, 앞에 붙는 사람용 로그가 전혀 없습니다 — 이는 tabula build --format=json을 JSON 파서로 파이프하는 에이전트가 의존하는 불변식입니다.

build

bash
npx tabula build
npx tabula build --check

tokens/*.tokens.jsontabula.config.json을 읽고, 전체 아티팩트 집합을 도출하여 원자적으로 .tabula/에 기록합니다(검증 실패 시에는 아무것도 기록되지 않습니다). 아티팩트 목록과 빌드의 inputsHash를 출력합니다.

플래그기본값의미
--checkoff메모리에서 재생성하여 커밋된 .tabula/와 바이트 단위로 비교합니다; scan 게이트와 CSS 거버넌스 게이트도 함께 실행합니다. 디스크에는 아무것도 기록하지 않습니다. 드리프트나 게이트 발견 사항이 있으면 종료 코드 1.
--backend a|b|conformb레지스트리 백엔드: a(디자인 시스템 API), b(PostCSS 프로브-시트 순회), 또는 conform(둘 다 실행하여 서로 일치하는지 확인).
--out <dir>.tabula출력 디렉터리.
--no-scanoff--check와 함께 사용 시, scan 게이트를 건너뜁니다(드리프트 비교만).
--no-cssoff--check와 함께 사용 시, CSS 거버넌스 게이트를 건너뜁니다(드리프트 비교만).
--css-entry <path>반복 가능. CSS 거버넌스 게이트를 위한 추가 허가 진입 스타일시트로, check:css에 그대로 전달됩니다.
--css-ignore <dir>반복 가능. .css 파일을 순회할 때 건너뛸 추가 디렉터리 이름.

--check는 드리프트 비교를 먼저 실행하고, 그다음 scan 게이트, 그다음 CSS 거버넌스 게이트를 이 순서로 실행합니다 — 그래서 --check 아래에서 scan이나 CSS 발견 사항은 항상 "소스가 잘못됨"을 의미하며, 결코 "레지스트리가 오래되었음"을 의미하지 않습니다. 매니페스트가 이름을 지정하지 않은 .tabula/ 내부의 낯선 파일도 드리프트로 취급됩니다.

bash
npx tabula build --check --backend conform

check:css

bash
npx tabula check:css

모든 프로젝트 .css 파일(고정된 무시 목록을 제외하고, scan의 소스 글롭이 아니라 트리 전체를 순회)과 .tabula/의 방출된 스타일시트를 파싱하고, @tabula-css/stylelint-plugin의 커널에서 가져온 다섯 가지 CSS 거버넌스 규칙을 실행합니다 — 에디터 플러그인이 실행하는 것과 동일한 규칙 코드이므로, 둘이 서로 어긋날 수 없습니다. 발견 사항이 있으면 종료 코드 1.

플래그기본값의미
--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반복 가능. 순회 시 건너뛸 추가 디렉터리 이름.

이 명령이 강제하는 다섯 가지 규칙(TAB-E221TAB-E225)은 @tabula-css/stylelint-plugin을, 이 게이트가 다루는 것과 다루지 않는 것은 CSS 거버넌스를 참고하십시오.

scan

bash
npx tabula scan

Tailwind 자체의 스캐너(@tailwindcss/oxide)를 프로젝트의 소스 글롭에 대해 실행하고 — CSS 빌드가 사용하는 것과 동일한 추출입니다 — 등록되지 않았으면서도 유틸리티 형태(리졸브되는 변형 체인, 등록된 패밀리 접두사, 금지 목록 적중, 또는 임의값/속성 구문)인 모든 후보를 file:line과 함께 보고합니다. 이 필터가 존재하는 이유는 스캐너가 파일 안의 단어 형태를 띤 모든 실행을 추출하기 때문이며, 여기에는 평범한 프로즈도 포함됩니다. 이를 모두 보고하면 게이트를 사용할 수 없게 될 것입니다. 발견 사항이 있으면 종료 코드 1.

플래그기본값의미
--strictofftabula/ 규칙을 지정한 eslint-disable 주석의 개수가 budgets.maxSuppressions(TAB-W900)를 초과할 때도 실패시킵니다.
--out <dir>.tabularegistry.json을 읽어 올 위치.

억제(suppression) 개수는 --strict 없이도 항상 출력됩니다 — 아무도 보지 않는 예산은 예산이 아닙니다.

리졸브되지만 그 프로덕트가 선언되지 않은 변형 체인은 TAB-E230("등록된 집합 밖이므로 아무 CSS도 내지 않는다")으로 보고됩니다 — v0.2의 변형-폐쇄성 게이트입니다. 이 fix-it은 벗어나는 두 가지 방법을 알려줍니다: variants.products에 프로덕트를 선언하고 다시 빌드하거나, 체인을 정규 오름차순 rank 순서로 다시 쓰는 것입니다. 파라메트릭 aria-*/data-*/group-*/peer-* 변형은 v0.1에서 지원되지 않으며 게이팅 대상이 아닙니다.

migrate <what>

bash
npx tabula migrate logical
npx tabula migrate spacing --write
npx tabula migrate merge
npx tabula migrate dark

프로파일로의 코드모드(codemod)입니다. 기본적으로 드라이런입니다 — --write를 전달하지 않으면 디스크상의 아무것도 바뀌지 않습니다. 지배 원칙은 이렇습니다: 명백히 1:1인 것만 다시 작성하고, 나머지는 모두 추측하지 말고 위치가 명시된, 설명이 붙은 TODO 주석으로 표시합니다.

하위 명령하는 일
logicalpl-/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이 등록되지 않은 대상 값을 잡아냅니다. 빌드된 레지스트리가 필요 없습니다.
spacingspace-x-*/space-y-*gap-x-*/gap-y-*, 다만 요소가 명백히 일치하는 flex 방향(flex-row/flex-col)을 가지고 있고 대상 클래스가 등록되어 있을 때만 적용됩니다. 그리드 컨테이너, 음수 값, space-*-reverse, 변형 접두사가 붙은 클래스, 또는 증명 불가능한 축에 대해서는 (TODO와 함께) 거부합니다. 빌드된 레지스트리가 필요하며, 없으면 종료 코드 2.
mergeclsx / classnames / tailwind-mergetwMerge / 외부 cn import를 @tabula-css/mergecn으로 다시 씁니다. import만 바뀌고 호출부는 그대로입니다(로컬 바인딩 이름은 import { cn as clsx } from '@tabula-css/merge'를 통해 보존됩니다). 단일 지정자(specifier)만 대상이며 — 혼합된 import는 나누지 않고 표시만 합니다. twMerge는 다시 쓰이지만 항상 표시됩니다: 이는 이름 형태 휴리스틱으로 병합하는 반면 cn은 레지스트리가 선언한 슬롯 소유권으로 병합하므로, 모든 호출부는 검토가 필요합니다.
dark--write가 있어도 보고만 합니다. dark:/light:/[data-theme=…]: 사용을 file:line과 함께, 그리고 왜 코드모드가 아니라 토큰 축이 필요한지와 함께 나열합니다 — 그 토큰의 다른 테마 리터럴은 오직 작성자의 디자인 의도 안에만 존재하며 자동으로 도출될 수 없습니다.
플래그기본값의미
--writeoff다시 쓰기를 적용합니다. 없으면 통합 diff가 출력되고 아무것도 바뀌지 않습니다.
--out <dir>.tabularegistry.json을 읽어 올 위치(migrate spacing에만 해당).

종료 코드는 하위 명령별로 다릅니다: 0 할 일이 없거나, --write가 모든 발견 사항에 적용됨; 1 마이그레이션 작업이 남아 있음(대기 중인 다시 쓰기가 있는 드라이런, 또는 TODO로 표시된 발견 사항 — 그래서 migrate dark는 사용처가 하나라도 있으면 항상 1); 2 도구가 고장났거나 잘못 사용됨(알 수 없는 하위 명령, 로드할 수 없는 프로젝트, 필요한 곳에 레지스트리 없음).

except add

bash
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를 전달하지 않으면 아무것도 기록하지 않습니다.

플래그필수의미
--nameyes예외의 토큰 이름.
--typeyesDTCG $type(dimension, color, duration 등).
--valueyes리터럴 CSS 값; dimension/duration 값은 { value, unit }으로 강제 변환됩니다.
--familiesyes반복 가능/쉼표로 결합. 예외가 발행할 수 있는 패밀리 접두사(w, h, p 등).
--reasonyes왜 등록된 토큰으로는 안 되는지.
--owneryes예외에 대해 책임지는 팀 또는 사람.
--expiresyesYYYY-MM-DD. 이름 있는 예외는 최대 12개월까지; --literal 탈출은 90일 이내에 만료되어야 합니다.
--allowed-inyes반복 가능. 예외의 클래스가 나타날 수 있는 글롭들.
--chainno일회성 변형 체인(hover:bg-accent-hover)을 값을 발행하는 대신 예외로 등록합니다 — 아래를 참고하십시오. --type/--value/--families가 아니라 서류 관련 플래그를 받습니다.
--literalno이 탈출을 이름 있는 예외가 아니라 레인 2(90일짜리 압력 밸브)로 표시합니다.
--applynoexception 네임스페이스를 소유하는 토큰 파일에 패치를 기록합니다(없으면 tokens/exceptions.tokens.json을 생성). 다시 빌드하지는 않습니다tabula build를 실행하기 전까지 .tabula/는 오래된 상태입니다.
--ticket, --descriptionno패치에 실리는 추가 메타데이터.

성공 시, 요청된 dimension 값의 약 5%/2px 이내에 기존 토큰이 있으면 그 토큰(TAB-W401)을 출력하여, 새 어휘를 발행하는 대신 재사용하도록 유도합니다.

체인 예외 (--chain)

bash
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

bash
npx tabula eject
npx tabula eject --to tabula-frozen --yes --write-imports

실험적 기능. Eject(동결과 --report 역매핑 분석)는 v0.3.0에서 실험적으로 제공됩니다 — 명령은 동작하고 테스트되어 있지만, 그 표면(플래그, 리포트 형식, 티어 표)은 향후 마이너 릴리스에서 바뀔 수 있습니다.

검증된 .tabula/를 프로젝트 소유의 디렉터리로 복사하여 클래스 변경 없이 순정 @tailwindcss/cli로 컴파일되게 만들고, 그 디렉터리로 흘러들어가는 토큰 파이프라인을 멈춥니다 — 돌아올 수 없는 동결입니다. 기본값은 드라이 런: --yes 없이는 eject가 전체 계획(복사할 모든 파일, 권한 변경, 발견된 @import 재작성, 만료 경고, 돌아올 수 없는 문 배너, cn() 정책 안내)을 출력하고 아무것도 건드리지 않습니다. 실행하면 각 복사본을 0644로 쓰고 대상에 EJECTED.md 출처(provenance) 파일을 씁니다. 전체 흐름과 이 명령이 다루는 네 가지 위험 요소는 동결(Eject)을 참고하십시오.

플래그기본값의미
--to <dir>tabula-frozen프로젝트 루트 아래의 동결 대상 디렉터리.
--yesoff (드라이 런)실행합니다. 없으면 eject는 계획만 출력하고 아무것도 건드리지 않습니다.
--forceoff이미 파일이 있는 대상을 허용합니다; 그렇지 않으면 비어 있지 않은 대상은 거부됩니다(TAB-E240).
--write-importsoff.tabula/source.css를 가리키는 프로젝트 CSS의 @import 줄을 동결된 복사본을 가리키도록 다시 씁니다. 없으면 eject는 발견한 파일과 정확한 새 import 줄을 출력만 합니다.
--reportoff분석 전용, 동결 없음: 소스가 실제로 사용하는 모든 class를 순정(vanilla) Tailwind v4에 대한 이식성 티어 A/B/C/D로 분류하고 tabula-eject-report.md를 씁니다. 리포트 티어를 참고하십시오.
--theme-portoff리포트 시나리오 전환: --tb-* 테마 네임스페이스가 순정 네임스페이스(--color-*, --spacing-* 등)로 이식된 것처럼 분류하고, 리포트에 이식 안내를 포함합니다.
--format=jsonmd--report와 함께: 리포트 문서를 Markdown 대신 JSON(최상위에 experimental: true)으로 출력합니다.
--writeoff--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

bash
npx tabula doctor

로컬 트리아지(triage)로, 다음 순서로 검사합니다: 오래됨(현재 입력 해시 대 매니페스트의 해시), 손으로 수정된 아티팩트(sha256 불일치, TAB-E601), 디렉터리 커버리지(낯선 파일, 또는 매니페스트에 없는 아티팩트), 만료 예정/만료된 예외(TAB-W401/TAB-E141), @tabula-css/*/Tailwind 버전 스큐(TAB-E302), 탈출 예산. 심각한 실패가 있으면 종료 코드 1, 그렇지 않으면 경고를 출력하고 0.

플래그기본값의미
--out <dir>.tabula매니페스트와 아티팩트를 읽어 올 위치.

doctor는 인증된 무결성 검사가 아닙니다 — 매니페스트는 스스로를 해시할 수 없으므로, (아티팩트 그 기록된 해시를) 함께 바꾸는 일관된 수정은 여기를 통과합니다. tabula build --check가 권위 있는 검사입니다: 토큰과 설정으로부터 모든 아티팩트를 다시 도출하여 매니페스트를 포함한 전체 집합을 바이트 단위로 비교합니다 — 그래서 CI는 doctor가 아니라 --check를 실행해야 합니다.

explain <TAB-Exxx>

bash
npx tabula explain TAB-E113

진단 코드의 원인, 그 규칙이 존재하는 이유, 그 해결책을 @tabula-css/core의 고정된 ERROR_CATALOG로부터 완전히 오프라인으로 출력합니다 — 다른 모든 진단이 의지하는 해결책의 기본 바닥입니다. 인식되지 않은 코드는 편집 거리 2 이내에서 최대 세 개의 제안을 받습니다.

canary

bash
npx tabula canary

strict 프리셋이 제공하는 모든 ESLint 규칙을 위반하도록 설계된 픽스처를 생성하고, 프로젝트 자체의 빌드된 레지스트리에 대해 프로그램적으로 린트한 뒤, 예상된 규칙이 하나라도 발동하지 않으면 실패합니다(TAB-E201) — 이는 배선되지 않은 플러그인, 누락된 설정, 또는 열려서 실패한(failed open) 레지스트리를 잡아내며, 일반적인 테스트 스위트로는 알아차리지 못할 것들입니다. eslint@typescript-eslint/parser가 설치되어 있어야 하며, 없으면 종료 코드 2로 종료합니다.

플래그기본값의미
--out <dir>.tabularegistry.json을 읽어 올 위치 — 카나리가 실행되기 전에 존재해야 합니다.

전역 플래그

플래그의미
--format=json표준 출력에 기계용 봉투 { tabula, ok, inputsHash, diagnostics }를 방출합니다; 이 모드에서는 그 밖의 어떤 것도 표준 출력으로 가지 않습니다.
--help사용법을 출력합니다.

함께 보기

Released under the MIT License.