oh-my-design-cli 1.7.1 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.zh-TW.md CHANGED
@@ -5,19 +5,16 @@
5
5
  <h1 align="center">oh-my-design</h1>
6
6
 
7
7
  <p align="center">
8
- <strong>從 107 家真實企業的設計系統生成 DESIGN.md。</strong>互動式精靈。零 AI 呼叫。
9
- </p>
10
-
11
- <p align="center">
12
- <strong>新增 OmD v0.1 Philosophy Layer。</strong>Voice・Narrative・Principles・Personas・States・Motion — 讓 Claude Code 輸出你的品牌,而不是 AI 的預設值。
8
+ <strong>為 AI 編碼代理打造的技能驅動設計 — 一個指令完成引導。</strong>221 個真實企業設計系統。安裝過程零 AI 呼叫。之後只要和你的代理對話即可。
13
9
  </p>
14
10
 
15
11
  <p align="center">
12
+ <a href="https://www.npmjs.com/package/oh-my-design-cli"><img src="https://img.shields.io/npm/v/oh-my-design-cli?style=flat-square&color=cb3837" alt="npm version" /></a>
13
+ <a href="https://www.npmjs.com/package/oh-my-design-cli"><img src="https://img.shields.io/npm/dm/oh-my-design-cli?style=flat-square&color=cb3837" alt="npm downloads" /></a>
16
14
  <a href="LICENSE"><img src="https://img.shields.io/github/license/kwakseongjae/oh-my-design?style=flat-square" alt="License" /></a>
17
15
  <a href="https://github.com/kwakseongjae/oh-my-design/stargazers"><img src="https://img.shields.io/github/stars/kwakseongjae/oh-my-design?style=social" alt="GitHub Stars" /></a>
18
- <img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square" alt="PRs Welcome" />
19
- <img src="https://img.shields.io/badge/AI%20calls-zero-blue?style=flat-square" alt="Zero AI" />
20
- <img src="https://img.shields.io/badge/references-107-7c5cfc?style=flat-square" alt="107 References" />
16
+ <img src="https://img.shields.io/badge/references-221-7c5cfc?style=flat-square" alt="221 References" />
17
+ <img src="https://img.shields.io/badge/CLI%20commands-1-blue?style=flat-square" alt="One CLI command" />
21
18
  </p>
22
19
 
23
20
  <p align="center">
@@ -28,118 +25,50 @@
28
25
 
29
26
  ## 什麼是 oh-my-design?
30
27
 
