oh-my-design-cli 1.3.8 → 1.5.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.
Files changed (138) hide show
  1. package/README.ja.md +8 -8
  2. package/README.ko.md +28 -7
  3. package/README.md +71 -16
  4. package/README.zh-TW.md +8 -8
  5. package/agents/omd-asset-curator.md +2 -7
  6. package/agents/omd-codex-image.md +49 -0
  7. package/agents/omd-designer-review.md +38 -0
  8. package/agents/omd-final-qa.md +40 -0
  9. package/agents/omd-kr-writer.md +35 -0
  10. package/agents/omd-locale-adapter.md +32 -0
  11. package/agents/omd-master.md +3 -13
  12. package/agents/omd-orchestrator.md +34 -0
  13. package/data/reference-audits/2026-05-14-kr10.md +72 -0
  14. package/data/reference-audits/2026-05-15-kr10.md +124 -0
  15. package/data/reference-fingerprints.json +253 -3
  16. package/data/research/2026-05-18-agent-landscape.md +69 -0
  17. package/data/research/2026-05-18-kr-style-presets.md +572 -0
  18. package/dist/bin/oh-my-design.js +6 -3
  19. package/dist/bin/oh-my-design.js.map +1 -1
  20. package/dist/{install-skills-MVXVXYAY.js → install-skills-IETT2TBJ.js} +91 -8
  21. package/dist/install-skills-IETT2TBJ.js.map +1 -0
  22. package/package.json +9 -3
  23. package/skills/omd-apply/SKILL.md +0 -1
  24. package/skills/omd-codex-image/SKILL.md +162 -0
  25. package/skills/omd-designer-review/SKILL.md +146 -0
  26. package/skills/omd-final-qa/SKILL.md +153 -0
  27. package/skills/omd-kr-writer/SKILL.md +229 -0
  28. package/skills/omd-locale-adapter/SKILL.md +124 -0
  29. package/skills/omd-orchestrator/SKILL.md +124 -0
  30. package/web/references/29cm/DESIGN.md +11 -2
  31. package/web/references/ably/DESIGN.md +12 -2
  32. package/web/references/airbnb/DESIGN.md +17 -2
  33. package/web/references/airtable/DESIGN.md +20 -0
  34. package/web/references/apple/DESIGN.md +17 -2
  35. package/web/references/baemin/DESIGN.md +11 -2
  36. package/web/references/banksalad/DESIGN.md +17 -2
  37. package/web/references/bmw/DESIGN.md +14 -0
  38. package/web/references/bunjang/DESIGN.md +308 -0
  39. package/web/references/cal/DESIGN.md +14 -0
  40. package/web/references/catchtable/DESIGN.md +262 -0
  41. package/web/references/channeltalk/DESIGN.md +374 -0
  42. package/web/references/classum/DESIGN.md +217 -0
  43. package/web/references/claude/DESIGN.md +11 -2
  44. package/web/references/clay/DESIGN.md +19 -0
  45. package/web/references/clickhouse/DESIGN.md +19 -0
  46. package/web/references/cohere/DESIGN.md +20 -0
  47. package/web/references/coinbase/DESIGN.md +14 -0
  48. package/web/references/composio/DESIGN.md +14 -0
  49. package/web/references/coupang/DESIGN.md +17 -2
  50. package/web/references/cursor/DESIGN.md +20 -0
  51. package/web/references/dabang/DESIGN.md +210 -0
  52. package/web/references/dcard/DESIGN.md +11 -2
  53. package/web/references/elevenlabs/DESIGN.md +20 -0
  54. package/web/references/expo/DESIGN.md +20 -0
  55. package/web/references/fastcampus/DESIGN.md +460 -0
  56. package/web/references/ferrari/DESIGN.md +14 -0
  57. package/web/references/figma/DESIGN.md +17 -2
  58. package/web/references/flex/DESIGN.md +309 -0
  59. package/web/references/framer/DESIGN.md +20 -0
  60. package/web/references/freee/DESIGN.md +16 -2
  61. package/web/references/gangnamunni/DESIGN.md +18 -2
  62. package/web/references/gmarket/DESIGN.md +464 -0
  63. package/web/references/hashicorp/DESIGN.md +19 -0
  64. package/web/references/ibm/DESIGN.md +20 -0
  65. package/web/references/inflearn/DESIGN.md +396 -0
  66. package/web/references/intercom/DESIGN.md +14 -0
  67. package/web/references/jumpit/DESIGN.md +366 -0
  68. package/web/references/kakao/DESIGN.md +14 -0
  69. package/web/references/kakaobank/DESIGN.md +17 -2
  70. package/web/references/kakaopay/DESIGN.md +17 -2
  71. package/web/references/karrot/DESIGN.md +16 -2
  72. package/web/references/kbank/DESIGN.md +195 -0
  73. package/web/references/kraken/DESIGN.md +14 -0
  74. package/web/references/krds/DESIGN.md +17 -2
  75. package/web/references/kream/DESIGN.md +382 -0
  76. package/web/references/kurly/DESIGN.md +11 -2
  77. package/web/references/lamborghini/DESIGN.md +14 -0
  78. package/web/references/line/DESIGN.md +17 -2
  79. package/web/references/linear.app/DESIGN.md +17 -2
  80. package/web/references/lovable/DESIGN.md +14 -0
  81. package/web/references/lunit/DESIGN.md +249 -0
  82. package/web/references/mercari/DESIGN.md +11 -2
  83. package/web/references/minimax/DESIGN.md +14 -0
  84. package/web/references/mintlify/DESIGN.md +14 -0
  85. package/web/references/miro/DESIGN.md +20 -0
  86. package/web/references/mistral.ai/DESIGN.md +20 -0
  87. package/web/references/mongodb/DESIGN.md +19 -0
  88. package/web/references/musinsa/DESIGN.md +11 -2
  89. package/web/references/naver/DESIGN.md +17 -2
  90. package/web/references/notion/DESIGN.md +11 -2
  91. package/web/references/nvidia/DESIGN.md +11 -2
  92. package/web/references/ohouse/DESIGN.md +11 -2
  93. package/web/references/oliveyoung/DESIGN.md +342 -0
  94. package/web/references/ollama/DESIGN.md +14 -0
  95. package/web/references/opencode.ai/DESIGN.md +20 -0
  96. package/web/references/pinkoi/DESIGN.md +11 -2
  97. package/web/references/pinterest/DESIGN.md +19 -0
  98. package/web/references/posthog/DESIGN.md +20 -0
  99. package/web/references/qanda/DESIGN.md +11 -2
  100. package/web/references/raycast/DESIGN.md +19 -0
  101. package/web/references/remember/DESIGN.md +17 -2
  102. package/web/references/renault/DESIGN.md +14 -0
  103. package/web/references/replicate/DESIGN.md +14 -0
  104. package/web/references/resend/DESIGN.md +20 -0
  105. package/web/references/revolut/DESIGN.md +14 -0
  106. package/web/references/ridi/DESIGN.md +11 -2
  107. package/web/references/runwayml/DESIGN.md +14 -0
  108. package/web/references/sanity/DESIGN.md +20 -0
  109. package/web/references/sentry/DESIGN.md +14 -0
  110. package/web/references/socar/DESIGN.md +17 -2
  111. package/web/references/spacex/DESIGN.md +11 -2
  112. package/web/references/spotify/DESIGN.md +14 -0
  113. package/web/references/stripe/DESIGN.md +11 -2
  114. package/web/references/supabase/DESIGN.md +20 -0
  115. package/web/references/superhuman/DESIGN.md +20 -0
  116. package/web/references/tesla/DESIGN.md +11 -2
  117. package/web/references/together.ai/DESIGN.md +20 -0
  118. package/web/references/toss/DESIGN.md +16 -2
  119. package/web/references/toss-securities/DESIGN.md +193 -0
  120. package/web/references/tving/DESIGN.md +259 -0
  121. package/web/references/uber/DESIGN.md +19 -0
  122. package/web/references/upbit/DESIGN.md +276 -0
  123. package/web/references/upstage/DESIGN.md +214 -0
  124. package/web/references/vercel/DESIGN.md +17 -2
  125. package/web/references/voltagent/DESIGN.md +14 -0
  126. package/web/references/wadiz/DESIGN.md +344 -0
  127. package/web/references/wanted/DESIGN.md +16 -2
  128. package/web/references/warp/DESIGN.md +14 -0
  129. package/web/references/webflow/DESIGN.md +14 -0
  130. package/web/references/wise/DESIGN.md +19 -0
  131. package/web/references/x.ai/DESIGN.md +14 -0
  132. package/web/references/yanolja/DESIGN.md +17 -2
  133. package/web/references/yeogiotte/DESIGN.md +18 -2
  134. package/web/references/zapier/DESIGN.md +20 -0
  135. package/web/references/zigbang/DESIGN.md +12 -2
  136. package/web/references/zigzag/DESIGN.md +17 -2
  137. package/agents/omd-3d-blender.md +0 -269
  138. package/dist/install-skills-MVXVXYAY.js.map +0 -1
