# Token Lint

> 지정한 경로의 vapor 디자인 토큰 CSS 변수 사용을 검사합니다. .css/.scss/.sass/.less/.ts/.tsx/.js/.jsx 파일에서 `var(--vapor-...)` 참조를 스캔하여, 정식 토큰 집합에 없는 이름을 신고하고 세그먼트 정렬 Damerau-Levenshtein 합 거리 2 이내의 가장 가까운 유효 토큰을 최대 3개까지 제안합니다. 사용자가 디자인 토큰 린트, 토큰 오타 검사, vapor 토큰 사용 검증, Figma에서 코드로 변환한 결과의 `var(--vapor-)` 참조 감사를 언급하거나 `/token-lint <path>`를 요청할 때 사용하세요. 디자인 의도 단계의 린트(의미 범위, 사용 가능/금지 여부)는 Figma 단계에서 이미 끝난 것으로 가정합니다 — 이 스킬은 개발자가 토큰을 코드에 옮겨 적는 과정에서 발생하는 전사 오타만 잡습니다. 자동 수정은 하지 않고 제안만 합니다.

- Skill: `goorm-dev/token-lint` (Agent Skill, multi-file: 17 files)
- Install (CLI): `npx skillmds@latest add goorm-dev/token-lint`
- Raw SKILL.md: https://api.skillmd.com/api/skills/goorm-dev/token-lint/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Design & Media
- Author: goorm-dev (https://skillmd.com/u/goorm-dev)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/goorm-dev/token-lint

---


# token-lint

## 사용 시점

사용자가 Figma 디자인을 코드(CSS, React 등)로 막 옮기고, 모든 `var(--vapor-...)` 참조가 실제 존재하는 토큰을 가리키는지 확인하고 싶을 때 사용합니다. Figma 측 의미 린트(이 맥락에 적합한 토큰인지 여부)는 이미 완료된 것으로 가정하며, 이 스킬은 전사 과정에서 발생하는 **오타**를 잡습니다.

트리거 표현:

- `/token-lint <path>`
- "vapor 토큰 오타 검사"
- "이 컴포넌트 토큰 사용 검사해줘"
- "var(--vapor-...) 잘 썼는지 확인"

## 동작 방식

번들된 결정론적 스크립트(`scripts/lint.mjs`)가 작업 전부를 수행합니다.

1. `assets/`의 DTCG JSON 파일(vapor 디자인 토큰 스냅샷)로부터 정식 CSS 변수 이름 집합을 빌드합니다.
2. 대상 경로를 순회하며 확장자가 `.css .scss .sass .less .ts .tsx .js .jsx`인 파일을 선별합니다.
3. `node_modules`, `dist`, `build`, `.next`, `.turbo`, `coverage`, `.git`, `.venv`, `__pycache__`, `.cache`, `out` 디렉터리는 건너뜁니다.
4. 각 파일을 통째로 읽어 단일 정규식으로 `var(--vapor-...)` 참조를 추출합니다. 정규식의 `\s*`가 개행을 포함하므로 멀티라인 `var(\n  --vapor-x\n)` 호출도 잡습니다. 닫는 `)` 또는 `,`와 마지막 글자가 alphanumeric일 것을 요구하므로, `.startsWith` 비교 등에 쓰이는 미완성 문자열 prefix(예: `'var(--vapor-color-'`)는 토큰 참조로 보지 않습니다. 라인 번호는 매치 오프셋에서 역산합니다.
5. 정식 집합에 없는 이름은 세그먼트 정렬 Damerau-Levenshtein(`--vapor-` 제거 후 `-`로 분해, 세그먼트 개수 일치 필수, 세그먼트당 거리 1·합 거리 2 이내)으로 가장 가까운 토큰을 거리·알파벳 순으로 최대 3개까지 제안합니다. 인접 글자 전치 오타(예: `foregruond` ↔ `foreground`)도 거리 1로 잡습니다.
6. 결과는 케이스별 블록(`[N] <파일:라인>`, `토큰: ...`, `추천:` + 번호 매긴 후보 목록)으로 출력하고, 블록 사이는 빈 줄로 구분합니다. 각 후보 옆에는 거리 힌트(`1글자 차이 — 오타 가능성 높음`, `2글자 차이`)를 붙여 사용자가 조치 우선순위를 즉시 판단할 수 있게 합니다. 거리 2 이내 후보가 없으면 `추천: 이름이 비슷한 토큰 없음`과 함께 Figma 디자인 파일에서 토큰 이름을 다시 확인하라는 안내를 출력합니다. 마지막 줄에는 `요약: M개 파일에서 등록되지 않은 --vapor- 토큰 N건 발견` 한 줄을 덧붙입니다. 깨끗하든 오타가 발견되든 exit 0이며(사용자가 셸·CI에서 실패로 오인하는 것을 막기 위함), 호출 오류만 exit 2입니다.

## 실행 방법

스크립트 경로는 스킬 로드 시 주입된 base directory를 기준으로 조립합니다.

```bash
node <skill-dir>/scripts/lint.mjs <path>
```

- `<skill-dir>`: 스킬 base directory의 절대 경로. 위치는 설치 형태에 따라 다릅니다(프로젝트 로컬 `.claude/skills/token-lint`, 사용자 글로벌 `~/.claude/skills/token-lint`, 플러그인 캐시 `~/.claude/plugins/cache/.../skills/token-lint` 등). 경로를 하드코딩하지 말고 base directory를 그대로 사용하세요.
- `<path>`: 사용자가 준 경로를 그대로 사용하세요. 디렉터리 또는 단일 파일 모두 가능합니다. 디렉터리 이동(`cd`) 없이 명시적 경로로 실행합니다.

실행 후 스크립트의 stdout을 **있는 그대로** 사용자에게 전달합니다. 요약·재배치·테이블 변환·글머리표 변환·문단 풀어쓰기 모두 금지. 라벨 블록과 꼬리 줄(`clean: ...` 또는 `found ...`)을 단일 코드 블록 없이 그대로 출력하면 됩니다. 어떤 해석 문구도 앞뒤로 붙이지 마세요. exit 코드는 별도로 언급할 필요 없습니다(사용자가 stdout 꼬리 줄로 파악 가능).

## 한계

이 스킬은 파일 전체 정규식 스캔 + 동결된 카탈로그 스냅샷 + 세그먼트 정렬 Damerau-Levenshtein으로 동작합니다. 따라서 깨끗한 exit이 "전부 검사했고 전부 옳다"를 보장하지 않습니다. 아래 **증상이 의심될 때만** `references/limitations.md`를 읽고 그 카테고리의 보정 지침을 적용해 사용자에게 알리세요.

- ``var(`--vapor-${name}`)``, helper 함수로 토큰을 조립하는 코드, 사용자 측 vapor prefix 확장 정의(`--vapor-team-x: ...`)가 검사 대상에 포함되어 있다 → §1 regex 한계.
- unknown으로 신고됐는데 제안이 비어 있거나, 직관적으로 의미축(foreground↔background 등) 오타로 보인다 → §2 Levenshtein 의미 맹점.
- 작업이 토큰의 타입 적합성(color를 font-size 자리에 쓰는 등)이나 deprecated 토큰 검출까지 요구한다 → §3 단방향 존재 검사.

위 어느 증상에도 해당하지 않으면 limitations.md를 읽을 필요 없이 stdout 결과를 그대로 보고합니다.