31
- **oh-my-design (OmD)** 是一份開放規範,為 AI 編碼代理提供「足以產出品牌級 UI」的品牌脈絡,而不是依賴 AI 的統計預設值。
32
-
33
- [Google 提出的](https://stitch.withgoogle.com/docs/design-md/overview/) `DESIGN.md` 本質上是**令牌文件** — 色彩、字體、元件。必要,但不夠。只靠令牌產 UI,形狀看似合理,卻「不像任何品牌」,會收斂到 AI 的預設:Inter-on-white、紫色漸層、毫無緣由的 emoji。OmD v0.1 在其上疊加**品牌哲學層**:**Voice・Narrative・Principles・Personas・States・Motion**。將 OmD 格式的 `DESIGN.md` 放在專案根目錄,代理的輸出就不再通用,而是「你的」。
34
-
35
- 三個組成部分:
36
-
37
- 1. **[規範](spec/omd-v0.1.md)** — 版本化的 Google Stitch 擴充,MIT 授權。
38
- 2. **[Claude Code skill](.claude/skills/omd/SKILL.md)** — 將規範作為硬性約束自動套用。
39
- 3. **[107 個參考檔案](references/)** — 真實企業的 `DESIGN.md`,可以 fork、透過 builder 客製化後直接上線。
40
-
41
- **無須 API 金鑰。零 AI 呼叫。全部在客戶端執行。**
42
-
43
- ## OmD v0.1 Philosophy Layer
44
-
45
- OmD 在 Google Stitch 的 9 個章節之上再加的 6 個章節:
46
-
47
- | 章節 | 用途 |
48
- |---|---|
49
- | **10. Voice & Tone** | 微文案約束 — 按鈕文字、錯誤訊息、導引流程 |
50
- | **11. Brand Narrative** | 「為什麼」 — 品牌拒絕什麼、試圖撼動哪個類別 |
51
- | **12. Principles** | 令牌無法裁決時用來拍板的 5〜10 條第一性原理 |
52
- | **13. Personas** | 2〜4 位具體使用者,讓代理輸出扎根於實際情境 |
53
- | **14. States** | Empty / loading / error / skeleton 模式 — 避免通用的「無資料」 |
54
- | **15. Motion & Easing** | 命名的 duration + easing 令牌 — Stitch 9 章節遺漏的維度 |
55
-
56
- **目前已有 10 個參考附帶完整的 Philosophy Layer:**
57
- Toss · Claude · Line · Stripe · Linear · Vercel · Notion · Airbnb · Apple · Figma — 每個都包含 voice、narrative、principles、personas、states、motion,全部基於公開來源撰寫。
28
+ **oh-my-design (OmD)** 是為 AI 編碼代理打造的設計系統。它讓 Claude Code / Codex / OpenCode / Cursor 變成一位記得你品牌的資深產品設計師。安裝一次之後,只要描述你想要的東西 — 元件、畫面、文案、素材、圖表 — 代理就會套用專案的設計系統並交付成果。`DESIGN.md` 是品牌規格([Google Stitch](https://stitch.withgoogle.com/docs/design-md/overview/) 令牌 + 品牌哲學層: Voice / Narrative / Principles / Personas / States / Motion),套件內建 221 個真實企業的 DESIGN.md。**無須 API 金鑰。無須外部基礎設施。一切都在你既有的 CLI 工作階段內執行。**
58
29
 
59
- 完整 OmD v0.1 範例請見 [references/toss/DESIGN.md](references/toss/DESIGN.md)。
30
+ ## 安裝
60
31
 
61
- ## 主要功能
62
-
63
- - **Builder** — 選擇參考、調整色彩 / radius / 深色模式、挑選元件,然後按下 Export。透過 **Philosophy** 篩選可以只顯示具備完整品牌哲學的 10 個參考。
64
- - **Design Systems 目錄** ([oh-my-design.kr/design-systems](https://oh-my-design.kr/design-systems)) — 107 個參考中有 34 個擁有官方設計系統或品牌指南頁面,可從目錄配合即時縮圖直接前往。
65
- - **Personal Curation** ([oh-my-design.kr/curation](https://oh-my-design.kr/curation)) — 透過 MBTI 風格的簡短測驗,將你的設計偏好對應到 107 個參考之一,並直接帶你進入已預選該參考的 Builder。
66
-
67
- ## 107 個支援的參考
68
-
69
- | 類別 | 企業 |
70
- |------|------|
71
- | **AI & LLM** | Claude, Cohere, ElevenLabs, Minimax, Mistral AI, Ollama, OpenCode AI, Replicate, RunwayML, Together AI, VoltAgent, xAI |
72
- | **設計工具** | Airtable, Clay, Figma, Framer, Miro, Webflow |
73
- | **開發者工具** | Cursor, Expo, Lovable, Raycast, Superhuman, Vercel, Warp |
74
- | **生產力** | Cal.com, freee, Intercom, Linear, Mintlify, Notion, Resend, Zapier |
75
- | **消費科技** | Airbnb, Apple, Baemin, Dcard, IBM, Kakao, Karrot, LINE, Mercari, NVIDIA, Pinkoi, Pinterest, SpaceX, Spotify, Uber |
76
- | **金融科技** | Coinbase, Kraken, Revolut, Stripe, Toss, Wise |
77
- | **後端 & DevOps** | ClickHouse, Composio, Hashicorp, MongoDB, PostHog, Sanity, Sentry, Supabase |
78
- | **汽車** | BMW, Ferrari, Lamborghini, Renault, Tesla |
79
- | **行銷** | Semrush |
80
-
81
- > 使用 Builder 中的**國家篩選器**按地區瀏覽 (韓國、台灣、日本、法國、義大利、德國、英國、美國)。
82
-
83
- ## 匯出的 DESIGN.md
84
-
85
- 以 [Google Stitch DESIGN.md 格式](https://stitch.withgoogle.com/docs/design-md/overview/)為基礎 — 1〜9 章節,加上選用的 OmD v0.1 Philosophy Layer(10〜15 章節):
32
+ ```bash
33
+ npx oh-my-design-cli install-skills
34
+ ```
86
35
 
87
- **基礎 (Google Stitch)**
88
- 1. Visual Theme & Atmosphere
89
- 2. Color Palette & Roles
90
- 3. Typography Rules
91
- 4. Component Stylings
92
- 5. Layout Principles
93
- 6. Depth & Elevation
94
- 7. Do's and Don'ts
95
- 8. Responsive Behavior
96
- 9. Agent Prompt Guide
36
+ 安裝後請重新啟動你的代理 (Claude Code 為 Cmd+Q 後重新開啟) — 新的 skills + agents 才會載入。
97
37
 
98
- **OmD v0.1 Philosophy Layer (附加)**
38
+ 這是你唯一需要執行的 CLI 指令。其餘一切都是對代理說的自然語言。
99
39
 
100
- 10. Voice & Tone
101
- 11. Brand Narrative
102
- 12. Principles
103
- 13. Personas
104
- 14. States
105
- 15. Motion & Easing
40
+ ## 支援的代理
106
41
 
107
- 另加:Style Preferences、Included Components、Iconography & SVG Guidelines、Document Policies。
42
+ | 代理 | 通道 | 安裝內容 |
43
+ |---|---|---|
44
+ | **Claude Code** | `--agent claude-code` (預設) | 完整套件 — `.claude/` 下的 skills、16 個子代理、hooks、data |
45
+ | **Codex** | `--agent codex` | `.agents/skills/` 技能套件 (官方 discovery 路徑) |
46
+ | **OpenCode** | `--agent opencode` | `.opencode/skills/` 技能套件 |
47
+ | **Cursor** | `--agent cursor` | 正式 rules 通道 — `.cursor/rules/omd-design.mdc` shim + 共用 `.claude/data` 目錄 (不含 skills/hooks) |
108
48
 
109
- ## 專案結構
49
+ 預設會安裝到所有偵測到的代理; 只要單一通道請加 `--agent <name>`。
110
50
 
111
- ```
112
- oh-my-design/
113
- spec/ OmD v0.1 規範 (正本)
114
- .claude/skills/omd/ Claude Code skill 包
115
- references/ 107 家企業的 DESIGN.md 檔案
116
- src/ CLI 核心 (TypeScript)
117
- web/ Next.js 網頁 builder
118
- src/app/ Landing + Builder + Directory 頁面
119
- src/components/ Wizard、Preview、Export
120
- test/ CLI Vitest 套件 (unit/、integration/、scripts/)
121
- ```
51
+ ## 套件內容
122
52
 
123
- Web 測試與原始碼並列存放 (`web/src/**/*.test.ts`)。
53
+ **17 skills · 16 個子代理 · 221 個經驗證的參考 · 活性化 hooks** — 上述一個指令全部安裝完成。
124
54
 
125
- ## 測試
55
+ 每個參考也以 raw markdown 形式提供於 `oh-my-design.kr/design-systems/<id>.md`,代理可以直接抓取。完整的 skill 與 agent 參考文件: **[oh-my-design.kr/docs](https://oh-my-design.kr/docs)**。
126
56
 
127
- 兩套測試套件,皆以 Vitest 執行,兩套都必須通過:
57
+ ## 升級
128
58
 
129
59
  ```bash
130
- npm test # CLI:370 個測試 — unit + 全 reference smoke
131
- cd web && npm test # Web:107 個測試 — generate-css、config-hash、survey
60
+ npx oh-my-design-cli@latest install-skills
132
61
  ```
133
62
 
134
- 整合套件 (`test/integration/all-references.test.ts`) 會對每個 `references/<id>/DESIGN.md` 執行完整的生成管線,因此損壞的 reference 會在 PR 審查時以單一 reference 的失敗形式呈現。資料夾規範與模組別覆蓋率對照表請參考 [test/README.md](test/README.md)
135
-
136
- ## 致謝
63
+ Idempotent。帶有 `<!-- omd:installed-skill -->` 標記的受管檔案會就地更新,使用者編輯過的檔案則保持不動 (要覆寫請加 `--force`)。重新執行後請重新啟動代理。
137
64
 
138
- - [VoltAgent/awesome-design-md](https://github.com/VoltAgent/awesome-design-md) — 啟動本專案的上游 DESIGN.md 集合。
139
- - [kzhrknt/awesome-design-md-jp](https://github.com/kzhrknt/awesome-design-md-jp) — 日本市場的設計系統參考。
65
+ ## 連結
140
66
 
141
- oh-my-design 在這些集合的基礎上加入了互動式客製化精靈、A/B 風格偏好、元件選擇、Design Systems 目錄與 CLI 匯出管線。
67
+ - **目錄** — [oh-my-design.kr/design-systems](https://oh-my-design.kr/design-systems)
68
+ - **精選集** — [oh-my-design.kr/collections](https://oh-my-design.kr/collections)
69
+ - **文件** — [oh-my-design.kr/docs](https://oh-my-design.kr/docs)
70
+ - **更新紀錄** — [CHANGELOG.md](CHANGELOG.md)
142
71
 
143
72
  ## 授權
144
73
 
145
- [MIT](LICENSE)
74
+ [MIT](LICENSE) — 參考資料屬於各企業所有,僅為教育性參考而重現。
package/agents/AGENT.md CHANGED
@@ -16,9 +16,9 @@ A 60-line operational context card. Loaded into the project at install via `omd
16
16
  - `agents/` — canonical 11 sub-agent definitions (master + 10 specialists; source-of-truth, generates `.claude/agents/` and `.codex/agents/`)
17
17
  - `skills/omd-harness/` — entry skill that calls master orchestrator
18
18
  - `skills/omd-init/`, `skills/omd-apply/`, `skills/omd-remember/`, `skills/omd-learn/`, `skills/omd-sync/` — existing OmD skills
19
- - `data/reference-fingerprints.json` — reference voice fingerprint manifest (skill-side semantic match)
19
+ - `data/reference-fingerprints.json` — 67-reference voice fingerprint manifest (skill-side semantic match)
20
20
  - `data/vocabulary.json`, `data/synonyms.json`, `data/reference-tags.md` — controlled vocab + tagging
21
- - `references/<id>/DESIGN.md` — bundled reference design systems
21
+ - `references/<id>/DESIGN.md` × 67 — bundled reference design systems
22
22
  - `spec/omd-v0.1.md` — OmD spec (15-section DESIGN.md format)
23
23
  - `.omd/runs/run-<ts>-<slug>/` — every harness run; permanent archive
24
24
  - `skills/omd-lab-02-design-harness/runs/v<N>-...` — Lab #02 versioned experiments
@@ -41,7 +41,7 @@ A 60-line operational context card. Loaded into the project at install via `omd
41
41
  - 999 → never fabricate §11–13 facts
42
42
  - 9999 → never invent tokens absent from DESIGN.md
43
43
  - 99999 → never auto-skip user checkpoints
44
- - 999999 → never invent reference ids only ids present in `reference-fingerprints.json` (items[].id) are valid.
44
+ - 999999 → never invent reference ids; 67-only catalog
45
45
  - 9999999 → never claim success when output is empty; Read the file
46
46
  - 99999999 → never overwrite previous iteration; snapshot to `iteration-<N>/`
47
47
 
@@ -119,7 +119,7 @@ Each turn you are in one state. Determine current state from `.handoff.json` `st
119
119
  - **FIGMA_GUIDANCE**: User pasted Figma file URL.
120
120
  - Tell user: "Figma URL은 v4에서 직접 추출이 안 돼요. 두 가지 방법이 있어요:
121
121
  1. Tokens Studio 플러그인으로 JSON export → 그 path 알려주세요
122
- 2. 우리 reference 카탈로그에서 가장 가까운 톤 골라서 시작 (catalog id로 답변)"
122
+ 2. 우리 67-catalog에서 가장 가까운 톤 골라서 시작 (catalog id로 답변)"
123
123
  - Wait for user. Either parse JSON path → fold into `extracted_tokens`, or treat as catalog selection.
124
124
 
125
125
  - **PRODUCTION_TRANSITION** (CRITICAL — re-engage when user says "프로덕션화" / "production" / "ship" / "deploy" / "실배포" mid-flight): User just shifted from prototyping to productionizing. **Don't fall back to plain coding.** **Don't extract DESIGN.md mechanically from prototype HTML/CSS** — that produces generic spec without brand DNA. Curate via reference matching instead.
@@ -132,14 +132,14 @@ Each turn you are in one state. Determine current state from `.handoff.json` `st
132
132
  - tone keywords from visible microcopy (e.g., "calm / encouraging / not-pushy" from "오늘 첫 잔으로 시작해요")
133
133
  - 5 short adjectives describing the *atmosphere* (NOT a full token dump)
134
134
 
135
- ### Step 2 — Reference matching (reference 카탈로그)
135
+ ### Step 2 — Reference matching (67 catalog)
136
136
  Score against `data/reference-fingerprints.json` using the signal above + voice_fingerprint + tone_keywords. Identify top 2-3 closest references.
137
137
 
138
138
  ### Step 3 — Curation proposal (the wow point)
139
139
  Surface the matched references as a *curation question*, not a token dump:
140
140
 
141
141
  ```
142
- prototype 한 번 보고 왔어요. 톤은 calm-blue + 응원하는 듯한 친근함 + 잔잔한 모션 — reference 카탈로그 중 toss + lovable이 가장 가깝게 보여요.
142
+ prototype 한 번 보고 왔어요. 톤은 calm-blue + 응원하는 듯한 친근함 + 잔잔한 모션 — 67-catalog 중 toss + lovable이 가장 가깝게 보여요.
143
143
  • toss — 차분한 calm-cerulean + 숫자 강조 + 한국 핀테크 절제미
144
144
  • lovable — parchment cream + 휴머니스트 + 응원하는 따뜻함
145
145
 
@@ -149,7 +149,7 @@ Each turn you are in one state. Determine current state from `.handoff.json` `st
149
149
  - go (toss base + drop delta) — 추천
150
150
  - lovable base + drop delta
151
151
  - 둘 다 섞기 (toss 60 / lovable 40)
152
- - 다른 reference 골라볼게 (reference 카탈로그 보여줘)
152
+ - 다른 reference 골라볼게 (catalog 67 보여줘)
153
153
  - 그냥 prototype에서 바로 추출 (덜 추천 — generic해질 수 있음)
154
154
  ```
155
155
 
@@ -168,7 +168,16 @@ Each turn you are in one state. Determine current state from `.handoff.json` `st
168
168
  ```
169
169
  (Edit 툴로 첫 줄 prepend.)
170
170
 
171
- **Step 4.2 — Reference DESIGN.md Read.** `Read references/<chosen_ref_id>/DESIGN.md` (예: `references/toss/DESIGN.md`). reference 카탈로그 안의 모든 ref에 DESIGN.md 있음.
171
+ **Step 4.2 — Reference DESIGN.md Read.** chosen ref의 DESIGN.md 다음 우선순위로 resolve (`<id>` = chosen_ref_id, omd:init Phase 4.1과 동일):
172
+
173
+ <!-- omd:catalog-resolution-order — omd-init/omd-harness/omd-reference-capture SKILL.md 와 동일 순서 강제. drift guard: test/unit/core/catalog-resolution-order.test.ts -->
174
+
175
+ 1. `.claude/data/references/<id>/DESIGN.md` (installer가 복사 — npx 설치 기본 경로)
176
+ 2. `node_modules/oh-my-design-cli/web/references/<id>/DESIGN.md` (로컬 npm 설치 직접 경로)
177
+ 3. `web/references/<id>/DESIGN.md` (개발 레포)
178
+ 4. `https://oh-my-design.kr/design-systems/<id>.md` 를 fetch (WebFetch 또는 `curl -fsSL`) — 200이면 본문이 곧 reference DESIGN.md. 가져온 내용을 `.claude/data/references/<id>/DESIGN.md`로 캐시해 다음부터는 로컬 캐시(경로 1)로 잡히게 한다.
179
+
180
+ 4개 경로 전부 miss면 **DESIGN.md를 임의로 지어내지 말 것** — 사용자에게 reference 자료 누락을 알리고 종료. 카탈로그 안의 모든 ref에 DESIGN.md 있음.
172
181
 
173
182
  **Step 4.3 — delta axes 추론.** 사용자 description + chosen ref base를 비교해서 다음 axes 중 사용자가 명시했거나 함의한 것만 shift 대상으로 표시:
174
183
  - `hue_deg` (색상 각도, 예: +30 = warmer rotation)
@@ -303,7 +312,7 @@ When user says "이 부분 좀 따뜻하게" / "더 세련되게" / "여기 좁
303
312
  **RULE 7.5 — Vague modifier disambiguator (don't guess).**
304
313
  When `signal-classifier` returns `vague_modifier !== null` (e.g., "좀 더 세련되게", "warmer", "여백 답답해"):
305
314
  1. Do NOT silently apply your guess — that's how you produce wrong work the user has to reject.
306
- 2. Call `scoreCandidatesForModifier` (in `src/core/visual-anchor.ts`) with current reference + axis + direction + the full reference catalog.
315
+ 2. Call `scoreCandidatesForModifier` (in `src/core/visual-anchor.ts`) with current reference + axis + direction + 67-catalog.
307
316
  3. Get top 3-4 reference candidates that move in the requested direction.
308
317
  4. Build picker via `modifierDisambiguatorPicker` and present:
309
318
  ```
@@ -537,7 +546,7 @@ Audit trail. Persists across master spawns within a run.
537
546
  - **999.** Never fabricate §11–13 facts. Use `[FILL IN]` placeholder.
538
547
  - **9999.** Never introduce a token absent from DESIGN.md without going through Phase 5.
539
548
  - **99999.** Never auto-skip mandatory user gates (Phase 3, Phase 5, SHIP_GATE).
540
- - **999999.** Never invent reference ids — only ids present in `reference-fingerprints.json` (items[].id) are valid.
549
+ - **999999.** Never invent reference ids — only the 67 in `reference-fingerprints.json` are valid.
541
550
  - **9999999.** Never claim sub-agent succeeded when output is missing/empty. Read the file.
542
551
  - **99999999.** Never overwrite previous iteration artifacts without snapshot.
543
552
 
@@ -60,4 +60,4 @@ You write microcopy. Every word you write must be derivable from `DESIGN.md §10
60
60
 
61
61
  Write a single `components/microcopy.json` containing all slots. No prose response — just the JSON file written.
62
62
 
63
- If §10 is missing from DESIGN.md, halt and report to master: "DESIGN.md §10 missing — cannot write microcopy without voice spec. Ask omd-master to populate §10 (Voice) before microcopy can be written."
63
+ If §10 is missing from DESIGN.md, halt and report to master: "DESIGN.md §10 missing — cannot write microcopy without voice spec. Run omd init Phase 4.5 to populate."
@@ -23,7 +23,7 @@ omd_managed: true
23
23
 
24
24
  ## 입력
25
25
 
26
- - `target` — 분석 대상 (e.g., `web/src/app/page.tsx`, 라이브 URL, 또는 wireframe 파일)
26
+ - `target` — 분석 대상 (e.g., `src/app/page.tsx` 같은 사용자 프로젝트의 페이지 파일, 라이브 URL, 또는 wireframe 파일)
27
27
  - `design_md_path` — DESIGN.md (있으면 §6 Depth / §15 Motion cite 의무)
28
28
  - `output_path` — `<run_dir>/audits/ux-engineer/<section>.md` 또는 단일 `audit.md`
29
29
  - `sections` — (선택) 분석할 섹션. 미지정 시 자동 분리 (omd-ux-writer와 동일 알고리즘)
@@ -94,6 +94,8 @@ omd_managed: true
94
94
 
95
95
  ## Output 포맷
96
96
 
97
+ 아래 audit 블록은 **가상의 Next.js 프로젝트 예시** — 경로/라인 번호는 실제 분석 대상 프로젝트의 파일 기준으로 채운다 (특정 레포의 경로가 아님).
98
+
97
99
  ```markdown
98
100
  # UX Engineering Audit — <target>
99
101
 
@@ -107,7 +109,7 @@ Live URL fetched: <yes/no>
107
109
  ### 현재 구현 (코드 인용)
108
110
 
109
111
  ```tsx
110
- // web/src/app/page.tsx:24-45
112
+ // src/app/page.tsx:24-45
111
113
  <section className="...">
112
114
  <h1>...</h1>
113
115
  ...
@@ -141,7 +143,7 @@ Live URL fetched: <yes/no>
141
143
 
142
144
  #### Fix 1 — Focus styles (priority: HIGH)
143
145
 
144
- `web/src/app/globals.css:12` 에 추가:
146
+ `src/app/globals.css:12` 에 추가:
145
147
  ```css
146
148
  /* Focus styles — WCAG 2.1.1 + 2.4.7 */
147
149
  :where(button, a, input, textarea, select):focus-visible {
@@ -153,7 +155,7 @@ Live URL fetched: <yes/no>
153
155
 
154
156
  #### Fix 2 — CTA 위계 (priority: HIGH)
155
157
 
156
- `web/src/app/page.tsx:38-44` 변경:
158
+ `src/app/page.tsx:38-44` 변경:
157
159
  - "Open Builder" — primary (filled, brand-500, large)
158
160
  - "GitHub" — secondary (outline, neutral)
159
161
  - "Get a personal curation" — tertiary (text link only, smaller, muted)
@@ -170,7 +172,7 @@ Live URL fetched: <yes/no>
170
172
 
171
173
  #### Fix 3 — Motion easing (priority: MED)
172
174
 
173
- `web/src/app/animations.css:5` 변경:
175
+ `src/app/animations.css:5` 변경:
174
176
  ```css
175
177
  /* Before */
176
178
  .animate-fade-in { animation: fadeIn 600ms linear both; }
@@ -187,7 +189,7 @@ Live URL fetched: <yes/no>
187
189
 
188
190
  #### Fix 4 — Mobile pt (priority: MED)
189
191
 
190
- `web/src/app/page.tsx:18`:
192
+ `src/app/page.tsx:18`:
191
193
  ```tsx
192
194
  // Before
193
195
  <section className="pt-10 sm:pt-28">
@@ -198,7 +200,7 @@ Live URL fetched: <yes/no>
198
200
 
199
201
  #### Fix 5 — font-display (priority: LOW but easy)
200
202
 
201
- `web/src/app/layout.tsx:18`:
203
+ `src/app/layout.tsx:18`:
202
204
  ```tsx
203
205
  const inter = Inter({
204
206
  subsets: ["latin"],
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: omd-ux-researcher
3
- description: Reads bundled oh-my-design references (the bundled reference catalog), researches competing services, validates Tier-1 official design system URLs. Returns concise, URL-cited findings. Read-only — never writes outside the run directory.
3
+ description: Reads bundled oh-my-design references (67 companies), researches competing services, validates Tier-1 official design system URLs. Returns concise, URL-cited findings. Read-only — never writes outside the run directory.
4
4
  tools: Read, Glob, Grep, WebSearch, WebFetch, Bash, Write
5
5
  model: opus
6
6
  ---
@@ -18,7 +18,7 @@ omd_managed: true
18
18
 
19
19
  ## 입력
20
20
 
21
- - `target` — 분석 대상 (e.g., `web/src/app/page.tsx`, `<run_dir>/wireframes/landing.md`, 또는 화면 id)
21
+ - `target` — 분석 대상 (e.g., `src/app/page.tsx` 같은 사용자 프로젝트의 페이지 파일, `<run_dir>/wireframes/landing.md`, 또는 화면 id)
22
22
  - `design_md_path` — DESIGN.md (없으면 voice 기준 약화 — 사용자에게 init 권유 후 일반 원칙만 사용)
23
23
  - `output_path` — `<run_dir>/audits/ux-writer/<section>.md` 또는 단일 `audit.md`
24
24
  - `sections` — (선택) 분석할 섹션 list. 미지정 시 페이지 전체 자동 분리.
@@ -24,10 +24,10 @@ function readPackageVersion() {
24
24
  }
25
25
  var program = new Command();
26
26
  program.name("oh-my-design").description("Bootstrap oh-my-design skills + agents into your project. After install, talk to your agent in natural language \u2014 no other CLI commands.").version(readPackageVersion()).showSuggestionAfterError(true).showHelpAfterError(true);
27
- program.command("install-skills").description("Install omd skill files + canonical agents into agent directories (.claude/, .codex/, .opencode/). Interactive multiselect TUI by default \u2014 picks which skills + sub-agents to install.").option("--dir <path>", "Project root (defaults to cwd)").option("--agent <name...>", "Restrict to specific channels (claude-code | codex | opencode)").option("--force", "Overwrite existing files even without the omd marker").option("--all", "Skip the interactive TUI and install every shipped skill + agent (use in CI)").option("--skills <names>", "Comma-separated skill names to install (overrides TUI)", (v) => v.split(",").map((s) => s.trim()).filter(Boolean)).option("--agents-only <names>", "Comma-separated agent names to install (overrides TUI). Use --agents-only to disambiguate from --agent (channel selector).", (v) => v.split(",").map((s) => s.trim()).filter(Boolean)).option("--skills-only", "Install only the named skill files \u2014 skip sub-agents, hooks, and settings.json (minimal single-skill install, e.g. --skills claude-design --skills-only)").option("--global", "Install to the user-level dir (~/.claude/skills, available in every project) instead of this project. Writes skills + sub-agents; never touches global hooks/settings.").action(
27
+ program.command("install-skills").description("Install omd skill files + canonical agents into agent directories (.claude/, .codex/, .opencode/). Interactive multiselect TUI by default \u2014 picks which skills + sub-agents to install.").option("--dir <path>", "Project root (defaults to cwd)").option("--agent <name...>", "Restrict to specific channels (claude-code | codex | opencode | cursor)").option("--force", "Overwrite existing files even without the omd marker").option("--all", "Skip the interactive TUI and install every shipped skill + agent (use in CI)").option("--skills <names>", "Comma-separated skill names to install (overrides TUI)", (v) => v.split(",").map((s) => s.trim()).filter(Boolean)).option("--agents-only <names>", "Comma-separated agent names to install (overrides TUI). Use --agents-only to disambiguate from --agent (channel selector).", (v) => v.split(",").map((s) => s.trim()).filter(Boolean)).option("--skills-only", "Install only the named skill files \u2014 skip sub-agents, hooks, and settings.json (minimal single-skill install, e.g. --skills claude-design --skills-only)").option("--global", "Install to the user-level dir (~/.claude/skills, available in every project) instead of this project. Writes skills + sub-agents; never touches global hooks/settings.").action(
28
28
  async (opts) => {
29
- const { runInstallSkills } = await import("../install-skills-YYHEC4CS.js");
30
- const validAgents = ["claude-code", "codex", "opencode"];
29
+ const { runInstallSkills } = await import("../install-skills-7UUDOLG2.js");
30
+ const validAgents = ["claude-code", "codex", "opencode", "cursor"];
31
31
  const agents = opts.agent ? opts.agent.filter(
32
32
  (a) => validAgents.includes(a)
33
33
  ) : void 0;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../bin/oh-my-design.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { readFileSync, existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nfunction readPackageVersion(): string {\n let cur = dirname(fileURLToPath(import.meta.url));\n for (let i = 0; i < 8; i++) {\n const pkg = join(cur, 'package.json');\n if (existsSync(pkg)) {\n try {\n return JSON.parse(readFileSync(pkg, 'utf8')).version ?? '0.0.0';\n } catch {\n return '0.0.0';\n }\n }\n const parent = dirname(cur);\n if (parent === cur) break;\n cur = parent;\n }\n return '0.0.0';\n}\n\nconst program = new Command();\n\nprogram\n .name('oh-my-design')\n .description('Bootstrap oh-my-design skills + agents into your project. After install, talk to your agent in natural language — no other CLI commands.')\n .version(readPackageVersion())\n .showSuggestionAfterError(true)\n .showHelpAfterError(true);\n\nprogram\n .command('install-skills')\n .description('Install omd skill files + canonical agents into agent directories (.claude/, .codex/, .opencode/). Interactive multiselect TUI by default — picks which skills + sub-agents to install.')\n .option('--dir <path>', 'Project root (defaults to cwd)')\n .option('--agent <name...>', 'Restrict to specific channels (claude-code | codex | opencode)')\n .option('--force', 'Overwrite existing files even without the omd marker')\n .option('--all', 'Skip the interactive TUI and install every shipped skill + agent (use in CI)')\n .option('--skills <names>', 'Comma-separated skill names to install (overrides TUI)', (v) => v.split(',').map((s) => s.trim()).filter(Boolean))\n .option('--agents-only <names>', 'Comma-separated agent names to install (overrides TUI). Use --agents-only to disambiguate from --agent (channel selector).', (v) => v.split(',').map((s) => s.trim()).filter(Boolean))\n .option('--skills-only', 'Install only the named skill files — skip sub-agents, hooks, and settings.json (minimal single-skill install, e.g. --skills claude-design --skills-only)')\n .option('--global', 'Install to the user-level dir (~/.claude/skills, available in every project) instead of this project. Writes skills + sub-agents; never touches global hooks/settings.')\n .action(\n async (opts: {\n dir?: string;\n agent?: string[];\n force?: boolean;\n all?: boolean;\n skills?: string[];\n agentsOnly?: string[];\n skillsOnly?: boolean;\n global?: boolean;\n }) => {\n const { runInstallSkills } = await import('../src/cli/install-skills.js');\n const validAgents = ['claude-code', 'codex', 'opencode'] as const;\n type Agent = (typeof validAgents)[number];\n const agents = opts.agent\n ? (opts.agent.filter((a): a is Agent =>\n (validAgents as readonly string[]).includes(a)\n ) as Agent[])\n : undefined;\n const code = await runInstallSkills({\n dir: opts.dir,\n agents,\n force: opts.force,\n all: opts.all,\n skillsFilter: opts.skills,\n agentsFilter: opts.agentsOnly,\n skillsOnly: opts.skillsOnly,\n global: opts.global,\n });\n if (code !== 0) process.exit(code);\n }\n );\n\nprogram.parse();\n"],"mappings":";;;AAAA,SAAS,eAAe;AACxB,SAAS,cAAc,kBAAkB;AACzC,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAE9B,SAAS,qBAA6B;AACpC,MAAI,MAAM,QAAQ,cAAc,YAAY,GAAG,CAAC;AAChD,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,MAAM,KAAK,KAAK,cAAc;AACpC,QAAI,WAAW,GAAG,GAAG;AACnB,UAAI;AACF,eAAO,KAAK,MAAM,aAAa,KAAK,MAAM,CAAC,EAAE,WAAW;AAAA,MAC1D,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AACA,UAAM,SAAS,QAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK;AACpB,UAAM;AAAA,EACR;AACA,SAAO;AACT;AAEA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,cAAc,EACnB,YAAY,+IAA0I,EACtJ,QAAQ,mBAAmB,CAAC,EAC5B,yBAAyB,IAAI,EAC7B,mBAAmB,IAAI;AAE1B,QACG,QAAQ,gBAAgB,EACxB,YAAY,8LAAyL,EACrM,OAAO,gBAAgB,gCAAgC,EACvD,OAAO,qBAAqB,gEAAgE,EAC5F,OAAO,WAAW,sDAAsD,EACxE,OAAO,SAAS,8EAA8E,EAC9F,OAAO,oBAAoB,0DAA0D,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,EAC7I,OAAO,yBAAyB,8HAA8H,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,EACtN,OAAO,iBAAiB,+JAA0J,EAClL,OAAO,YAAY,wKAAwK,EAC3L;AAAA,EACC,OAAO,SASD;AACJ,UAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,+BAA8B;AACxE,UAAM,cAAc,CAAC,eAAe,SAAS,UAAU;AAEvD,UAAM,SAAS,KAAK,QACf,KAAK,MAAM;AAAA,MAAO,CAAC,MACjB,YAAkC,SAAS,CAAC;AAAA,IAC/C,IACA;AACJ,UAAM,OAAO,MAAM,iBAAiB;AAAA,MAClC,KAAK,KAAK;AAAA,MACV;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,KAAK,KAAK;AAAA,MACV,cAAc,KAAK;AAAA,MACnB,cAAc,KAAK;AAAA,MACnB,YAAY,KAAK;AAAA,MACjB,QAAQ,KAAK;AAAA,IACf,CAAC;AACD,QAAI,SAAS,EAAG,SAAQ,KAAK,IAAI;AAAA,EACnC;AACF;AAEF,QAAQ,MAAM;","names":[]}
1
+ {"version":3,"sources":["../../bin/oh-my-design.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { readFileSync, existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nfunction readPackageVersion(): string {\n let cur = dirname(fileURLToPath(import.meta.url));\n for (let i = 0; i < 8; i++) {\n const pkg = join(cur, 'package.json');\n if (existsSync(pkg)) {\n try {\n return JSON.parse(readFileSync(pkg, 'utf8')).version ?? '0.0.0';\n } catch {\n return '0.0.0';\n }\n }\n const parent = dirname(cur);\n if (parent === cur) break;\n cur = parent;\n }\n return '0.0.0';\n}\n\nconst program = new Command();\n\nprogram\n .name('oh-my-design')\n .description('Bootstrap oh-my-design skills + agents into your project. After install, talk to your agent in natural language — no other CLI commands.')\n .version(readPackageVersion())\n .showSuggestionAfterError(true)\n .showHelpAfterError(true);\n\nprogram\n .command('install-skills')\n .description('Install omd skill files + canonical agents into agent directories (.claude/, .codex/, .opencode/). Interactive multiselect TUI by default — picks which skills + sub-agents to install.')\n .option('--dir <path>', 'Project root (defaults to cwd)')\n .option('--agent <name...>', 'Restrict to specific channels (claude-code | codex | opencode | cursor)')\n .option('--force', 'Overwrite existing files even without the omd marker')\n .option('--all', 'Skip the interactive TUI and install every shipped skill + agent (use in CI)')\n .option('--skills <names>', 'Comma-separated skill names to install (overrides TUI)', (v) => v.split(',').map((s) => s.trim()).filter(Boolean))\n .option('--agents-only <names>', 'Comma-separated agent names to install (overrides TUI). Use --agents-only to disambiguate from --agent (channel selector).', (v) => v.split(',').map((s) => s.trim()).filter(Boolean))\n .option('--skills-only', 'Install only the named skill files — skip sub-agents, hooks, and settings.json (minimal single-skill install, e.g. --skills claude-design --skills-only)')\n .option('--global', 'Install to the user-level dir (~/.claude/skills, available in every project) instead of this project. Writes skills + sub-agents; never touches global hooks/settings.')\n .action(\n async (opts: {\n dir?: string;\n agent?: string[];\n force?: boolean;\n all?: boolean;\n skills?: string[];\n agentsOnly?: string[];\n skillsOnly?: boolean;\n global?: boolean;\n }) => {\n const { runInstallSkills } = await import('../src/cli/install-skills.js');\n const validAgents = ['claude-code', 'codex', 'opencode', 'cursor'] as const;\n type Agent = (typeof validAgents)[number];\n const agents = opts.agent\n ? (opts.agent.filter((a): a is Agent =>\n (validAgents as readonly string[]).includes(a)\n ) as Agent[])\n : undefined;\n const code = await runInstallSkills({\n dir: opts.dir,\n agents,\n force: opts.force,\n all: opts.all,\n skillsFilter: opts.skills,\n agentsFilter: opts.agentsOnly,\n skillsOnly: opts.skillsOnly,\n global: opts.global,\n });\n if (code !== 0) process.exit(code);\n }\n );\n\nprogram.parse();\n"],"mappings":";;;AAAA,SAAS,eAAe;AACxB,SAAS,cAAc,kBAAkB;AACzC,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAE9B,SAAS,qBAA6B;AACpC,MAAI,MAAM,QAAQ,cAAc,YAAY,GAAG,CAAC;AAChD,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,MAAM,KAAK,KAAK,cAAc;AACpC,QAAI,WAAW,GAAG,GAAG;AACnB,UAAI;AACF,eAAO,KAAK,MAAM,aAAa,KAAK,MAAM,CAAC,EAAE,WAAW;AAAA,MAC1D,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AACA,UAAM,SAAS,QAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK;AACpB,UAAM;AAAA,EACR;AACA,SAAO;AACT;AAEA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,cAAc,EACnB,YAAY,+IAA0I,EACtJ,QAAQ,mBAAmB,CAAC,EAC5B,yBAAyB,IAAI,EAC7B,mBAAmB,IAAI;AAE1B,QACG,QAAQ,gBAAgB,EACxB,YAAY,8LAAyL,EACrM,OAAO,gBAAgB,gCAAgC,EACvD,OAAO,qBAAqB,yEAAyE,EACrG,OAAO,WAAW,sDAAsD,EACxE,OAAO,SAAS,8EAA8E,EAC9F,OAAO,oBAAoB,0DAA0D,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,EAC7I,OAAO,yBAAyB,8HAA8H,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,EACtN,OAAO,iBAAiB,+JAA0J,EAClL,OAAO,YAAY,wKAAwK,EAC3L;AAAA,EACC,OAAO,SASD;AACJ,UAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,+BAA8B;AACxE,UAAM,cAAc,CAAC,eAAe,SAAS,YAAY,QAAQ;AAEjE,UAAM,SAAS,KAAK,QACf,KAAK,MAAM;AAAA,MAAO,CAAC,MACjB,YAAkC,SAAS,CAAC;AAAA,IAC/C,IACA;AACJ,UAAM,OAAO,MAAM,iBAAiB;AAAA,MAClC,KAAK,KAAK;AAAA,MACV;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,KAAK,KAAK;AAAA,MACV,cAAc,KAAK;AAAA,MACnB,cAAc,KAAK;AAAA,MACnB,YAAY,KAAK;AAAA,MACjB,QAAQ,KAAK;AAAA,IACf,CAAC;AACD,QAAI,SAAS,EAAG,SAAQ,KAAK,IAAI;AAAA,EACnC;AACF;AAEF,QAAQ,MAAM;","names":[]}