DESIGN.md는 색상·타이포·간격 같은 토큰뿐 아니라 보이스(말투)·내러티브·원칙·페르소나·모션까지 담는 이식 가능한 브랜드 명세로, 실제 440개 기업의 검증된 디자인 시스템을 출발점(레퍼런스)으로 삼을 수 있다. 설치와 핵심 워크플로에는 별도 API 키나 MCP 서버가 필요 없다 — 추론은 이미 쓰고 있는 에이전트 세션 안에서 그대로 일어난다.
kwakseongjae/oh-my-design · 라이선스 MIT · npm 패키지 oh-my-design-cli v1.9.0(2026-07-17) · 최신 커밋 0a7f3a1(2026-07-21) · 소스 파일 약 3,259개 중 마크다운 2,204개 · 레퍼런스 440개 기업 DESIGN.md · CLI=TypeScript/Node · 부속 웹앱 oh-my-design.kr=Next.js 16 + React 19 · 한국어·영어·일본어·중국어 번체 4개 언어 문서)
oh-my-design은 "디자인 시스템 설치기"다. npx oh-my-design-cli@latest 한 번이면 지금 쓰는 코딩 에이전트(Claude Code / Codex / OpenCode / Cursor) 안에 20개 스킬 · 최대 18개 전문 서브에이전트 · 자동 훅 · 440개 기업 레퍼런스 카탈로그가 깔린다. 이후 사용자가 "우리 서비스 디자인 시스템 세팅해줘"라고 말하면, 방금 설치된 omd:init 스킬이 카탈로그에서 어울리는 기업(예: 토스, 뱅크샐러드, Linear)을 추천하고, 선택된 레퍼런스의 톤을 보존한 변형본을 프로젝트 루트 DESIGN.md로 만들어낸다.
중요한 건 이 도구가 새 AI를 추가하지 않는다는 점이다. 추천 로직도, 문서 작성도 전부 사용자가 이미 쓰고 있는 에이전트의 모델이 스킬 마크다운에 적힌 절차를 그대로 따라가며 수행한다. oh-my-design은 그 절차서(SKILL.md)와 근거 자료(레퍼런스 카탈로그)를 만들어 설치해줄 뿐이다.
셰프는 이미 요리를 잘한다. 하지만 매번 "그냥 맛있게"라고만 주문하면 오늘은 짜게, 내일은 싱겁게 나온다. oh-my-design은 셰프를 바꾸지 않는다. 대신 "우리 가게는 이 레시피(토큰)로, 이런 말투(보이스)로, 이 손님층(페르소나)을 위해 요리한다"고 적힌 레시피북 한 권(DESIGN.md)을 주방에 걸어둔다.
다음에 다른 요리사(다른 세션, 다른 날)가 와도 같은 레시피북을 펴 보면 똑같은 맛이 나온다 — 이것이 이 프로젝트가 노리는 "톤의 일관성"이다.
2025~2026년은 Claude Code · Codex · OpenCode 같은 터미널 코딩 에이전트가 일상 도구가 된 시기다. 코드 생성은 빨라졌지만, "디자인 판단"은 여전히 매 프롬프트마다 즉흥적으로 이뤄진다. "미니멀하게", "토스 느낌으로" 같은 지시는 세션이 바뀌면 다시 처음부터 설명해야 하고, 팀원마다 해석이 달라 결과물이 들쭉날쭉해진다. oh-my-design은 이 틈을 정확히 겨냥한다.
코드에는 eslint·prettier·타입 체커 같은 일관성 강제 장치가 있지만, "이 버튼이 우리 브랜드다운가"에는 그런 장치가 없었다. oh-my-design은 DESIGN.md라는 파일을 프로젝트에 커밋시켜, 디자인 판단도 코드처럼 버전 관리되고 다음 세션에서 다시 읽히는 문서로 만든다.
단순 "느낌적인 느낌"이 아니라, 각 기업 레퍼런스는 실제 라이브 사이트의 computed-style 스크래핑과 공식 디자인 시스템 문서를 근거로 토큰 값에 출처(source)·방법(method)·날짜(captured)를 매긴다. 한국 기업 레퍼런스는 "브랜드 소유 Tier-1 출처 2개 이상 + Proof 블록"이라는 자체 품질 게이트를 통과해야 카탈로그에 들어간다(CHANGELOG 기준). "그럴듯한 색상 팔레트"가 아니라 "이 회사가 실제로 이 값을 쓴다는 근거"를 파는 셈이다.
같은 팀 안에서도 누구는 Claude Code, 누구는 Codex, 누구는 Cursor를 쓴다. oh-my-design은 하나의 DESIGN.md를 4개 채널이 공유하게 만들어, 도구가 달라도 같은 브랜드 규칙을 참조하게 한다.
Style Dictionary 같은 토큰 빌드 도구는 코드 상수를 만들지만 "브랜드가 왜 이런 말투를 쓰는지"는 다루지 않는다. shadcn/ui 같은 컴포넌트 킷은 코드를 주지만 브랜드 고유성이 없다. oh-my-design은 그 중간 — "에이전트가 UI를 짜기 직전에 읽는 산문형 규칙서"라는 자리를 차지한다.
실제로 해결하는 문제는 셋으로 요약된다.
코딩 에이전트는 대화가 끝나면 그 세션의 판단(어떤 파란색을 썼는지, 왜 그 폰트 크기를 골랐는지)을 잊는다. oh-my-design은 그 판단을 DESIGN.md라는 파일로 프로젝트에 남겨, 다음 세션·다음 사람이 다시 그 파일을 Read하면 동일한 맥락을 되찾게 한다.
"토스 같은 느낌"이라는 지시는 사람마다, 세션마다 다르게 해석된다. 440개 기업의 검증된 실제 토큰·보이스·원칙을 출발점으로 제공함으로써, "느낌"이 아니라 "이 회사의 실제 값을 기준으로 우리 것을 만든다(hybrid variation)"는 재현 가능한 절차로 바꾼다.
Claude Code용 지시, Codex용 지시, Cursor용 규칙을 따로 관리하면 셋이 어긋난다. oh-my-design은 CLAUDE.md / AGENTS.md / .cursor/rules/omd-design.mdc 세 개의 "shim"(연결 통로) 파일을 자동 생성·동기화해, 진짜 소스는 DESIGN.md 하나로 유지한다.
저장소는 겉보기엔 npm 패키지 하나(oh-my-design-cli)지만, 실제로는 서로 다른 세 가지 산출물이 한 레포에 같이 산다: ① Node/TypeScript로 짠 설치·진단 CLI, ② 코드가 아니라 마크다운으로 쓰인 절차서(스킬·서브에이전트), ③ Next.js로 만든 웹사이트 겸 레퍼런스 파이프라인(oh-my-design.kr). 이 셋의 관계를 그림으로 보면 아래와 같다.
세 계층은 완전히 다른 언어로 짜여 있다는 게 이 레포의 특징이다. ①은 평범한 TypeScript CLI, ②는 실행 가능한 산문(prose-as-program), ③은 표준적인 Next.js 앱이다. "어디에 로직이 있나"를 코드에서만 찾으면 ②를 놓친다.
이 레포에서 배울 가치가 가장 큰 설계는 코드의 복잡도가 아니라 "신뢰를 어떻게 기계적으로 보장하는가"다. 네 가지 패턴으로 나눠본다.
src/cli/hook-contract.ts는 설치되는 훅 6개(skill-activation.cjs 등) 각각에 대해, 파일 맨 위에 // omd:installed-hook sha256=<해시>라는 한 줄을 새긴다. 이 해시는 마커를 뺀 나머지 내용으로 계산되므로(renderManagedHook), 파일을 열어 실제로 재계산해보면 "이 파일이 지금 배포되는 버전 그대로인지, 사용자가 손을 댔는지"를 판별할 수 있다(isCurrentManagedHook). 과거 버전(마커가 없던 시절) 파일까지 LEGACY_HOOK_HASHES 해시 목록으로 인식해, 재설치 시 "이건 예전 관리 파일이니 갱신해도 안전"이라고 판단한다.
도서관 대출 스탬프처럼 생각하면 쉽다. 관리자가 배포한 책(훅 파일) 첫 페이지에는 "이 판본의 지문(해시)"이 찍혀 있다. 다음 번 새 판본을 배포할 때, 책을 펼쳐 지문이 초판 그대로면 "아무도 안 건드렸으니 새 판으로 안전하게 교체", 지문이 달라졌으면 "누군가 낙서(수정)했으니 강제로 덮어쓰지 않고 사용자에게 물어본다." doctor·install-skills --force는 바로 이 판별 결과로 동작한다.
skills/omd-init/SKILL.md는 약 320줄짜리 마크다운인데, 이 자체가 7단계 상태 기계다. TypeScript 함수가 아니라 "다음 순서로 하라"는 지시문으로 짜여 있고, 이를 실제로 실행하는 건 호스트 에이전트(Claude Code 등)의 LLM이다.
data/reference-fingerprints.json을 읽어, "브랜드명 언급 +5점 / 톤 키워드 일치당 +1점 / 카테고리 일치 +1점"이라는 결정론적 점수 규칙을 LLM이 머릿속으로(in-head) 계산해 상위 5개를 추천.DESIGN.md를 정해진 우선순위 경로(.codex/data → .claude/data → .opencode/data → node_modules → 개발 레포 → 그래도 없으면 oh-my-design.kr/<id>/design.md 원격 fetch)로 찾는다. 전부 실패하면 "절대 지어내지 말고 사용자에게 실패를 알리라"고 명시돼 있다.[FILL IN: …] 플레이스홀더 + <!-- omd:limitation --> 주석을 넣도록 강제한다.omd:sync 스킬에 위임해 CLAUDE.md/AGENTS.md/Cursor rule shim을 갱신하고 요약을 출력.
이 절차서는 스스로에게 "금지 목록"도 박아둔다 — 예컨대 "omd init recommend처럼 존재하지 않는 CLI 서브커맨드를 호출하지 말 것"이라는 문장이 SKILL.md 본문에 그대로 적혀 있다(§9에서 다시 다룬다).
design-md/toss/DESIGN.md의 frontmatter를 열어보면 verification_v2.claims 블록에 YAML 앵커(&tds_button)와 참조(*tds_button)를 써서, tokens.colors.primary 같은 각 토큰 값이 어느 화면(surface)·어느 출처(source)·어떤 방법(computed-style-and-official-doc)·언제(captured 날짜) 확인됐는지 일일이 매핑해 둔다. "그냥 그럴듯한 값"이 아니라 "이 값은 이 URL의 이 방법으로 이 날짜에 확인했다"는 감사 추적(audit trail)이다.
&name / *name)&tds_button으로 한 번 값을 "고정"해두고, 이후 *tds_button으로 그 값을 그대로 가져다 쓴다. oh-my-design은 이를 이용해 "여러 토큰이 같은 출처 하나를 공유한다"는 사실을 중복 없이 표현한다.
모든 채널이 같은 걸 받지 않는다. Claude Code는 스킬+18개 서브에이전트+훅+데이터 전체 번들을 받지만, Cursor는 규칙 파일 하나 + 공유 카탈로그만 받는다(서브에이전트·훅·스킬 없음). 이는 실수가 아니라 README가 명시한 설계 결정 — "Cursor는 omd:init 같은 스킬을 실행할 호스트가 아니다"라는 현실을 인정하고, Cursor 사용자에게는 미리 만든 DESIGN.md를 그대로 붙여 넣는 경로만 제공한다.
oh-my-design은 이미지를 그리거나 UI를 렌더링하지 않는다. 하는 일은 ①이미 검증된 텍스트 근거를 제공하고 ②그 근거를 읽고 쓰는 절차를 마크다운으로 코딩해 두는 것뿐이다. 실제 UI 코드 생성·이미지 판단은 여전히 호스트 에이전트(Claude Code 등)의 모델이 한다. "AI 로직을 찾는다"는 마음으로 src/만 뒤지면 실망한다 — 진짜 "로직"은 skills/*.md와 agents/*.md의 자연어 지시 안에 있다.
버전 진실원(source of truth)부터 짚으면: 루트 package.json의 version은 1.9.0이고, CHANGELOG.md 최신 항목도 "1.9.0 — 2026-07-17"로 정확히 일치한다. 클론한 HEAD는 그보다 나흘 뒤인 0a7f3a1(2026-07-21) — 버전을 올리지 않은 문서/레퍼런스 후속 커밋으로 보인다.
oh-my-design-cli (npm 배포 패키지)| 요소 | 무엇 / 왜 |
|---|---|
| 언어·빌드 | TypeScript + tsup(번들러). bin/oh-my-design.ts → dist/bin/oh-my-design.js로 빌드돼 oh-my-design/omd 두 이름으로 실행된다. |
| CLI 프레임워크 | commander 13 — install-skills·doctor 서브커맨드 정의. |
| 대화형 설치 UI | @clack/prompts — bare 실행 시 뜨는 TUI(Project/Global 스코프 선택 등). 색은 picocolors. |
| 테스트 | vitest 3. devDependency에 playwright-core도 있는데, 이는 선택 스킬 claude-design이 로그인된 Chrome의 claude.ai/design 세션을 여는 데 쓰인다(별도 API 호출 아님). |
| 엔진 | engines.node >= 18. |
web/ (oh-my-design.kr, 별도 미배포 패키지)
루트 CLI와 별개로, web/package.json(이름 web, 버전 0.1.0)이 정의하는 완전히 다른 Next.js 애플리케이션이 카탈로그 사이트·빌더·문서를 서빙한다.
| 요소 | 무엇 / 왜 |
|---|---|
| 프레임워크 | Next.js 16.2.6 + React 19.2.4. 스타일은 Tailwind CSS v4 + @base-ui/react, 모션은 framer-motion. |
| 레퍼런스 파이프라인 | scripts/build-registry.mjs(카탈로그 인덱스 생성) · build-reference-quality.mjs(품질 등급) · build-reference-ast.ts · build-embeddings.mjs(검색용 임베딩) — @anthropic-ai/sdk를 이 빌드 스크립트들이 사용(런타임 스킬 추론과는 별개). |
| 재검증(reverify) | build-reverify-queue.ts · run-reverify-batch.ts · capture-reference-evidence.ts — 라이브 사이트를 주기적으로 다시 스크래핑해 토큰 값이 드리프트했는지 확인하는 자체 파이프라인. |
| 데이터·분석 | @upstash/redis(성장 지표 스냅샷) · mixpanel-browser(제품 분석) · zod(스키마 검증) · react-markdown+rehype-sanitize(레퍼런스 원문 마크다운을 안전하게 렌더링). |
packages/mcp/
과거 카탈로그를 MCP(Model Context Protocol) 서버로 서빙하던 구현이 남아 있다(server.ts·tools/get-design-md.ts·tools/search-by-vibe.ts 등). README가 명시적으로 "은퇴했고, 아카이브로만 남는다"고 밝힌다 — 지금 스킬들은 로컬 카탈로그 파일 또는 oh-my-design.kr/<id>/design.md raw 라우트를 직접 읽지, MCP 서버를 거치지 않는다.
| 채널 | 설치 위치 | 받는 것 |
|---|---|---|
| Claude Code | .claude/ | 스킬 20개 + 서브에이전트 18개 + 훅 + 데이터 — 전체 번들 |
| Codex | .agents/skills/ + .codex/{agents,data}/ | 스킬 + 내장 서브에이전트 역할 + 로컬 카탈로그 |
| OpenCode | .opencode/{skills,agents,data}/ (전역은 ~/.config/opencode/…) | 스킬 + 네이티브 서브에이전트 + 카탈로그 |
| Cursor | .cursor/rules/omd-design.mdc | 규칙 파일 1개 + .claude/data 공유 카탈로그뿐 — 스킬·서브에이전트·훅 없음 |
설치 후 에이전트 앱을 완전히 재시작(Claude Code는 종료 후 재실행)해야 새로 생긴 스킬/훅 파일을 인식한다. 이후 doctor로 실제 파일 상태를 확인하는 습관을 들이라고 README가 강조한다.
업그레이드도 같은 명령(npx oh-my-design-cli@latest)을 다시 실행하면 되는데, sha256 마커 덕분에 관리 파일만 갱신되고 사용자가 손댄 파일은 그대로("skipped-drift") 유지된다.
npx oh-my-design-cli@latest로 채널을 고르고, 에이전트 재시작 후 doctor로 확인한다.
에이전트에게 예: "가족용 식단 관리 앱의 프로젝트 전용 DESIGN.md를 만들어줘. 토스를 레퍼런스로 쓰고, 검증된 사실만 남기고 제품 고유 사실은 먼저 물어봐줘." 라고 자연어로 요청한다. skill-activation.cjs 훅이 "DESIGN.md가 없고 UI 관련 요청 같다"고 판단되면 omd:init을 먼저 권하기도 한다.
omd:init의 7단계가 실행된다맥락 질문 → 카탈로그에서 top-5 추천(Claude Code에서는 화살표로 고르는 AskUserQuestion UI) → 사용자가 하나 확정 → 원본 DESIGN.md 로드 → 브랜드 서사용 사실 확인 → 하이브리드 변형 작성 → omd:sync로 shim 3종 설치. 결과로 프로젝트 루트에 DESIGN.md, CLAUDE.md/AGENTS.md/Cursor rule이 생긴다.
다음 프롬프트부터는 "DESIGN.md 읽고 홈 화면 디자인해줘" 처럼 요청하면, 에이전트가 커밋된 파일을 Read해 톤을 재사용한다. 전체 화면을 새로 짤 때는 omd:harness, 사용자 선호를 기록해두려면 omd:remember, 완성도 감사는 omd:feel/omd:slop-audit/omd:final-qa 같은 나머지 스킬들이 이어받는다.
packages/mcp/를 보고 "이게 현재 아키텍처구나" 오해server.ts·tools/search-by-vibe.ts 같은 파일이 멀쩡히 남아 있어 MCP 서버가 지금도 동작 중이라 착각하기 쉽다. 하지만 README는 "옛 카탈로그 MCP 전송은 은퇴했다"고 못 박는다. 현재 스킬들은 로컬 파일 또는 raw markdown 라우트를 직접 읽는다 — MCP 서버를 거치지 않는다.
omd:init) 때문에 CLI 서브커맨드가 있다고 착각omd:init, omd:sync 같은 이름 때문에 omd init, omd sync 같은 CLI 명령이 있을 것 같지만 존재하지 않는다. bin/oh-my-design.ts가 실제로 노출하는 명령은 bare 설치기, install-skills, doctor 셋뿐이다. skills/omd-init/SKILL.md 자체에도 "omd init recommend·omd init prepare·omd sync처럼 존재하지 않는 CLI 서브커맨드를 호출하지 말 것"이라는 금지 문구가 박혀 있다 — 저장소가 스스로 이 오해를 경계한다는 점이 흥미롭다.
레퍼런스 추천의 점수 계산(브랜드 힌트 +5점 등)은 src/ 어디에도 함수로 존재하지 않는다. 전부 skills/omd-init/SKILL.md 안의 산문 지시이고, 호스트 에이전트의 LLM이 그때그때 "머릿속으로" 계산한다. 결정론적으로 보이지만 실제 구현은 코드가 아니라 자연어 규칙이라는 점을 헷갈리면 안 된다.
skills/(레포 소스)와 .claude/skills/(설치된 사본)는 바이트 단위로 동일하지 않다실제로 diff해보면 두 omd-init/SKILL.md는 내용이 다르다 — 설치 과정에서 경로·마커가 채널에 맞게 조정되기 때문이다. "레포에 있는 스킬 파일 = 실제로 내 프로젝트에 깔리는 파일"이라고 단정하면 안 된다.
design-md/ 아래 디렉터리 수를 실제로 세어보면 정확히 440개(각각 DESIGN.md+README.md+.verification.md)로, README·배지의 "440+" 표기와 일치한다. 다만 이 숫자는 web/scripts/build-registry.mjs가 갱신하는 계속 늘어나는 값이므로, 이 문서를 나중에 다시 볼 때는 실제 값을 다시 확인하는 게 안전하다(참고로 이 딥다이브는 별점 수를 인용하지 않는다 — GitHub 스타는 변동성이 크고 이 문서의 근거 기준에 맞지 않는다).
| 대안 | oh-my-design과의 차이 |
|---|---|
| Style Dictionary 등 토큰 빌드 도구 | 디자인 토큰을 여러 플랫폼 코드(CSS 변수, Swift, Android XML 등)로 빌드하는 데 집중한다. 브랜드 보이스·원칙·페르소나 같은 "왜 이 색인가" 서사는 다루지 않는다. oh-my-design은 그 서사까지 문서화해 에이전트가 읽게 한다. |
| shadcn/ui, MUI 등 컴포넌트 라이브러리 | 바로 쓸 수 있는 코드/컴포넌트를 준다. 특정 브랜드 톤을 강제하지 않는다. oh-my-design은 코드를 주지 않고, 코드를 짤 때 참고할 규칙 문서만 준다 — 서로 배타적이지 않고 같이 쓰인다. |
| 범용 Claude Skills 마켓플레이스 | 서로 무관한 스킬을 잡다하게 모아둔다. oh-my-design은 디자인 워크플로 하나에 특화돼 있고, 검증된 440개 레퍼런스라는 자체 데이터 자산을 함께 배포한다는 점이 다르다. |
| Figma / Google Stitch 등 비주얼 디자인 툴 | 사람이 눈으로 보며 반복하는 비주얼 산출물을 만든다. oh-my-design은 그 결과를 텍스트 규격(DESIGN.md, Stitch의 design-md 규격을 뼈대로 함)으로 옮겨 에이전트가 코드를 짜기 직전에 읽는 계약서로 쓴다 — 경쟁이 아니라 다음 단계에 가깝다. |
| 손으로 쓴 CLAUDE.md/AGENTS.md 프롬프트 | 가장 흔한 현실의 대안이지만 검증된 근거·드리프트 감지·다채널 동기화가 전혀 없다. oh-my-design은 이 수작업을 sha256 마커 기반 관리 파일 체계로 자동화한다. |
· 1인 개발자~소규모 팀이 "토스처럼", "Linear-clone" 같은 즉흥 지시에 의존해 왔고, 그 결과가 세션마다 달라지는 걸 겪어본 사람.
· 이미 구독 중인 코딩 에이전트만으로 끝내고 싶고, 별도 API 키·MCP 서버·인프라를 새로 관리하고 싶지 않은 사람.
· 팀 안에 서로 다른 에이전트(Claude Code, Codex, Cursor 등)를 쓰는 사람이 섞여 있어 규칙을 한 곳에서 관리하고 싶은 경우.
· 이미 성숙한 자체 디자인 토큰 파이프라인(Style Dictionary 등)과 디자인 시스템 문서를 갖춘 대규모 조직 — 역할이 겹치지 않고 오히려 이중 관리가 될 수 있다.
· Claude Code/Codex/OpenCode/Cursor 계열이 아닌 다른 코딩 도구만 쓰는 경우 — 채널 지원이 이 넷으로 한정돼 있다.
기술적으로 이 레포에서 가장 배울 만한 것은 화려한 알고리즘이 아니라 "신뢰를 어떻게 파일 시스템 수준에서 기계적으로 보장하는가"다 — sha256 마커로 관리 파일과 사용자 수정본을 구분하고, YAML 앵커로 토큰 값마다 출처를 추적하고, 스킬 자신이 스스로의 오남용(존재하지 않는 CLI 호출)을 금지 문구로 막는 방식. "AI를 위한 문서 하나가 이 정도로 엄격하게 설계될 수 있다"는 사례로 읽으면 유익하다.