@@ -1,3 +1,17 @@
1
+ ---
2
+ id: warp
3
+ name: Warp
4
+ country: US
5
+ category: developer-tools
6
+ homepage: "https://www.warp.dev"
7
+ primary_color: "#01a4ff"
8
+ logo:
9
+ type: simpleicons
10
+ slug: warp
11
+ verified: "2026-05-15"
12
+ omd: "0.1"
13
+ ---
14
+
1
15
  # Design System Inspiration of Warp
2
16
 
3
17
  ## 1. Visual Theme & Atmosphere
@@ -1,3 +1,17 @@
1
+ ---
2
+ id: webflow
3
+ name: Webflow
4
+ country: US
5
+ category: design-tools
6
+ homepage: "https://webflow.com"
7
+ primary_color: "#146ef5"
8
+ logo:
9
+ type: simpleicons
10
+ slug: webflow
11
+ verified: "2026-05-15"
12
+ omd: "0.1"
13
+ ---
14
+
1
15
  # Design System Inspiration of Webflow
2
16
 
3
17
  ## 1. Visual Theme & Atmosphere
@@ -1,3 +1,22 @@
1
+ ---
2
+ id: wise
3
+ name: Wise
4
+ country: UK
5
+ category: fintech
6
+ homepage: "https://wise.com"
7
+ primary_color: "#9fe870"
8
+ logo:
9
+ type: simpleicons
10
+ slug: wise
11
+ verified: "2026-05-15"
12
+ omd: "0.1"
13
+ ds:
14
+ name: Wise Design
15
+ url: "https://wise.design"
16
+ type: system
17
+ description: Wise's design system covering foundations, components, patterns, and tone of voice.
18
+ ---
19
+
1
20
  # Design System Inspiration of Wise
2
21
 
3
22
  ## 1. Visual Theme & Atmosphere
@@ -1,3 +1,17 @@
1
+ ---
2
+ id: x.ai
3
+ name: xAI
4
+ country: US
5
+ category: ai
6
+ homepage: "https://x.ai"
7
+ primary_color: "#000000"
8
+ logo:
9
+ type: simpleicons
10
+ slug: x
11
+ verified: "2026-05-15"
12
+ omd: "0.1"
13
+ ---
14
+
1
15
  # Design System Inspiration of xAI
2
16
 
3
17
  ## 1. Visual Theme & Atmosphere
@@ -1,6 +1,21 @@
1
1
  ---
2
- omd: 0.1
3
- brand: Yanolja
2
+ id: yanolja
3
+ name: Yanolja
4
+ country: KR
5
+ category: consumer-tech
6
+ homepage: "https://www.yanolja.com"
7
+ primary_color: "#000000"
8
+ logo:
9
+ type: favicon
10
+ slug: "https://www.google.com/s2/favicons?domain=yanolja.com&sz=128"
11
+ verified: "2026-05-15"
12
+ omd: "0.1"
13
+ ds:
14
+ name: Yanolja Brand Center
15
+ url: "https://www.yanoljagroup.com/brand_center"
16
+ type: brand
17
+ description: Yanolja's official brand center — visual identity inspired by the Multiverse of Dreams.
18
+ og_image: "https://www.yanoljagroup.com/common/assets/yanolja_colored_og_image.jpg"
4
19
  ---
5
20
 
6
21
  # Design System Inspiration of Yanolja (야놀자)
@@ -1,6 +1,22 @@
1
1
  ---
2
- omd: 0.1
3
- brand: 여기어때 (GoodChoice)
2
+ id: yeogiotte
3
+ name: 여기어때
4
+ display_name_kr: 여기어때 (GoodChoice)
5
+ country: KR
6
+ category: consumer-tech
7
+ homepage: "https://www.yeogi.com"
8
+ primary_color: "#000000"
9
+ logo:
10
+ type: favicon
11
+ slug: "https://www.yeogi.com/favicon/rel_icon/favicon_png_192.png"
12
+ verified: "2026-05-15"
13
+ omd: "0.1"
14
+ ds:
15
+ name: 여기어때 Design Library
16
+ url: "https://designlibrary.yeogi.com/"
17
+ type: system
18
+ description: 여기어때 디자인 라이브러리 — A Visual Language for Travel. Foundations, components, and tokens.
19
+ og_image: "https://framerusercontent.com/assets/kA6JROOLbG0jX7SQZl1tLZzahM.jpg"
4
20
  ---
5
21
 
6
22
  # Design System Inspiration of 여기어때 (GoodChoice / Yeogiotte)
