CLI·스킬 모음
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를 위한 문서 하나가 이 정도로 엄격하게 설계될 수 있다"는 사례로 읽으면 유익하다.
아래 경로와 명령은 모두 레포 루트를 기준으로 합니다. 터미널 실습에는 rg(파일 내용 검색 도구)와 Node.js를 사용하며, 로컬 파일 읽기와 메모리 안의 값 비교로 진행합니다.
목표: 레퍼런스에 적힌 값과 그 값을 뒷받침하는 관찰 기록을 연결합니다.
design-md/toss/DESIGN.md에서 색상·타이포·컴포넌트 관련 제목을 찾고, design-md/toss/.verification.md의 검증 기록을 읽습니다.rg -n '^## |^### ' design-md/toss/DESIGN.md
cat design-md/toss/.verification.md
완료 기준: 세 항목 모두 근거 위치를 설명할 수 있고, 직접 관찰된 내용·문서 설명·미확인 내용을 구분한 대조표가 있어야 합니다.
목표: 자연어로 적힌 절차에서도 입력·결과·중단 조건을 찾아냅니다.
skills/omd-init/SKILL.md 전체를 읽고, 단계 제목과 선택·실패 관련 문장을 찾아 표시합니다.cat skills/omd-init/SKILL.md
rg -n '^## Phase|참고용|중단|찾지 못' skills/omd-init/SKILL.md
완료 기준: 정상 흐름 하나와 세 분기를 설명한 표가 있어야 합니다. 특히 원문 부재 시 내용을 지어내지 않는 처리와, 참고용 저장이 프로젝트 표준 적용과 다른 처리를 거친다는 점을 짚어야 합니다.
목표: 실행 중인 에이전트의 신호, 프로젝트에 남은 도구 흔적, DESIGN.md를 읽게 하는 연결 규칙을 구별합니다.
src/core/agent-detect.ts에서 detectCallingAgent가 읽는 환경 변수와 detectInstalledAgents가 검사하는 경로를 각각 찾습니다..claude/만 있는 경우, AGENTS.md만 있는 경우, opencode.json만 있는 경우, .cursor/만 있는 경우입니다. 실제 파일을 만들지 않고 각 경우의 반환값을 예측한 뒤 테스트와 대조합니다.skills/omd-sync/SKILL.md를 읽고 CLAUDE.md·AGENTS.md·.cursor/rules/omd-design.mdc가 어떻게 DESIGN.md로 안내하는지 정리합니다. 관리 블록만 갱신하는 파일과 전체를 관리하는 파일도 나눕니다.cat src/core/agent-detect.ts
cat test/unit/core/agent-detect.test.ts
cat skills/omd-sync/SKILL.md
완료 기준: 다섯 경우에 대한 채널 감지 결과와 연결 파일별 관리 범위를 설명할 수 있어야 합니다. 파일 존재로 얻은 신호만으로 해당 앱이 현재 실행 중이라고 단정해서는 안 됩니다.
목표: 파일 내용의 지문인 해시가 변경을 드러내는 원리를 직접 확인합니다.
src/cli/hook-contract.ts의 stripManagedHookMarker·renderManagedHook·isCurrentManagedHook를 읽습니다. 해시를 계산할 때 기존 마커를 제외하는 이유를 설명해 봅니다..claude/hooks/skill-activation.cjs를 텍스트로 읽고, 마커를 뺀 본문으로 기준 해시를 만듭니다. 이어서 같은 본문과 공백을 더한 메모리 복사본을 각각 비교합니다.src/cli/install-skills.ts에서 관리 훅의 갱신 판정을 찾아봅니다. “현재 배포 원본과 동일함”과 “기록된 해시와 본문이 서로 일치함”이 각각 무엇을 확인하는지 정리합니다.node -e '
const { readFileSync } = require("node:fs");
const { createHash } = require("node:crypto");
const source = readFileSync(".claude/hooks/skill-activation.cjs", "utf8");
const raw = source.replace(/^\/\/ omd:installed-hook sha256=[0-9a-f]{64}\r?\n/m, "");
function hash(text) {
return createHash("sha256").update(text).digest("hex");
}
const expected = hash(raw);
console.log("같은 본문:", expected === hash(raw));
console.log("공백 추가:", expected === hash(raw + " "));
'
이 예제는 훅을 실행하지 않고 파일 내용만 읽습니다. 기준 해시는 읽은 본문에서 새로 계산하므로, 원본에 적힌 기존 마커의 유효성을 검사하는 예제와는 구분해야 합니다.
완료 기준: 비교 결과가 차례로 true·false여야 합니다. 또한 내용이 온전한 구버전 파일도 현재 배포 원본과는 다를 수 있다는 점을 설명할 수 있어야 합니다.
매주 “개념을 자기 말로 설명하기 → 관련 소스 읽기 → 확인 가능한 결과물 만들기” 순서로 진행합니다. 테스트 파일은 입력과 기대 결과를 보여주는 예제집으로 읽고, 소스의 판단 근거를 함께 찾습니다.
| 주차·배울 개념 | 이 레포에서 읽을 파일 | 결과물 |
|---|---|---|
| 1주차 디자인 토큰과 근거 |
design-md/toss/DESIGN.mddesign-md/toss/.verification.md |
색상·글꼴·컴포넌트 상태의 근거 대조표. 값의 적용 화면과 미확인 범위를 함께 적습니다. |
| 2주차 스킬과 상태 전이 |
skills/omd-init/SKILL.mdskills/omd-sync/SKILL.md |
입력·출력·선택·중단 조건을 담은 흐름도. 초기 설정에서 연결 파일 관리로 넘어가는 경계를 표시합니다. |
| 3주차 채널 감지와 연결 규칙 |
src/core/agent-detect.tstest/unit/core/agent-detect.test.tsskills/omd-sync/SKILL.md |
환경 변수와 파일 존재 신호의 비교표, 연결 파일별 관리 범위표. 사용자 작성 내용을 보존할 영역도 표시합니다. |
| 4주차 해시와 변경 감지 |
src/cli/hook-contract.ts.claude/hooks/skill-activation.cjssrc/cli/install-skills.ts |
원문과 메모리 복사본의 해시 비교 기록. 현재 버전과의 동일성 검사와 자체 해시 일치 검사를 구별합니다. |
| 5주차 진단과 반복 실행 |
src/cli/doctor.tstest/unit/cli/doctor.test.tstest/unit/cli/install-skills.test.ts |
설치 누락·사용자 수정·다시 설치하는 상황의 기대 동작표. 각 판단을 뒷받침하는 테스트 이름과 소스 위치를 붙입니다. |
마지막에는 “같은 설치를 반복해도 불필요한 변경이 없어야 한다”와 “사용자가 고친 내용을 구별해야 한다”는 요구를 각각 어떤 코드와 테스트가 맡는지 연결해 보세요. 이 연결표가 있으면 다른 설치기나 설정 동기화 도구도 같은 관점으로 읽을 수 있습니다.
---로 감싸는 구조화된 정보 영역입니다. skills/omd-init/SKILL.md에서는 스킬 이름과 설명을, 레퍼런스 DESIGN.md에서는 색상·타이포 같은 데이터를 확인할 수 있습니다.design-md/toss/처럼 기업별로 묶인 문서를 읽을 때는 해당 기업의 확인된 사실과 내 프로젝트에 적용할 판단을 구분합니다..verification.md를 대조해 관찰 대상·방법·시점과 확인 범위를 읽을 수 있습니다.skills/omd-init/SKILL.md처럼 마크다운으로 적힌 질문·선택·실패 처리 규칙도 실제 동작을 결정하므로 코드와 함께 읽어야 합니다.src/core/agent-detect.ts는 환경 변수와 프로젝트 경로를 살펴 채널을 판단할 신호를 찾습니다.skills/omd-sync/SKILL.md는 CLAUDE.md·AGENTS.md·Cursor 규칙 파일의 연결 내용을 관리합니다..claude/hooks/skill-activation.cjs는 DESIGN.md 존재 여부와 UI 관련 요청을 살펴 초기 설정 안내가 필요한지 판단합니다.src/cli/hook-contract.ts는 관리 훅의 본문으로 해시를 만들어 마커에 기록합니다.skills/omd-init/SKILL.md의 사용자 선택·참고용 저장·중단 경로를 표로 옮기면 자연어 절차도 이 관점으로 이해할 수 있습니다.test/unit/cli/install-skills.test.ts에는 다시 설치했을 때 기존 스킬 파일의 수정 시각이 유지되는지 확인하는 사례가 있습니다.