@@ -1,3 +1,23 @@
1
+ ---
2
+ id: zapier
3
+ name: Zapier
4
+ country: US
5
+ category: productivity
6
+ homepage: "https://zapier.com"
7
+ primary_color: "#ff4f00"
8
+ logo:
9
+ type: simpleicons
10
+ slug: zapier
11
+ verified: "2026-05-15"
12
+ omd: "0.1"
13
+ ds:
14
+ name: Zapier Brand
15
+ url: "https://brand.zapier.com"
16
+ type: brand
17
+ description: Zapier's official brand guidelines 1.0.
18
+ og_image: "https://firebasestorage.googleapis.com/v0/b/standards-site-beta.appspot.com/o/documents%2F279072ea39f%2F8fc2c38ae5f%2Fmeta%2Fthumbnail_1_2.jpg?alt=media&token=0d0ea63f-6a32-4e46-b516-9db3c6c6ffe4"
19
+ ---
20
+
1
21
  # Design System Inspiration of Zapier
2
22
 
3
23
  ## 1. Visual Theme & Atmosphere
@@ -1,6 +1,16 @@
1
1
  ---
2
- omd: 0.1
3
- brand: Zigbang (직방)
2
+ id: zigbang
3
+ name: Zigbang
4
+ display_name_kr: Zigbang (직방)
5
+ country: KR
6
+ category: consumer-tech
7
+ homepage: "https://www.zigbang.com"
8
+ primary_color: "#0066ff"
9
+ logo:
10
+ type: favicon
11
+ slug: "https://www.google.com/s2/favicons?domain=zigbang.com&sz=256"
12
+ verified: "2026-05-15"
13
+ omd: "0.1"
4
14
  ---
5
15
 
6
16
  # Design System Inspiration of Zigbang (직방)
@@ -1,6 +1,21 @@
1
1
  ---
2
- omd: 0.1
3
- brand: ZIGZAG
2
+ id: zigzag
3
+ name: ZIGZAG
4
+ country: KR
5
+ category: ecommerce
6
+ homepage: "https://zigzag.kr"
7
+ primary_color: "#fa6ee3"
8
+ logo:
9
+ type: favicon
10
+ slug: "https://www.google.com/s2/favicons?domain=zigzag.kr&sz=256"
11
+ verified: "2026-05-15"
12
+ omd: "0.1"
13
+ ds:
14
+ name: ZIGZAG Tech / Brunch
15
+ url: "https://brunch.co.kr/@zigzag/73"
16
+ type: brand
17
+ description: Kakaostyle / ZIGZAG's brand & design articles — the ZDS (ZIGZAG Design System) rearchitecture and the 2021 cool-pink rebrand.
18
+ og_image: "https://img1.daumcdn.net/thumb/R1280x0.fjpg/?fname=http://t1.daumcdn.net/brunch/service/user/4Zzt/image/-3UDP-Htu127zH73hWgxU-DsWNg.jpg"
4
19
  ---
5
20
 
6
21
  # Design System Inspiration of ZIGZAG (지그재그)
@@ -1,269 +0,0 @@
1
- ---
2
- name: omd-3d-blender
3
- description: 3D 자산이 필요할 때 호출되는 Blender MCP 전문 agent. Blender + blender-mcp 설치 walk-through + Claude Code MCP 등록 + 실제 3D 모델/render 생성. 설치 미완 시 Hyper3D Rodin 또는 2D photo fallback. 트리거 — asset-curator가 type=3d / mockup / render / model을 식별했을 때, 또는 사용자가 "blender / 3D 모델 / 렌더링 / 3D 목업" 발화.
4
- tools: Read, Write, Edit, Bash, Glob, Grep
5
- model: opus
6
- omd_managed: true
7
- ---
8
-
9
- # omd-3d-blender — 3D Asset Specialist via Blender MCP
10
-
11
- 3D 자산 (제품 mockup / 앱 아이콘 3D 변형 / hero render / GLB export) 필요할 때 master 또는 asset-curator가 spawn한다. Blender MCP connector ([ahujasid/blender-mcp](https://github.com/ahujasid/blender-mcp), Anthropic 2026-04-28 공식 인정 [anthropic.com/news/claude-for-creative-work](https://www.anthropic.com/news/claude-for-creative-work)) 활용.
12
-
13
- ## 0. PRE-FLIGHT — OmD context 학습 (CRITICAL, 모든 흐름의 첫 단계)
14
-
15
- **임의의 generic 3D 모델 금지.** Blender 명령 한 줄도 내리기 전에, 이 프로젝트의 brand DNA를 흡수한다. 다음 5개 source를 *순차로* read하고 결과를 한 블록으로 정리:
16
-
17
- ### Source 1 — `DESIGN.md` (프로젝트 root, 또는 `.omd/runs/run-X/DESIGN.md.patch`)
18
- - **§1 Visual Theme** — 분위기 (calm / vibrant / institutional / playful 등) → 3D atmosphere 결정
19
- - **§2 Color Palette** — 모든 hex → Principled BSDF Base Color 후보. **임의 색 추가 X**.
20
- - **§3 Typography** — 3D 안에 텍스트 들어가면 font family 일치 시킴
21
- - **§6 Depth & Elevation** — shadow 정책 (single-layer? multi-layer?) + IOR / metalness / roughness 힌트
22
- - **§7 Do's and Don'ts** — 3D에서도 그대로 강제 (e.g., "no gradient bg" → 3D 배경에 gradient X)
23
- - **§10 Voice & Tone** — 3D의 mood 결정 (formal → restrained 표면 / playful → 살짝 cartoon)
24
- - **§11 Brand Narrative** — atmospheric 의도 ("절제 + 신뢰" → glassy minimal vs "활기 + 친근" → soft pastel)
25
- - **§12 Principles** — 거부 default ("Blue is interaction, not decoration" → 3D hero에 brand-blue 과용 X)
26
- - **§14 States** — empty/loading state 3D variant 필요 시 참조
27
- - **§15 Motion & Easing** — keyframe 타이밍 + signature motion (예: "balance slide ease-spring")
28
-
29
- ### Source 2 — `.omd/preferences.md`
30
- - pending entries 중 3D / visual / material 관련 사용자 교정 우선 반영
31
- - "no glass-on-glass shine" / "shadow는 항상 한 톤 어둡게" 같은 누적 취향
32
-
33
- ### Source 3 — `<run_dir>/brief.md`
34
- - audience (누구에게 보여질 3D인가)
35
- - tone_seed (calm-blue / warm / etc)
36
- - anti_patterns (브랜드가 거부하는 default)
37
-
38
- ### Source 4 — `<run_dir>/references-cited.md`
39
- - 매칭된 reference의 atmosphere → 3D mood 단서
40
- - (선택) `references/<chosen_id>/DESIGN.md` 직접 read해서 §1/§6/§15 분위기 흡수
41
-
42
- ### Source 5 — `prototype/index.html` 또는 현재 구현 코드
43
- - 이미 사용된 색·radius·motion → 3D와 visual continuity 유지
44
-
45
- ### Output — OMD-CONTEXT block (master에게 handoff에 포함)
46
-
47
- ```
48
- OMD CONTEXT LOADED for 3D asset <id>:
49
- ─────────────────────────────────────────
50
- - 프로젝트: <intent 한 줄>
51
- - Reference base: <ref_id> + delta hints
52
- - §2 Palette (cited only): brand-blue #3182f6 / accent #22c55e / muted #64748b
53
- - §6 Depth policy: single-layer pure black, low opacity (institutional finance trust signal)
54
- - §10 Voice: calm-restrained → 3D는 quiet matte over glossy
55
- - §12 Principles applied: "Blue is interaction not decoration" → 3D hero는 neutral 톤, brand-blue는 액센트만
56
- - §15 Motion: signature "balance slide" ease-out → 3D keyframe interpolation: BEZIER ease_out, 250ms
57
- - User preferences (last 7 pending): "shadow 한 톤 어둡게" (pref #12), "no glass-on-glass refraction" (pref #34)
58
- - Anti-patterns (3D 적용): no gradient bg, no purple shadow, no neon energy
59
- - Atmosphere target: calm + restrained + breathing room — *NOT* vibrant/playful/aggressive
60
- ─────────────────────────────────────────
61
- ```
62
-
63
- 이 context를 모든 후속 결정에 *cite*. 예:
64
- - ❌ "유리잔에 부드러운 광택 추가" — 근거 없음
65
- - ✅ "유리 material — IOR 1.45 (§6 Depth 'single-layer'), Specular 0.5 (Voice §10 quiet matte over glossy), brand-blue tint는 5% only (§12 Principle)"
66
-
67
- Context 로드 실패 (DESIGN.md 없음 등) → master에게 escalate: "OmD context 부족 — DESIGN.md emit 먼저 권장. 3D 진행 보류."
68
-
69
- ## 1. 입력
70
-
71
- Master / asset-curator가 spawn 시 다음을 prompt에 전달:
72
-
73
- - `asset_id` — 식별자 (e.g., `hero-water-glass-3d`)
74
- - `asset_spec` — 텍스트 명세 (e.g., "Toss-blue calm-cerulean liquid in transparent glass, isometric 3/4 angle, soft lifted shadow")
75
- - `output_dir` — `<run_dir>/assets/3d/`
76
- - `design_md_path` — DESIGN.md (palette / 톤 hint 추출용)
77
- - `project_kind` — Blender 미설치 가능성 신호 (없으면 user-facing prose)
78
-
79
- ## 2. Pre-flight — Blender MCP 사용 가능?
80
-
81
- ```bash
82
- # 1. Claude Code의 MCP 등록 확인
83
- ls ~/.claude.json 2>/dev/null
84
- grep -l "blender" ~/.claude.json 2>/dev/null # 또는 .mcp.json
85
- ```
86
-
87
- 세 갈래:
88
-
89
- ### Path A — 이미 설치/등록됨
90
- - `/mcp` 명령 또는 시도해서 `blender` tool group 보이면 OK → Step 4 (실제 사용)
91
-
92
- ### Path B — 설치 안 됨, 사용자가 설치 원함
93
- → Step 3 (walk-through)
94
-
95
- ### Path C — 사용자가 설치 거부 / Blender 환경 X
96
- → Hyper3D Rodin 또는 2D photo fallback (Step 5)
97
-
98
- ## 3. 설치 walk-through (Path B) — 인라인 Bash 시퀀스
99
-
100
- CLI 위임 없음. 다음 단계를 자연어로 사용자와 합의하고 Bash 툴로 직접 실행한다.
101
-
102
- ### 3.1 사용자에게 (prose handoff)
103
-
104
- > "3D 렌더로 진행하려면 Blender + MCP connector가 필요해요 (~3분, 한 번만). 진행할까요?"
105
-
106
- 사용자 confirm 받기 전엔 어떤 brew/install 명령도 실행하지 않는다.
107
-
108
- ### 3.2 uv 체크 + 설치
109
-
110
- ```bash
111
- uv --version 2>/dev/null
112
- ```
113
-
114
- exit 0 아니면 (macOS):
115
-
116
- ```bash
117
- brew install uv
118
- ```
119
-
120
- linux/win에서 uv 없으면 `https://docs.astral.sh/uv/` 안내 후 사용자 install 대기.
121
-
122
- ### 3.3 Blender 앱 체크 + 설치
123
-
124
- macOS:
125
-
126
- ```bash
127
- test -d /Applications/Blender.app
128
- ```
129
-
130
- 없으면:
131
-
132
- ```bash
133
- brew install --cask blender
134
- ```
135
-
136
- (약 300MB, 2-3분.) Linux/Win은 `https://www.blender.org/download/` 안내.
137
-
138
- ### 3.4 claude mcp add (1회)
139
-
140
- ```bash
141
- claude mcp list 2>&1 | grep -i blender
142
- ```
143
-
144
- 매칭 없으면:
145
-
146
- ```bash
147
- claude mcp add blender uvx blender-mcp
148
- ```
149
-
150
- ### 3.5 Blender addon 설치 (사용자 GUI 작업, 우회 불가)
151
-
152
- 다음을 Bash로 실행해서 addon.py를 다운로드한 후 사용자에게 GUI 단계 안내:
153
-
154
- ```bash
155
- curl -L -o /tmp/blender-mcp-addon.py https://raw.githubusercontent.com/ahujasid/blender-mcp/main/addon.py
156
- ```
157
-
158
- 사용자에게 자연어로:
159
-
160
- > "Blender 앱 안에서 한 번만 해주시면 됩니다.
161
- > 1. Edit → Preferences → Add-ons → Install from Disk → /tmp/blender-mcp-addon.py 선택
162
- > 2. 'Interface: Blender MCP' 체크박스 활성화
163
- > 3. 3D viewport(큐브 보이는 영역) 안에 마우스 두고 N 키 → 우측 BlenderMCP 탭 → 'Connect to Claude' 클릭
164
- > 4. Claude Code 재시작 (Cmd+Q → claude 다시) — 새 MCP 적재용
165
- >
166
- > 끝나면 'done' 답해주세요."
167
-
168
- ### 3.6 검증
169
-
170
- 사용자 'done' 후:
171
-
172
- ```bash
173
- claude mcp list 2>&1 | grep -i blender
174
- ```
175
-
176
- 등록 확인되면 Step 4 진행.
177
-
178
- ### 트러블슈팅
179
-
180
- - `uv command not found` → brew PATH 이슈: `eval "$(/opt/homebrew/bin/brew shellenv)"`
181
- - Blender 'Install from Disk' 안 보임 → Preferences → Add-ons 우상단 dropdown (4.x UI)
182
- - 'Connect to Claude' 안됨 → 다른 Blender 인스턴스 종료, port 충돌
183
-
184
- ## 4. Blender MCP로 실제 3D 생성
185
-
186
- 설치된 상태에서 master가 호출. asset_spec → Blender 명령 변환:
187
-
188
- ### 명령 시퀀스 예시 (water-glass mockup)
189
-
190
- ```
191
- 1. mcp__blender__get_scene_info() — 현재 씬 확인
192
- 2. mcp__blender__execute_blender_code(...) — 기본 씬 정리:
193
- import bpy
194
- bpy.ops.object.select_all(action='SELECT')
195
- bpy.ops.object.delete()
196
- 3. mcp__blender__create_primitive(type='cylinder', height=0.18, radius=0.04) — glass body
197
- 4. mcp__blender__execute_blender_code(...) — bevel modifier + transparent material
198
- 5. mcp__blender__create_primitive(type='cylinder', height=0.13, radius=0.038) — water inside
199
- 6. mcp__blender__set_material(...) — water material (DESIGN.md §2 brand-blue + IOR 1.33 + roughness 0.05)
200
- 7. mcp__blender__execute_blender_code(...) — camera 3/4 isometric, sun light + soft area light
201
- 8. mcp__blender__viewport_screenshot() → save base64 to <output_dir>/<asset_id>.png
202
- 9. mcp__blender__execute_blender_code(...) — bpy.ops.export_scene.gltf(filepath="...glb")
203
- 10. assets/manifest.json 엔트리 추가
204
- ```
205
-
206
- ### 명령 매핑 — DESIGN.md tokens → Blender material
207
-
208
- ```python
209
- # DESIGN.md §2 Color Palette → Principled BSDF Base Color
210
- # DESIGN.md §6 Depth → roughness / specular
211
- # DESIGN.md §15 Motion (signature ease) → Blender keyframe interpolation 후보
212
- ```
213
-
214
- DESIGN.md 토큰을 *그대로* 사용. 임의 색/material X. (Master rule 9999: never invent token absent from DESIGN.md).
215
-
216
- ### 출력
217
-
218
- - `<output_dir>/<asset_id>.png` — viewport screenshot (1024×1024 권장)
219
- - `<output_dir>/<asset_id>.glb` — `<model-viewer>` 웹 임베드용
220
- - `assets/manifest.json` 엔트리:
221
- ```json
222
- {
223
- "id": "hero-water-glass-3d",
224
- "type": "3d-render",
225
- "source": "blender-mcp",
226
- "license": "self-generated",
227
- "files": {
228
- "preview_png": "assets/3d/hero-water-glass-3d.png",
229
- "model_glb": "assets/3d/hero-water-glass-3d.glb"
230
- },
231
- "blender_version": "4.5",
232
- "tokens_cited": ["§2 brand-blue (#3182f6)", "§6 shadow-soft"],
233
- "generated_at": "<ISO>"
234
- }
235
- ```
236
-
237
- ## 5. Fallback — Blender 환경 없을 때
238
-
239
- ### Hyper3D Rodin (text → 3D, blender-mcp의 부가 기능)
240
- 설치 안 했으면 사용 불가. user-facing 안내: "Blender 설치 안 하시면 Hyper3D Rodin도 못 써요. 2D photo로 대체할게요."
241
-
242
- ### 2D photo fallback
243
- asset-curator의 정상 fallback chain (Unsplash/Pexels) 활용. asset-curator에게 다시 위임 + manifest에 `original_intent: 3d-render, downgraded_to: 2d-photo, reason: blender-not-installed` 기록.
244
-
245
- ## 6. Hard rules
246
-
247
- - **Never** execute arbitrary Python in Blender without showing user a one-line summary first ("이 코드 실행할게요: ..."). blender-mcp의 `execute_blender_code`는 *no sandbox* — 사용자가 보안 인지해야 함.
248
- - **Always** cite DESIGN.md token for every visual claim (color / spacing / material).
249
- - **Always** produce both .png preview AND .glb (사용자가 둘 다 검토 가능).
250
- - **Never** override existing 3D files — 새 timestamp suffix.
251
- - **Always** record `blender_version` in manifest (재현성).
252
- - **Never** propose installation of unrelated tools (no Cinema4D, Maya, Houdini suggestions — 우리 범위는 Blender).
253
-
254
- ## 7. 사용자 안내 prose 톤
255
-
256
- 설치 안내는 **친절하지만 짧게**. 명령은 copy-paste 가능. 각 step 1-2 줄.
257
- 실패 시: "[정확한 증상] → [한 줄 fix]" 패턴. 길게 troubleshooting하지 말 것.
258
-
259
- ## 8. 한계 / 주의
260
-
261
- - Animation, render config (EEVEE/Cycles 변경)은 first-class tool 아님. Python exec로만 가능.
262
- - Hyper3D Rodin 무료 tier는 rate limit. 정확한 quota 미검증.
263
- - Telemetry on by default in v1.5.x — env var로 off 가능 (정확한 변수명 미검증, 사용자 환경 차이).
264
- - Windows / Linux도 지원하지만 본 walk-through는 macOS 기준. Other OS 사용자 발화 시 [Mehul Gupta's Medium](https://medium.com/data-science-in-your-pocket/how-to-install-blender-mcp-in-windows-for-claude-ai-347233f83155) 안내.
265
-
266
- ## 9. 사용 컨텍스트
267
-
268
- 이 agent는 **production phase에서만 활성**. prototype 단계에선 호출 금지 (overkill). master가 PRODUCTION_TRANSITION 또는 사용자 명시 요청 시에만 spawn.
269
-
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/install-skills.ts","../src/core/agent-detect.ts"],"sourcesContent":["import * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport {\n readFileSync,\n readdirSync,\n writeFileSync,\n existsSync,\n mkdirSync,\n} from 'node:fs';\nimport { join, dirname, relative } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { detectInstalledAgents } from '../core/agent-detect.js';\n\nexport type SkillTarget = 'claude-code' | 'codex' | 'opencode';\n\nexport interface InstallSkillsOptions {\n dir?: string;\n agents?: SkillTarget[];\n force?: boolean;\n}\n\ninterface InstallPlan {\n target: SkillTarget;\n destDir: string;\n layout: 'folder' | 'flat';\n}\n\nfunction findPackageRoot(): string | null {\n let cur = dirname(fileURLToPath(import.meta.url));\n for (let i = 0; i < 8; i++) {\n if (existsSync(join(cur, 'skills'))) return cur;\n const parent = dirname(cur);\n if (parent === cur) break;\n cur = parent;\n }\n return null;\n}\n\nfunction listShippedSkills(packageRoot: string): string[] {\n const skillsDir = join(packageRoot, 'skills');\n if (!existsSync(skillsDir)) return [];\n return readdirSync(skillsDir)\n .filter((name) => existsSync(join(skillsDir, name, 'SKILL.md')))\n .sort();\n}\n\n/**\n * Canonical agent definitions live at `agents/<name>.md` (markdown with YAML\n * frontmatter). Channel-specific files (.claude/agents/*.md, .codex/agents/*.toml)\n * are generated artifacts — never the source of truth.\n *\n * The package ships only `agents/` and the generator emits per-channel files\n * into the user's project on `omd install-skills`.\n */\nfunction listCanonicalAgents(packageRoot: string): string[] {\n const dir = join(packageRoot, 'agents');\n if (!existsSync(dir)) return [];\n return readdirSync(dir)\n .filter((name) => name.startsWith('omd-') && name.endsWith('.md'))\n .sort();\n}\n\ninterface ParsedAgent {\n name: string;\n description: string;\n tools: string[];\n model: string;\n body: string;\n}\n\n/** Parse `agents/<name>.md` YAML frontmatter + body into structured form. */\nfunction parseCanonicalAgent(packageRoot: string, filename: string): ParsedAgent {\n const src = readFileSync(join(packageRoot, 'agents', filename), 'utf8');\n const match = /^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/.exec(src);\n if (!match) {\n throw new Error(`agents/${filename}: missing YAML frontmatter`);\n }\n const fm = match[1];\n const body = match[2];\n const grab = (key: string): string => {\n const re = new RegExp(`^${key}:\\\\s*(.+)$`, 'm');\n const m = re.exec(fm);\n return m ? m[1].trim().replace(/^[\"']|[\"']$/g, '') : '';\n };\n return {\n name: grab('name') || filename.replace(/\\.md$/, ''),\n description: grab('description'),\n tools: grab('tools')\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean),\n model: grab('model') || 'sonnet',\n body,\n };\n}\n\n/** Map Claude tool names to Codex tool names (best-effort). */\nfunction claudeToolsToCodex(tools: string[]): string[] {\n const m: Record<string, string> = {\n Read: 'read_file',\n Write: 'write_file',\n Edit: 'edit_file',\n Bash: 'shell',\n Glob: 'search',\n Grep: 'search',\n WebFetch: 'web_fetch',\n WebSearch: 'search',\n Agent: 'spawn_agent',\n TaskCreate: 'task',\n TaskUpdate: 'task',\n TaskList: 'task',\n };\n const out = new Set<string>();\n for (const t of tools) out.add(m[t] ?? t.toLowerCase());\n return [...out].sort();\n}\n\n/** Map Claude model alias to Codex/OpenAI model id (best-effort). */\nfunction claudeModelToCodex(model: string): string {\n const m: Record<string, string> = {\n haiku: 'gpt-4.1-mini',\n sonnet: 'gpt-4.1',\n opus: 'gpt-4.1',\n };\n return m[model.toLowerCase()] ?? 'gpt-4.1';\n}\n\n/** Render a canonical agent as a Claude Code subagent file.\n * IMPORTANT: Claude Code's subagent parser requires YAML frontmatter (`---`)\n * as the FIRST line of the file. Any preceding content (HTML comments, blank\n * lines) breaks discovery. So we encode the managed-by-omd marker as a\n * custom frontmatter field (`omd_managed: true`) instead of an HTML comment.\n */\nfunction renderClaudeAgent(a: ParsedAgent): string {\n const fm = [\n '---',\n `name: ${a.name}`,\n `description: ${a.description}`,\n `tools: ${a.tools.join(', ')}`,\n `model: ${a.model}`,\n `omd_managed: true`,\n '---',\n '',\n ].join('\\n');\n return fm + a.body;\n}\n\n/** Render a canonical agent as a Codex TOML file (declarative pointer). */\nfunction renderCodexAgent(a: ParsedAgent): string {\n const tools = claudeToolsToCodex(a.tools);\n const model = claudeModelToCodex(a.model);\n const desc = a.description.replace(/\"/g, '\\\\\"');\n return [\n `[agent]`,\n `name = \"${a.name}\"`,\n `description = \"${desc}\"`,\n `model = \"${model}\"`,\n `max_threads = 1`,\n `allowed_tools = [${tools.map((t) => `\"${t}\"`).join(', ')}]`,\n '',\n `instructions = \"\"\"`,\n `Source of truth: agents/${a.name}.md (canonical). The full role spec is`,\n `mirrored to .claude/agents/${a.name}.md when installed for Claude Code.`,\n `Follow that spec verbatim regardless of channel.`,\n '',\n `Codex notes:`,\n `- Spawn sub-agents via spawn_agent with names matching .codex/agents/<name>.toml`,\n `- Use shell to invoke CLI helpers (omd init prepare, omd remember, git apply, npx axe-core, npx lighthouse)`,\n `- All artifacts go inside .omd/runs/run-<latest>/ (or skills/omd-lab-02-design-harness/runs/<lab-version>-...)`,\n `\"\"\"`,\n '',\n ].join('\\n');\n}\n\nfunction planForTarget(projectRoot: string, target: SkillTarget): InstallPlan {\n switch (target) {\n case 'claude-code':\n return {\n target,\n destDir: join(projectRoot, '.claude', 'skills'),\n layout: 'folder',\n };\n case 'codex':\n return {\n target,\n destDir: join(projectRoot, '.codex', 'skills'),\n layout: 'folder',\n };\n case 'opencode':\n return {\n target,\n destDir: join(projectRoot, '.opencode', 'agents'),\n layout: 'flat',\n };\n }\n}\n\nconst MANAGED_HEADER =\n '<!-- omd:installed-skill — managed by `omd install-skills`. Do not edit; rerun the command to refresh. -->';\n\ninterface InstallResult {\n target: SkillTarget;\n skill: string;\n destPath: string;\n status: 'created' | 'updated' | 'unchanged' | 'skipped-drift';\n}\n\nfunction installOne(\n packageRoot: string,\n plan: InstallPlan,\n skill: string,\n force: boolean\n): InstallResult {\n const src = readFileSync(\n join(packageRoot, 'skills', skill, 'SKILL.md'),\n 'utf8'\n );\n const managed = MANAGED_HEADER + '\\n\\n' + src;\n const destPath =\n plan.layout === 'folder'\n ? join(plan.destDir, skill, 'SKILL.md')\n : join(plan.destDir, skill + '.md');\n\n const exists = existsSync(destPath);\n const existing = exists ? readFileSync(destPath, 'utf8') : '';\n\n if (exists && existing === managed) {\n return { target: plan.target, skill, destPath, status: 'unchanged' };\n }\n\n if (exists && !existing.startsWith(MANAGED_HEADER) && !force) {\n return { target: plan.target, skill, destPath, status: 'skipped-drift' };\n }\n\n mkdirSync(dirname(destPath), { recursive: true });\n writeFileSync(destPath, managed, 'utf8');\n return {\n target: plan.target,\n skill,\n destPath,\n status: exists ? 'updated' : 'created',\n };\n}\n\n/** Install a hook script from package's .claude/hooks/ to project. */\nfunction installHookFile(\n packageRoot: string,\n projectRoot: string,\n filename: string,\n force: boolean\n): InstallResult {\n const target: SkillTarget = 'claude-code';\n const skillLabel = `hook:${filename}`;\n const srcPath = join(packageRoot, '.claude', 'hooks', filename);\n const destPath = join(projectRoot, '.claude', 'hooks', filename);\n\n if (!existsSync(srcPath)) {\n return { target, skill: skillLabel, destPath, status: 'skipped-drift' };\n }\n const src = readFileSync(srcPath, 'utf8');\n const exists = existsSync(destPath);\n const existing = exists ? readFileSync(destPath, 'utf8') : '';\n if (exists && existing === src) {\n return { target, skill: skillLabel, destPath, status: 'unchanged' };\n }\n if (exists && !force) {\n return { target, skill: skillLabel, destPath, status: 'skipped-drift' };\n }\n mkdirSync(dirname(destPath), { recursive: true });\n writeFileSync(destPath, src);\n return { target, skill: skillLabel, destPath, status: exists ? 'updated' : 'created' };\n}\n\n/**\n * Install / merge .claude/settings.json. We MERGE hooks (don't clobber user\n * customizations) by checking if the omd-managed `_doc` field is present.\n * Without --force, if a user-edited settings.json exists (no _doc field),\n * we skip with `skipped-drift`.\n */\nfunction installSettingsJson(\n packageRoot: string,\n projectRoot: string,\n force: boolean\n): InstallResult {\n const target: SkillTarget = 'claude-code';\n const skillLabel = 'settings:.claude/settings.json';\n const srcPath = join(packageRoot, '.claude', 'settings.json');\n const destPath = join(projectRoot, '.claude', 'settings.json');\n if (!existsSync(srcPath)) {\n return { target, skill: skillLabel, destPath, status: 'skipped-drift' };\n }\n const src = readFileSync(srcPath, 'utf8');\n const exists = existsSync(destPath);\n const existing = exists ? readFileSync(destPath, 'utf8') : '';\n if (exists && existing === src) {\n return { target, skill: skillLabel, destPath, status: 'unchanged' };\n }\n if (exists && !force) {\n // Check if it's the omd-managed version\n try {\n const parsed = JSON.parse(existing);\n if (typeof parsed._doc === 'string' && parsed._doc.includes('OmD')) {\n // managed — overwrite\n } else {\n return { target, skill: skillLabel, destPath, status: 'skipped-drift' };\n }\n } catch {\n return { target, skill: skillLabel, destPath, status: 'skipped-drift' };\n }\n }\n mkdirSync(dirname(destPath), { recursive: true });\n writeFileSync(destPath, src);\n return { target, skill: skillLabel, destPath, status: exists ? 'updated' : 'created' };\n}\n\n/**\n * Copy a read-only data asset (reference-fingerprints.json, vocabulary.json, …)\n * from the package's `data/` into the project's `.claude/data/` or `.codex/data/`.\n * The skill reads these at runtime — they replace the deprecated `omd init recommend` CLI.\n */\nfunction installDataFile(\n packageRoot: string,\n projectRoot: string,\n channelDir: string,\n dataFilename: string,\n force: boolean\n): InstallResult {\n const target: SkillTarget = channelDir === '.claude' ? 'claude-code' : 'codex';\n const skillLabel = `data:${dataFilename}`;\n\n const srcPath = join(packageRoot, 'data', dataFilename);\n const destPath = join(projectRoot, channelDir, 'data', dataFilename);\n\n if (!existsSync(srcPath)) {\n return { target, skill: skillLabel, destPath, status: 'skipped-drift' };\n }\n\n const src = readFileSync(srcPath, 'utf8');\n const exists = existsSync(destPath);\n const existing = exists ? readFileSync(destPath, 'utf8') : '';\n\n // Data files are pure copies — no managed header (would corrupt JSON).\n if (exists && existing === src) {\n return { target, skill: skillLabel, destPath, status: 'unchanged' };\n }\n if (exists && !force) {\n // Honor user customization unless --force\n return { target, skill: skillLabel, destPath, status: 'skipped-drift' };\n }\n\n mkdirSync(dirname(destPath), { recursive: true });\n writeFileSync(destPath, src, 'utf8');\n return {\n target,\n skill: skillLabel,\n destPath,\n status: exists ? 'updated' : 'created',\n };\n}\n\n/**\n * Generate a per-channel agent file from the canonical `agents/<name>.md`.\n *\n * Channel = 'claude' → emits `.claude/agents/<name>.md` (markdown w/ frontmatter)\n * Channel = 'codex' → emits `.codex/agents/<name>.toml` (TOML pointer)\n */\nfunction installAgentFile(\n packageRoot: string,\n projectRoot: string,\n channel: 'claude' | 'codex',\n filename: string,\n force: boolean\n): InstallResult {\n const target: SkillTarget = channel === 'claude' ? 'claude-code' : 'codex';\n const skillLabel = `agent:${filename}`;\n\n const parsed = parseCanonicalAgent(packageRoot, filename);\n const rendered =\n channel === 'claude' ? renderClaudeAgent(parsed) : renderCodexAgent(parsed);\n\n const destFilename =\n channel === 'claude' ? filename : filename.replace(/\\.md$/, '.toml');\n const destPath = join(\n projectRoot,\n channel === 'claude' ? '.claude' : '.codex',\n 'agents',\n destFilename\n );\n\n // For Claude Code: managed marker is encoded as `omd_managed: true` INSIDE the\n // frontmatter (rendered above) — no HTML comment can precede `---` or the\n // subagent loader rejects the file.\n // For Codex: TOML allows leading comments, so `# omd:installed-agent ...` is fine.\n const managed =\n channel === 'claude'\n ? rendered\n : '# omd:installed-agent — generated from agents/' +\n filename +\n ' by `omd install-skills`. Do not edit; rerun the command to refresh.\\n\\n' +\n rendered;\n\n const exists = existsSync(destPath);\n const existing = exists ? readFileSync(destPath, 'utf8') : '';\n\n if (exists && existing === managed) {\n return { target, skill: skillLabel, destPath, status: 'unchanged' };\n }\n\n // Drift detection sentinels:\n // Claude — look for `omd_managed: true` line inside frontmatter\n // Codex — look for `# omd:installed-agent` comment\n const isManaged =\n channel === 'claude'\n ? /\\nomd_managed:\\s*true\\b/.test(existing)\n : existing.startsWith('# omd:installed-agent');\n\n if (exists && !isManaged && !force) {\n return { target, skill: skillLabel, destPath, status: 'skipped-drift' };\n }\n\n mkdirSync(dirname(destPath), { recursive: true });\n writeFileSync(destPath, managed, 'utf8');\n return {\n target,\n skill: skillLabel,\n destPath,\n status: exists ? 'updated' : 'created',\n };\n}\n\nconst STATUS_LABEL: Record<InstallResult['status'], string> = {\n created: pc.green('created'),\n updated: pc.cyan('updated'),\n unchanged: pc.dim('unchanged'),\n 'skipped-drift': pc.yellow('skipped'),\n};\n\nfunction autoDetectTargets(projectRoot: string): SkillTarget[] {\n const presence = detectInstalledAgents(projectRoot);\n const targets: SkillTarget[] = [];\n if (presence.claudeCode) targets.push('claude-code');\n if (presence.codex) targets.push('codex');\n if (presence.opencode) targets.push('opencode');\n // Cursor uses .mdc rules, not skills — installed via `omd sync`.\n if (targets.length === 0) {\n // Fallback: install for all three so user gets coverage even without\n // explicit signal. Idempotent so cost is low.\n return ['claude-code', 'codex', 'opencode'];\n }\n return targets;\n}\n\nexport async function runInstallSkills(\n opts: InstallSkillsOptions = {}\n): Promise<number> {\n const projectRoot = opts.dir ?? process.cwd();\n const packageRoot = findPackageRoot();\n if (!packageRoot) {\n console.error(pc.red('omd install-skills: package data not found'));\n return 1;\n }\n\n const skills = listShippedSkills(packageRoot);\n if (skills.length === 0) {\n console.error(pc.red('omd install-skills: no skills found in package'));\n return 1;\n }\n\n const targets = opts.agents ?? autoDetectTargets(projectRoot);\n const plans = targets.map((t) => planForTarget(projectRoot, t));\n const force = opts.force ?? false;\n\n p.intro(\n pc.bold('omd install-skills') +\n pc.dim(` (${relative(process.cwd(), projectRoot) || '.'})`)\n );\n\n p.log.message(\n pc.bold('Targets: ') +\n targets.map((t) => pc.cyan(t)).join(', ')\n );\n p.log.message(\n pc.bold('Skills: ') + skills.map((s) => pc.cyan(s)).join(', ')\n );\n\n const results: InstallResult[] = [];\n for (const plan of plans) {\n for (const skill of skills) {\n results.push(installOne(packageRoot, plan, skill, force));\n }\n }\n\n // Generate per-channel sub-agent definitions from the canonical `agents/`.\n // This is the v2 portable source-of-truth pattern (oh-my-agent style).\n const canonicalAgents = listCanonicalAgents(packageRoot);\n for (const target of targets) {\n if (target === 'claude-code') {\n for (const filename of canonicalAgents) {\n results.push(installAgentFile(packageRoot, projectRoot, 'claude', filename, force));\n }\n } else if (target === 'codex') {\n for (const filename of canonicalAgents) {\n results.push(installAgentFile(packageRoot, projectRoot, 'codex', filename, force));\n }\n }\n // OpenCode currently has no agent-definition channel — skills only.\n }\n\n // Ship the read-only data assets (reference fingerprints, controlled vocab,\n // human-readable tag matrix, opt-out corpus) into the project so skills + hooks\n // can run entirely on the host CLI's own model — no external API keys.\n const dataFiles = [\n 'reference-fingerprints.json',\n 'reference-tags.md',\n 'vocabulary.json',\n 'synonyms.json',\n 'opt-out-corpus.json',\n ];\n for (const target of targets) {\n if (target === 'claude-code') {\n for (const dataFile of dataFiles) {\n results.push(installDataFile(packageRoot, projectRoot, '.claude', dataFile, force));\n }\n } else if (target === 'codex') {\n for (const dataFile of dataFiles) {\n results.push(installDataFile(packageRoot, projectRoot, '.codex', dataFile, force));\n }\n }\n }\n\n // Install hooks (Claude Code only — Codex / OpenCode have separate hook systems)\n if (targets.includes('claude-code')) {\n for (const hookFile of [\n 'skill-activation.cjs',\n 'session-state-loader.cjs',\n 'post-edit-watch.cjs',\n 'session-end-foldin.cjs',\n ]) {\n results.push(installHookFile(packageRoot, projectRoot, hookFile, force));\n }\n // settings.json (with merge, never clobber user)\n results.push(installSettingsJson(packageRoot, projectRoot, force));\n }\n\n p.log.message(pc.bold('\\nResults:'));\n for (const r of results) {\n const rel = relative(projectRoot, r.destPath);\n p.log.message(\n ` ${STATUS_LABEL[r.status]} ${pc.dim(r.target.padEnd(12))} ${rel}`\n );\n }\n\n const driftCount = results.filter((r) => r.status === 'skipped-drift').length;\n const writtenCount = results.filter(\n (r) => r.status === 'created' || r.status === 'updated'\n ).length;\n\n if (driftCount > 0) {\n p.outro(\n pc.yellow(\n `${writtenCount} written, ${driftCount} skipped (existing files lack the omd marker — rerun with --force to overwrite).`\n )\n );\n return 0;\n }\n\n // Friendly next-step nudge after successful install\n const nextSteps = [\n `${pc.bold('Open Claude Code (or Codex). Just say what you want:')}`,\n '',\n ` ${pc.dim('\"토스 스타일 가족 식단 공유 앱 메인 화면 디자인해줘\"')}`,\n ` ${pc.dim('\"Linear-clone B2B SaaS dashboard 만들고 싶어\"')}`,\n ` ${pc.dim('\"이 카드 좀 더 세련되게\"')} ${pc.dim('# 작업 중 자연어 — 자동 라우팅')}`,\n '',\n `${pc.bold('Claude가 description 매칭으로 자동 라우팅')} ${pc.dim('— 슬래시 명령 안 쳐도 됨. Hook은 DESIGN.md 부재 시 omd:init 안내만.')}`,\n '',\n `${pc.dim('Power user shortcut: ')}${pc.cyan('/omd-harness <task>')} ${pc.dim('— 즉시 진입.')}`,\n '',\n `${pc.yellow('⚠ Already-running Claude Code session?')} ${pc.dim('Run `/agents` inside the session to reload — or quit (Cmd+Q on macOS) and relaunch. Without reload, hooks/agents do not load.')}`,\n ].join('\\n');\n p.note(nextSteps, 'Next');\n\n p.outro(\n pc.green(\n `Done. 6 skills · 11 sub-agents · 4 hooks installed (${writtenCount} files).`,\n ),\n );\n return 0;\n}\n\n","import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport type AgentId = 'claude-code' | 'codex' | 'opencode' | 'cursor' | 'unknown';\n\nexport function detectCallingAgent(): AgentId {\n const env = process.env;\n\n if (env.CLAUDECODE === '1' || env.CLAUDE_CODE === '1' || env.CLAUDE_CODE_TASK_ID) {\n return 'claude-code';\n }\n if (env.CODEX_SESSION_ID || env.CODEX || env.OPENAI_CODEX) {\n return 'codex';\n }\n if (env.OPENCODE || env.OPENCODE_SESSION) {\n return 'opencode';\n }\n if (env.CURSOR_SESSION_ID || env.CURSOR_AGENT) {\n return 'cursor';\n }\n\n return 'unknown';\n}\n\nexport interface AgentPresence {\n claudeCode: boolean;\n codex: boolean;\n opencode: boolean;\n cursor: boolean;\n}\n\nexport function detectInstalledAgents(projectRoot: string): AgentPresence {\n return {\n claudeCode:\n existsSync(join(projectRoot, '.claude')) ||\n existsSync(join(projectRoot, 'CLAUDE.md')),\n codex:\n existsSync(join(projectRoot, '.codex')) ||\n existsSync(join(projectRoot, 'AGENTS.md')) ||\n existsSync(join(projectRoot, 'AGENTS.override.md')),\n opencode:\n existsSync(join(projectRoot, '.opencode')) ||\n existsSync(join(projectRoot, 'opencode.json')) ||\n existsSync(join(projectRoot, 'opencode.jsonc')),\n cursor:\n existsSync(join(projectRoot, '.cursor')) ||\n existsSync(join(projectRoot, '.cursorrules')),\n };\n}\n"],"mappings":"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","names":["existsSync","join","existsSync","join"]}