oh-my-design-cli 1.8.6 → 1.9.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 (275) hide show
  1. package/.claude/hooks/lib/preferences-parser.cjs +1 -0
  2. package/.claude/hooks/lib/preferences-writer.cjs +1 -0
  3. package/.claude/hooks/post-edit-watch.cjs +1 -0
  4. package/.claude/hooks/session-end-foldin.cjs +1 -0
  5. package/.claude/hooks/session-state-loader.cjs +1 -0
  6. package/.claude/hooks/skill-activation.cjs +1 -0
  7. package/.claude/settings.json +10 -1
  8. package/.github/assets/logo-bg.png +0 -0
  9. package/AGENTS.md +20 -1
  10. package/CHANGELOG.md +482 -0
  11. package/MIGRATION.md +103 -0
  12. package/README.ja.md +56 -19
  13. package/README.ko.md +47 -30
  14. package/README.md +48 -30
  15. package/README.zh-TW.md +59 -22
  16. package/agents/AGENT.md +8 -7
  17. package/agents/omd-codex-image.md +1 -1
  18. package/agents/omd-critic.md +6 -7
  19. package/agents/omd-designer-review.md +1 -1
  20. package/agents/omd-final-qa.md +1 -1
  21. package/agents/omd-humanizer.md +38 -0
  22. package/agents/omd-kr-writer.md +3 -4
  23. package/agents/omd-locale-adapter.md +12 -16
  24. package/agents/omd-master.md +24 -19
  25. package/agents/omd-microcopy.md +1 -1
  26. package/agents/omd-orchestrator.md +7 -8
  27. package/agents/omd-slop-auditor.md +31 -0
  28. package/agents/omd-ux-researcher.md +1 -1
  29. package/data/reference-fingerprints.json +2761 -85
  30. package/dist/bin/oh-my-design.js +16 -8
  31. package/dist/bin/oh-my-design.js.map +1 -1
  32. package/dist/chunk-UJIHCEYF.js +99 -0
  33. package/dist/chunk-UJIHCEYF.js.map +1 -0
  34. package/dist/doctor-LDWSFM3I.js +763 -0
  35. package/dist/doctor-LDWSFM3I.js.map +1 -0
  36. package/dist/install-skills-ZZFNJ2II.js +1120 -0
  37. package/dist/install-skills-ZZFNJ2II.js.map +1 -0
  38. package/docs/CLI_QUICKSTART.md +157 -0
  39. package/package.json +25 -4
  40. package/scripts/postinstall.cjs +5 -4
  41. package/skills/claude-design/SKILL.md +38 -14
  42. package/skills/claude-design/references/claude-design-flow.md +11 -11
  43. package/skills/claude-design/references/codebase-analysis.md +5 -4
  44. package/skills/omd-final-qa/SKILL.md +1 -1
  45. package/skills/omd-harness/SKILL.md +51 -50
  46. package/skills/omd-humanize/SKILL.md +116 -0
  47. package/skills/omd-humanize/agents/openai.yaml +4 -0
  48. package/skills/omd-humanize/references/locale-playbooks.md +102 -0
  49. package/skills/omd-humanize/references/sources.md +11 -0
  50. package/skills/omd-init/SKILL.md +18 -12
  51. package/skills/omd-locale-adapter/SKILL.md +58 -91
  52. package/skills/omd-orchestrator/SKILL.md +11 -5
  53. package/skills/omd-reference-capture/SKILL.md +80 -26
  54. package/skills/omd-reference-capture/scripts/PLAYWRIGHT-LICENSE.txt +202 -0
  55. package/skills/omd-reference-capture/scripts/PLAYWRIGHT-NOTICE.txt +5 -0
  56. package/skills/omd-reference-capture/scripts/THIRD_PARTY_NOTICES.md +3 -0
  57. package/skills/omd-reference-capture/scripts/capture-reference-evidence.mjs +159906 -0
  58. package/skills/omd-slop-audit/SKILL.md +110 -0
  59. package/skills/omd-slop-audit/agents/openai.yaml +4 -0
  60. package/skills/omd-slop-audit/references/pattern-catalog.md +96 -0
  61. package/skills/omd-slop-audit/references/sources.md +24 -0
  62. package/web/references/104/DESIGN.md +354 -0
  63. package/web/references/11st/DESIGN.md +197 -316
  64. package/web/references/29cm/DESIGN.md +297 -393
  65. package/web/references/42dot/DESIGN.md +390 -0
  66. package/web/references/8percent/DESIGN.md +438 -0
  67. package/web/references/ably/DESIGN.md +267 -572
  68. package/web/references/acer/DESIGN.md +329 -0
  69. package/web/references/airbnb/DESIGN.md +219 -557
  70. package/web/references/airbridge/DESIGN.md +451 -0
  71. package/web/references/alipay/DESIGN.md +179 -420
  72. package/web/references/apple/DESIGN.md +224 -498
  73. package/web/references/asleep/DESIGN.md +402 -0
  74. package/web/references/au/DESIGN.md +334 -0
  75. package/web/references/autopedia/DESIGN.md +382 -0
  76. package/web/references/aws-cloudscape/DESIGN.md +241 -0
  77. package/web/references/baemin/DESIGN.md +332 -491
  78. package/web/references/banksalad/DESIGN.md +269 -180
  79. package/web/references/barogo/DESIGN.md +416 -0
  80. package/web/references/beusable/DESIGN.md +464 -0
  81. package/web/references/bigin/DESIGN.md +454 -0
  82. package/web/references/bilibili/DESIGN.md +206 -374
  83. package/web/references/bmw/DESIGN.md +162 -276
  84. package/web/references/brandi/DESIGN.md +184 -325
  85. package/web/references/buzzvil/DESIGN.md +457 -0
  86. package/web/references/cafe24/DESIGN.md +472 -0
  87. package/web/references/catchtable/DESIGN.md +219 -264
  88. package/web/references/cgv/DESIGN.md +317 -0
  89. package/web/references/channeltalk/DESIGN.md +210 -336
  90. package/web/references/china-airlines/DESIGN.md +291 -0
  91. package/web/references/cjonstyle/DESIGN.md +453 -0
  92. package/web/references/class101/DESIGN.md +168 -387
  93. package/web/references/classum/DESIGN.md +228 -203
  94. package/web/references/claude/DESIGN.md +242 -479
  95. package/web/references/clay/DESIGN.md +179 -377
  96. package/web/references/clickhouse/DESIGN.md +254 -343
  97. package/web/references/codeit/DESIGN.md +470 -0
  98. package/web/references/cohere/DESIGN.md +214 -324
  99. package/web/references/coinone/DESIGN.md +199 -179
  100. package/web/references/corca/DESIGN.md +414 -0
  101. package/web/references/coupang/DESIGN.md +205 -475
  102. package/web/references/cursor/DESIGN.md +240 -381
  103. package/web/references/dabang/DESIGN.md +248 -213
  104. package/web/references/dable/DESIGN.md +431 -0
  105. package/web/references/datarize/DESIGN.md +338 -0
  106. package/web/references/dealicious/DESIGN.md +402 -0
  107. package/web/references/drdiary/DESIGN.md +404 -0
  108. package/web/references/elastic/DESIGN.md +238 -0
  109. package/web/references/elevenlabs/DESIGN.md +183 -321
  110. package/web/references/elice/DESIGN.md +445 -0
  111. package/web/references/eslite/DESIGN.md +257 -0
  112. package/web/references/evaair/DESIGN.md +338 -0
  113. package/web/references/expo/DESIGN.md +238 -331
  114. package/web/references/familymart-tw/DESIGN.md +254 -0
  115. package/web/references/ferrari/DESIGN.md +160 -377
  116. package/web/references/figma/DESIGN.md +197 -451
  117. package/web/references/fitpet/DESIGN.md +445 -0
  118. package/web/references/flex/DESIGN.md +170 -253
  119. package/web/references/framer/DESIGN.md +197 -340
  120. package/web/references/freee/DESIGN.md +211 -533
  121. package/web/references/friendliai/DESIGN.md +431 -0
  122. package/web/references/frip/DESIGN.md +440 -0
  123. package/web/references/furiosaai/DESIGN.md +450 -0
  124. package/web/references/gangnamunni/DESIGN.md +154 -591
  125. package/web/references/gaudiolab/DESIGN.md +414 -0
  126. package/web/references/google/DESIGN.md +290 -398
  127. package/web/references/goorm/DESIGN.md +470 -0
  128. package/web/references/greencar/DESIGN.md +420 -0
  129. package/web/references/hackle/DESIGN.md +472 -0
  130. package/web/references/hashicorp/DESIGN.md +273 -318
  131. package/web/references/heydealer/DESIGN.md +429 -0
  132. package/web/references/humanscape/DESIGN.md +433 -0
  133. package/web/references/hwahae/DESIGN.md +453 -0
  134. package/web/references/hyundai/DESIGN.md +158 -368
  135. package/web/references/hyundaicard/DESIGN.md +171 -121
  136. package/web/references/ibm/DESIGN.md +227 -378
  137. package/web/references/idus/DESIGN.md +450 -0
  138. package/web/references/igaworks/DESIGN.md +437 -0
  139. package/web/references/inflearn/DESIGN.md +221 -366
  140. package/web/references/intuit/DESIGN.md +244 -0
  141. package/web/references/jandi/DESIGN.md +191 -291
  142. package/web/references/jobplanet/DESIGN.md +415 -0
  143. package/web/references/kakao/DESIGN.md +287 -475
  144. package/web/references/kakaobank/DESIGN.md +220 -521
  145. package/web/references/kakaogames/DESIGN.md +220 -0
  146. package/web/references/kakaopay/DESIGN.md +207 -526
  147. package/web/references/karrot/DESIGN.md +227 -251
  148. package/web/references/kb-kookmin/DESIGN.md +308 -0
  149. package/web/references/kbank/DESIGN.md +220 -175
  150. package/web/references/kcd/DESIGN.md +432 -0
  151. package/web/references/kmong/DESIGN.md +281 -356
  152. package/web/references/krds/DESIGN.md +245 -19
  153. package/web/references/kream/DESIGN.md +224 -359
  154. package/web/references/kurly/DESIGN.md +211 -533
  155. package/web/references/kyobobook/DESIGN.md +445 -0
  156. package/web/references/lablup/DESIGN.md +474 -0
  157. package/web/references/lamborghini/DESIGN.md +198 -360
  158. package/web/references/lemonbase/DESIGN.md +452 -0
  159. package/web/references/lguplus/DESIGN.md +259 -0
  160. package/web/references/likelion/DESIGN.md +283 -0
  161. package/web/references/line/DESIGN.md +396 -355
  162. package/web/references/linear.app/DESIGN.md +209 -562
  163. package/web/references/lotteon/DESIGN.md +386 -0
  164. package/web/references/lovable/DESIGN.md +255 -349
  165. package/web/references/makinarocks/DESIGN.md +242 -0
  166. package/web/references/maum-ai/DESIGN.md +423 -0
  167. package/web/references/medibloc/DESIGN.md +425 -0
  168. package/web/references/megabox/DESIGN.md +232 -0
  169. package/web/references/mercari/DESIGN.md +217 -434
  170. package/web/references/microsoft/DESIGN.md +234 -388
  171. package/web/references/mildang/DESIGN.md +411 -0
  172. package/web/references/millie/DESIGN.md +183 -504
  173. package/web/references/minimax/DESIGN.md +264 -322
  174. package/web/references/miricanvas/DESIGN.md +182 -355
  175. package/web/references/miro/DESIGN.md +234 -232
  176. package/web/references/mistral.ai/DESIGN.md +231 -314
  177. package/web/references/mixi/DESIGN.md +234 -0
  178. package/web/references/moin/DESIGN.md +445 -0
  179. package/web/references/mongodb/DESIGN.md +219 -316
  180. package/web/references/moreh/DESIGN.md +437 -0
  181. package/web/references/musinsa/DESIGN.md +184 -510
  182. package/web/references/mynavi/DESIGN.md +242 -0
  183. package/web/references/myrealtrip/DESIGN.md +169 -406
  184. package/web/references/naver/DESIGN.md +328 -499
  185. package/web/references/naverwebtoon/DESIGN.md +172 -395
  186. package/web/references/neosapience/DESIGN.md +441 -0
  187. package/web/references/nhn/DESIGN.md +169 -346
  188. package/web/references/nhncloud/DESIGN.md +185 -123
  189. package/web/references/nota/DESIGN.md +451 -0
  190. package/web/references/notion/DESIGN.md +271 -475
  191. package/web/references/nrise/DESIGN.md +417 -0
  192. package/web/references/ohouse/DESIGN.md +210 -549
  193. package/web/references/oliveyoung/DESIGN.md +217 -326
  194. package/web/references/ollama/DESIGN.md +241 -308
  195. package/web/references/onestore/DESIGN.md +248 -0
  196. package/web/references/palantir/DESIGN.md +256 -0
  197. package/web/references/panasonic/DESIGN.md +276 -0
  198. package/web/references/patternfly/DESIGN.md +259 -0
  199. package/web/references/payhere/DESIGN.md +438 -0
  200. package/web/references/pega/DESIGN.md +262 -0
  201. package/web/references/peoplefund/DESIGN.md +431 -0
  202. package/web/references/petfriends/DESIGN.md +428 -0
  203. package/web/references/pinkfong/DESIGN.md +199 -367
  204. package/web/references/pinterest/DESIGN.md +258 -308
  205. package/web/references/portone/DESIGN.md +446 -0
  206. package/web/references/poya/DESIGN.md +286 -0
  207. package/web/references/pozalabs/DESIGN.md +438 -0
  208. package/web/references/protopie/DESIGN.md +419 -0
  209. package/web/references/qraft/DESIGN.md +448 -0
  210. package/web/references/queenit/DESIGN.md +432 -0
  211. package/web/references/quotabook/DESIGN.md +449 -0
  212. package/web/references/rebellions/DESIGN.md +449 -0
  213. package/web/references/recruit/DESIGN.md +247 -0
  214. package/web/references/remember/DESIGN.md +202 -396
  215. package/web/references/resend/DESIGN.md +274 -348
  216. package/web/references/returnzero/DESIGN.md +460 -0
  217. package/web/references/sakura-internet/DESIGN.md +269 -0
  218. package/web/references/samsung/DESIGN.md +157 -359
  219. package/web/references/sandoll/DESIGN.md +445 -0
  220. package/web/references/sanity/DESIGN.md +241 -375
  221. package/web/references/saramin/DESIGN.md +465 -0
  222. package/web/references/scatterlab/DESIGN.md +412 -0
  223. package/web/references/selectstar/DESIGN.md +439 -0
  224. package/web/references/servicenow/DESIGN.md +289 -0
  225. package/web/references/shiftee/DESIGN.md +468 -0
  226. package/web/references/shinhanbank/DESIGN.md +161 -341
  227. package/web/references/shinhancard/DESIGN.md +208 -319
  228. package/web/references/sionic/DESIGN.md +454 -0
  229. package/web/references/sktelecom/DESIGN.md +310 -0
  230. package/web/references/socar/DESIGN.md +125 -32
  231. package/web/references/softbank/DESIGN.md +231 -0
  232. package/web/references/solapi/DESIGN.md +483 -0
  233. package/web/references/sony/DESIGN.md +234 -0
  234. package/web/references/soop/DESIGN.md +261 -0
  235. package/web/references/spacex/DESIGN.md +184 -323
  236. package/web/references/spotify/DESIGN.md +253 -394
  237. package/web/references/squeezebits/DESIGN.md +441 -0
  238. package/web/references/stayfolio/DESIGN.md +422 -0
  239. package/web/references/stripe/DESIGN.md +212 -491
  240. package/web/references/supabase/DESIGN.md +244 -316
  241. package/web/references/supertone/DESIGN.md +413 -0
  242. package/web/references/tabling/DESIGN.md +415 -0
  243. package/web/references/taishinbank/DESIGN.md +243 -0
  244. package/web/references/teamlab/DESIGN.md +240 -0
  245. package/web/references/teamsparta/DESIGN.md +472 -0
  246. package/web/references/tellingme/DESIGN.md +392 -0
  247. package/web/references/tesla/DESIGN.md +244 -427
  248. package/web/references/thsr/DESIGN.md +284 -0
  249. package/web/references/thumbtack/DESIGN.md +302 -0
  250. package/web/references/together.ai/DESIGN.md +257 -304
  251. package/web/references/toss/DESIGN.md +251 -593
  252. package/web/references/toss-securities/DESIGN.md +255 -178
  253. package/web/references/tossbank/DESIGN.md +195 -491
  254. package/web/references/toyota/DESIGN.md +238 -0
  255. package/web/references/tving/DESIGN.md +197 -245
  256. package/web/references/typed/DESIGN.md +413 -0
  257. package/web/references/uber/DESIGN.md +256 -333
  258. package/web/references/udn/DESIGN.md +250 -0
  259. package/web/references/upbit/DESIGN.md +145 -256
  260. package/web/references/upstage/DESIGN.md +211 -204
  261. package/web/references/uswds/DESIGN.md +287 -0
  262. package/web/references/vercel/DESIGN.md +236 -440
  263. package/web/references/vuno/DESIGN.md +413 -0
  264. package/web/references/wanted/DESIGN.md +215 -487
  265. package/web/references/weverse/DESIGN.md +437 -0
  266. package/web/references/wise/DESIGN.md +223 -231
  267. package/web/references/wisetracker/DESIGN.md +462 -0
  268. package/web/references/wooribank/DESIGN.md +245 -0
  269. package/web/references/yanolja/DESIGN.md +250 -419
  270. package/web/references/yeogiotte/DESIGN.md +235 -418
  271. package/web/references/zapier/DESIGN.md +256 -377
  272. package/web/references/zendesk/DESIGN.md +288 -0
  273. package/web/references/zigzag/DESIGN.md +200 -621
  274. package/dist/install-skills-7UUDOLG2.js +0 -734
  275. package/dist/install-skills-7UUDOLG2.js.map +0 -1
@@ -1,734 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/cli/install-skills.ts
4
- import * as p from "@clack/prompts";
5
- import pc from "picocolors";
6
- import {
7
- readFileSync,
8
- readdirSync,
9
- writeFileSync,
10
- existsSync as existsSync2,
11
- mkdirSync,
12
- cpSync
13
- } from "fs";
14
- import { join as join2, dirname, relative } from "path";
15
- import { homedir } from "os";
16
- import { createHash } from "crypto";
17
- import { fileURLToPath } from "url";
18
-
19
- // src/core/agent-detect.ts
20
- import { existsSync } from "fs";
21
- import { join } from "path";
22
- function detectInstalledAgents(projectRoot) {
23
- return {
24
- claudeCode: existsSync(join(projectRoot, ".claude")) || existsSync(join(projectRoot, "CLAUDE.md")),
25
- codex: existsSync(join(projectRoot, ".codex")) || existsSync(join(projectRoot, "AGENTS.md")) || existsSync(join(projectRoot, "AGENTS.override.md")),
26
- opencode: existsSync(join(projectRoot, ".opencode")) || existsSync(join(projectRoot, "opencode.json")) || existsSync(join(projectRoot, "opencode.jsonc")),
27
- cursor: existsSync(join(projectRoot, ".cursor")) || existsSync(join(projectRoot, ".cursorrules"))
28
- };
29
- }
30
-
31
- // src/cli/install-skills.ts
32
- function findPackageRoot() {
33
- let cur = dirname(fileURLToPath(import.meta.url));
34
- for (let i = 0; i < 8; i++) {
35
- if (existsSync2(join2(cur, "skills"))) return cur;
36
- const parent = dirname(cur);
37
- if (parent === cur) break;
38
- cur = parent;
39
- }
40
- return null;
41
- }
42
- function listShippedSkills(packageRoot) {
43
- const skillsDir = join2(packageRoot, "skills");
44
- if (!existsSync2(skillsDir)) return [];
45
- return readdirSync(skillsDir).filter((name) => existsSync2(join2(skillsDir, name, "SKILL.md"))).sort();
46
- }
47
- function listCanonicalAgents(packageRoot) {
48
- const dir = join2(packageRoot, "agents");
49
- if (!existsSync2(dir)) return [];
50
- return readdirSync(dir).filter((name) => name.startsWith("omd-") && name.endsWith(".md")).sort();
51
- }
52
- function parseCanonicalAgent(packageRoot, filename) {
53
- const src = readFileSync(join2(packageRoot, "agents", filename), "utf8");
54
- const match = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/.exec(src);
55
- if (!match) {
56
- throw new Error(`agents/${filename}: missing YAML frontmatter`);
57
- }
58
- const fm = match[1];
59
- const body = match[2];
60
- const grab = (key) => {
61
- const re = new RegExp(`^${key}:\\s*(.+)$`, "m");
62
- const m = re.exec(fm);
63
- return m ? m[1].trim().replace(/^["']|["']$/g, "") : "";
64
- };
65
- return {
66
- name: grab("name") || filename.replace(/\.md$/, ""),
67
- description: grab("description"),
68
- tools: grab("tools").split(",").map((t) => t.trim()).filter(Boolean),
69
- model: grab("model") || "sonnet",
70
- body
71
- };
72
- }
73
- function claudeToolsToCodex(tools) {
74
- const m = {
75
- Read: "read_file",
76
- Write: "write_file",
77
- Edit: "edit_file",
78
- Bash: "shell",
79
- Glob: "search",
80
- Grep: "search",
81
- WebFetch: "web_fetch",
82
- WebSearch: "search",
83
- Agent: "spawn_agent",
84
- TaskCreate: "task",
85
- TaskUpdate: "task",
86
- TaskList: "task"
87
- };
88
- const out = /* @__PURE__ */ new Set();
89
- for (const t of tools) out.add(m[t] ?? t.toLowerCase());
90
- return [...out].sort();
91
- }
92
- function claudeModelToCodex(model) {
93
- const m = {
94
- haiku: "gpt-4.1-mini",
95
- sonnet: "gpt-4.1",
96
- opus: "gpt-4.1"
97
- };
98
- return m[model.toLowerCase()] ?? "gpt-4.1";
99
- }
100
- function renderClaudeAgent(a) {
101
- const fm = [
102
- "---",
103
- `name: ${a.name}`,
104
- `description: ${a.description}`,
105
- `tools: ${a.tools.join(", ")}`,
106
- `model: ${a.model}`,
107
- `omd_managed: true`,
108
- "---",
109
- ""
110
- ].join("\n");
111
- return fm + a.body;
112
- }
113
- function renderCodexAgent(a) {
114
- const tools = claudeToolsToCodex(a.tools);
115
- const model = claudeModelToCodex(a.model);
116
- const desc = a.description.replace(/"/g, '\\"');
117
- return [
118
- `[agent]`,
119
- `name = "${a.name}"`,
120
- `description = "${desc}"`,
121
- `model = "${model}"`,
122
- `max_threads = 1`,
123
- `allowed_tools = [${tools.map((t) => `"${t}"`).join(", ")}]`,
124
- "",
125
- `instructions = """`,
126
- `Source of truth: agents/${a.name}.md (canonical). The full role spec is`,
127
- `mirrored to .claude/agents/${a.name}.md when installed for Claude Code.`,
128
- `Follow that spec verbatim regardless of channel.`,
129
- "",
130
- `Codex notes:`,
131
- `- Spawn sub-agents via spawn_agent with names matching .codex/agents/<name>.toml`,
132
- `- Use shell to invoke CLI helpers (omd init prepare, omd remember, git apply, npx axe-core, npx lighthouse)`,
133
- `- All artifacts go inside .omd/runs/run-<latest>/ (or skills/omd-lab-02-design-harness/runs/<lab-version>-...)`,
134
- `"""`,
135
- ""
136
- ].join("\n");
137
- }
138
- function planForTarget(projectRoot, target) {
139
- switch (target) {
140
- case "claude-code":
141
- return {
142
- target,
143
- destDir: join2(projectRoot, ".claude", "skills"),
144
- layout: "folder"
145
- };
146
- case "codex":
147
- return {
148
- target,
149
- destDir: join2(projectRoot, ".agents", "skills"),
150
- layout: "folder"
151
- };
152
- case "opencode":
153
- return {
154
- target,
155
- destDir: join2(projectRoot, ".opencode", "skills"),
156
- layout: "folder"
157
- };
158
- }
159
- }
160
- var CHANNEL_DATA_DIRS = {
161
- "claude-code": ".claude",
162
- codex: ".codex",
163
- opencode: null,
164
- cursor: null
165
- };
166
- function dataDirFor(target, targets) {
167
- if (target === "cursor") {
168
- return targets.includes("claude-code") ? null : ".claude";
169
- }
170
- return CHANNEL_DATA_DIRS[target];
171
- }
172
- var MANAGED_HEADER = "<!-- omd:installed-skill \u2014 managed by `omd install-skills`. Do not edit; rerun the command to refresh. -->";
173
- var MANAGED_MARKER_SUBSTR = "omd:installed-skill";
174
- function withManagedMarker(src) {
175
- const fm = /^(---\r?\n[\s\S]*?\r?\n---\r?\n)([\s\S]*)$/.exec(src);
176
- if (!fm) {
177
- return MANAGED_HEADER + "\n\n" + src;
178
- }
179
- return fm[1] + MANAGED_HEADER + "\n\n" + fm[2];
180
- }
181
- function isManagedSkillFile(content) {
182
- if (!content) return false;
183
- const head = content.split("\n", 30).join("\n");
184
- return head.includes(MANAGED_MARKER_SUBSTR);
185
- }
186
- var IGNORED_SKILL_ENTRIES = /* @__PURE__ */ new Set([".runtime", "__pycache__", ".DS_Store"]);
187
- function parseSkillChannels(skillMd) {
188
- const fm = /^---\n([\s\S]*?)\n---/.exec(skillMd);
189
- if (!fm) return null;
190
- const m = /^x-omd-channels:\s*(.+)$/m.exec(fm[1]);
191
- if (!m) return null;
192
- const valid = ["claude-code", "codex", "opencode"];
193
- const list = m[1].split(/[,\s]+/).map((s) => s.trim()).filter((s) => valid.includes(s));
194
- return list.length > 0 ? list : null;
195
- }
196
- function skillSupportedChannels(packageRoot, skill) {
197
- return parseSkillChannels(readFileSync(join2(packageRoot, "skills", skill, "SKILL.md"), "utf8")) ?? ["claude-code", "codex", "opencode"];
198
- }
199
- function installOne(packageRoot, plan, skill, force) {
200
- const skillDir = join2(packageRoot, "skills", skill);
201
- const src = readFileSync(join2(skillDir, "SKILL.md"), "utf8");
202
- const managed = withManagedMarker(src);
203
- const channels = parseSkillChannels(src);
204
- if (channels && !channels.includes(plan.target)) {
205
- return {
206
- target: plan.target,
207
- skill,
208
- destPath: join2(plan.destDir, skill + ".md"),
209
- status: "skipped-incompat"
210
- };
211
- }
212
- const extras = readdirSync(skillDir).filter(
213
- (n) => n !== "SKILL.md" && !IGNORED_SKILL_ENTRIES.has(n)
214
- );
215
- const isMultiFile = extras.length > 0;
216
- if (plan.layout !== "folder" && isMultiFile) {
217
- return {
218
- target: plan.target,
219
- skill,
220
- destPath: join2(plan.destDir, skill + ".md"),
221
- status: "skipped-incompat"
222
- };
223
- }
224
- const destPath = plan.layout === "folder" ? join2(plan.destDir, skill, "SKILL.md") : join2(plan.destDir, skill + ".md");
225
- const exists = existsSync2(destPath);
226
- const existing = exists ? readFileSync(destPath, "utf8") : "";
227
- if (exists && existing === managed && !isMultiFile) {
228
- return { target: plan.target, skill, destPath, status: "unchanged" };
229
- }
230
- if (exists && !isManagedSkillFile(existing) && !force) {
231
- return { target: plan.target, skill, destPath, status: "skipped-drift" };
232
- }
233
- mkdirSync(dirname(destPath), { recursive: true });
234
- writeFileSync(destPath, managed, "utf8");
235
- if (plan.layout === "folder" && isMultiFile) {
236
- const destSkillDir = join2(plan.destDir, skill);
237
- for (const entry of extras) {
238
- cpSync(join2(skillDir, entry), join2(destSkillDir, entry), {
239
- recursive: true,
240
- filter: (s) => !/(\/__pycache__|\/\.runtime|\.pyc$|\.DS_Store$)/.test(s)
241
- });
242
- }
243
- }
244
- return {
245
- target: plan.target,
246
- skill,
247
- destPath,
248
- status: exists ? "updated" : "created"
249
- };
250
- }
251
- function installHookFile(packageRoot, projectRoot, filename, force) {
252
- const target = "claude-code";
253
- const skillLabel = `hook:${filename}`;
254
- const srcPath = join2(packageRoot, ".claude", "hooks", filename);
255
- const destPath = join2(projectRoot, ".claude", "hooks", filename);
256
- if (!existsSync2(srcPath)) {
257
- return { target, skill: skillLabel, destPath, status: "skipped-drift" };
258
- }
259
- const src = readFileSync(srcPath, "utf8");
260
- const exists = existsSync2(destPath);
261
- const existing = exists ? readFileSync(destPath, "utf8") : "";
262
- if (exists && existing === src) {
263
- return { target, skill: skillLabel, destPath, status: "unchanged" };
264
- }
265
- if (exists && !force) {
266
- return { target, skill: skillLabel, destPath, status: "skipped-drift" };
267
- }
268
- mkdirSync(dirname(destPath), { recursive: true });
269
- writeFileSync(destPath, src);
270
- return { target, skill: skillLabel, destPath, status: exists ? "updated" : "created" };
271
- }
272
- function installSettingsJson(packageRoot, projectRoot, force) {
273
- const target = "claude-code";
274
- const skillLabel = "settings:.claude/settings.json";
275
- const srcPath = join2(packageRoot, ".claude", "settings.json");
276
- const destPath = join2(projectRoot, ".claude", "settings.json");
277
- if (!existsSync2(srcPath)) {
278
- return { target, skill: skillLabel, destPath, status: "skipped-drift" };
279
- }
280
- const src = readFileSync(srcPath, "utf8");
281
- const exists = existsSync2(destPath);
282
- const existing = exists ? readFileSync(destPath, "utf8") : "";
283
- if (exists && existing === src) {
284
- return { target, skill: skillLabel, destPath, status: "unchanged" };
285
- }
286
- if (exists && !force) {
287
- try {
288
- const parsed = JSON.parse(existing);
289
- if (typeof parsed._doc === "string" && parsed._doc.includes("OmD")) {
290
- } else {
291
- return { target, skill: skillLabel, destPath, status: "skipped-drift" };
292
- }
293
- } catch {
294
- return { target, skill: skillLabel, destPath, status: "skipped-drift" };
295
- }
296
- }
297
- mkdirSync(dirname(destPath), { recursive: true });
298
- writeFileSync(destPath, src);
299
- return { target, skill: skillLabel, destPath, status: exists ? "updated" : "created" };
300
- }
301
- function installDataFile(packageRoot, projectRoot, channelDir, dataFilename, force, target) {
302
- const skillLabel = `data:${dataFilename}`;
303
- const srcPath = join2(packageRoot, "data", dataFilename);
304
- const destPath = join2(projectRoot, channelDir, "data", dataFilename);
305
- if (!existsSync2(srcPath)) {
306
- return { target, skill: skillLabel, destPath, status: "skipped-drift" };
307
- }
308
- const src = readFileSync(srcPath, "utf8");
309
- const exists = existsSync2(destPath);
310
- const existing = exists ? readFileSync(destPath, "utf8") : "";
311
- if (exists && existing === src) {
312
- return { target, skill: skillLabel, destPath, status: "unchanged" };
313
- }
314
- if (exists && !force) {
315
- return { target, skill: skillLabel, destPath, status: "skipped-drift" };
316
- }
317
- mkdirSync(dirname(destPath), { recursive: true });
318
- writeFileSync(destPath, src, "utf8");
319
- return {
320
- target,
321
- skill: skillLabel,
322
- destPath,
323
- status: exists ? "updated" : "created"
324
- };
325
- }
326
- function installAgentFile(packageRoot, projectRoot, channel, filename, force) {
327
- const target = channel === "claude" ? "claude-code" : "codex";
328
- const skillLabel = `agent:${filename}`;
329
- const parsed = parseCanonicalAgent(packageRoot, filename);
330
- const rendered = channel === "claude" ? renderClaudeAgent(parsed) : renderCodexAgent(parsed);
331
- const destFilename = channel === "claude" ? filename : filename.replace(/\.md$/, ".toml");
332
- const destPath = join2(
333
- projectRoot,
334
- channel === "claude" ? ".claude" : ".codex",
335
- "agents",
336
- destFilename
337
- );
338
- const managed = channel === "claude" ? rendered : "# omd:installed-agent \u2014 generated from agents/" + filename + " by `omd install-skills`. Do not edit; rerun the command to refresh.\n\n" + rendered;
339
- const exists = existsSync2(destPath);
340
- const existing = exists ? readFileSync(destPath, "utf8") : "";
341
- if (exists && existing === managed) {
342
- return { target, skill: skillLabel, destPath, status: "unchanged" };
343
- }
344
- const isManaged = channel === "claude" ? /\nomd_managed:\s*true\b/.test(existing) : existing.startsWith("# omd:installed-agent");
345
- if (exists && !isManaged && !force) {
346
- return { target, skill: skillLabel, destPath, status: "skipped-drift" };
347
- }
348
- mkdirSync(dirname(destPath), { recursive: true });
349
- writeFileSync(destPath, managed, "utf8");
350
- return {
351
- target,
352
- skill: skillLabel,
353
- destPath,
354
- status: exists ? "updated" : "created"
355
- };
356
- }
357
- function installReferenceCatalog(packageRoot, installRoot, channelDir, force) {
358
- const srcRoot = join2(packageRoot, "web", "references");
359
- if (!existsSync2(srcRoot)) return 0;
360
- const destRoot = join2(installRoot, channelDir, "data", "references");
361
- let written = 0;
362
- for (const id of readdirSync(srcRoot)) {
363
- const srcDesign = join2(srcRoot, id, "DESIGN.md");
364
- if (!existsSync2(srcDesign)) continue;
365
- const destDesign = join2(destRoot, id, "DESIGN.md");
366
- const src = readFileSync(srcDesign, "utf8");
367
- if (existsSync2(destDesign)) {
368
- const existing = readFileSync(destDesign, "utf8");
369
- if (existing === src) continue;
370
- if (!force) continue;
371
- }
372
- mkdirSync(dirname(destDesign), { recursive: true });
373
- writeFileSync(destDesign, src, "utf8");
374
- written++;
375
- }
376
- return written;
377
- }
378
- var CURSOR_RULE_BODY = [
379
- "The authoritative design spec lives at `@DESIGN.md` (repo root). Open and read before generating/modifying UI.",
380
- "",
381
- "Pending preference corrections: `@.omd/preferences.md`.",
382
- "",
383
- "Precedence: DESIGN.md > preferences.md > framework defaults."
384
- ].join("\n");
385
- function renderCursorRule() {
386
- const hash = createHash("sha256").update(CURSOR_RULE_BODY).digest("hex").slice(0, 12);
387
- return [
388
- "---",
389
- "description: Authoritative brand & UI design system. Read DESIGN.md before UI work.",
390
- "globs:",
391
- ' - "**/*.tsx"',
392
- ' - "**/*.jsx"',
393
- ' - "**/*.vue"',
394
- ' - "**/*.svelte"',
395
- ' - "**/*.css"',
396
- ' - "**/*.scss"',
397
- ' - "**/tailwind.config.*"',
398
- ' - "**/components/**"',
399
- ' - "**/app/**/page.*"',
400
- "alwaysApply: false",
401
- "---",
402
- "",
403
- `<!-- omd:start v=1 hash=${hash} -->`,
404
- CURSOR_RULE_BODY,
405
- "<!-- omd:end -->",
406
- ""
407
- ].join("\n");
408
- }
409
- function installCursorRule(installRoot, force) {
410
- const target = "cursor";
411
- const skillLabel = "rule:omd-design.mdc";
412
- const destPath = join2(installRoot, ".cursor", "rules", "omd-design.mdc");
413
- const rendered = renderCursorRule();
414
- const exists = existsSync2(destPath);
415
- const existing = exists ? readFileSync(destPath, "utf8") : "";
416
- if (exists && existing === rendered) {
417
- return { target, skill: skillLabel, destPath, status: "unchanged" };
418
- }
419
- if (exists && !existing.includes("<!-- omd:start") && !force) {
420
- return { target, skill: skillLabel, destPath, status: "skipped-drift" };
421
- }
422
- mkdirSync(dirname(destPath), { recursive: true });
423
- writeFileSync(destPath, rendered, "utf8");
424
- return { target, skill: skillLabel, destPath, status: exists ? "updated" : "created" };
425
- }
426
- var STATUS_LABEL = {
427
- created: pc.green("created"),
428
- updated: pc.cyan("updated"),
429
- unchanged: pc.dim("unchanged"),
430
- "skipped-drift": pc.yellow("skipped"),
431
- "skipped-incompat": pc.yellow("skipped (claude-code only)")
432
- };
433
- function autoDetectTargets(projectRoot) {
434
- const presence = detectInstalledAgents(projectRoot);
435
- const targets = [];
436
- if (presence.claudeCode) targets.push("claude-code");
437
- if (presence.codex) targets.push("codex");
438
- if (presence.opencode) targets.push("opencode");
439
- if (presence.cursor) targets.push("cursor");
440
- if (targets.length === 0) {
441
- return ["claude-code", "codex", "opencode"];
442
- }
443
- return targets;
444
- }
445
- async function runInstallSkills(opts = {}) {
446
- const projectRoot = opts.dir ?? process.cwd();
447
- const packageRoot = findPackageRoot();
448
- if (!packageRoot) {
449
- console.error(pc.red("omd install-skills: package data not found"));
450
- return 1;
451
- }
452
- const allSkills = listShippedSkills(packageRoot);
453
- if (allSkills.length === 0) {
454
- console.error(pc.red("omd install-skills: no skills found in package"));
455
- return 1;
456
- }
457
- const allAgents = listCanonicalAgents(packageRoot);
458
- const force = opts.force ?? false;
459
- const minimal = opts.skillsOnly === true;
460
- let scope = opts.global ? "global" : "project";
461
- p.intro(
462
- pc.bold("omd install-skills") + pc.dim(` (${relative(process.cwd(), projectRoot) || "."})`)
463
- );
464
- const isTTY = Boolean(process.stdin.isTTY && process.stdout.isTTY);
465
- const interactive = isTTY && !opts.all;
466
- const detected = autoDetectTargets(projectRoot);
467
- const presence = detectInstalledAgents(projectRoot);
468
- const actuallyDetected = [
469
- presence.claudeCode ? "claude-code" : null,
470
- presence.codex ? "codex" : null,
471
- presence.opencode ? "opencode" : null,
472
- presence.cursor ? "cursor" : null
473
- ].filter((x) => x !== null);
474
- if (!opts.global && interactive) {
475
- const scopeResult = await p.select({
476
- message: "Install scope \xB7 \uC5B4\uB514\uC5D0 \uC124\uCE58\uD560\uAE4C\uC694?",
477
- options: [
478
- { value: "project", label: "Project", hint: `${relative(process.cwd(), projectRoot) || "."}/.claude/skills \xB7 \uC774 \uD504\uB85C\uC81D\uD2B8\uB9CC` },
479
- { value: "global", label: "Global", hint: "~/.claude/skills \xB7 \uBAA8\uB4E0 \uD504\uB85C\uC81D\uD2B8 (skills + sub-agents, hooks/settings \uC81C\uC678)" }
480
- ],
481
- initialValue: "project"
482
- });
483
- if (p.isCancel(scopeResult)) {
484
- p.cancel("Install cancelled.");
485
- return 130;
486
- }
487
- scope = scopeResult;
488
- }
489
- let skills;
490
- if (opts.skillsFilter) {
491
- skills = allSkills.filter((s) => opts.skillsFilter.includes(s));
492
- } else if (interactive) {
493
- const skillResult = await p.multiselect({
494
- message: "Skills \xB7 space = \uD1A0\uAE00 \xB7 a = \uC804\uCCB4 \xB7 enter = \uD655\uC778 (default ALL)",
495
- options: allSkills.map((s) => ({ value: s, label: s, hint: "omd skill" })),
496
- initialValues: allSkills,
497
- required: true
498
- });
499
- if (p.isCancel(skillResult)) {
500
- p.cancel("Install cancelled.");
501
- return 130;
502
- }
503
- skills = skillResult;
504
- } else {
505
- skills = allSkills;
506
- }
507
- let canonicalAgents;
508
- if (minimal) {
509
- canonicalAgents = [];
510
- } else if (opts.agentsFilter) {
511
- canonicalAgents = allAgents.filter((a) => opts.agentsFilter.includes(a.replace(/\.md$/, "")));
512
- } else if (interactive && allAgents.length > 0) {
513
- const agentResult = await p.multiselect({
514
- message: "Sub-agents \xB7 space = \uD1A0\uAE00 \xB7 a = \uC804\uCCB4 \xB7 enter = \uD655\uC778 (default ALL)",
515
- options: allAgents.map((a) => ({ value: a, label: a.replace(/\.md$/, ""), hint: "subagent" })),
516
- initialValues: allAgents,
517
- required: false
518
- });
519
- if (p.isCancel(agentResult)) {
520
- p.cancel("Install cancelled.");
521
- return 130;
522
- }
523
- canonicalAgents = agentResult;
524
- } else {
525
- canonicalAgents = allAgents;
526
- }
527
- const supportedTargets = (() => {
528
- const set = new Set(skills.flatMap((s) => skillSupportedChannels(packageRoot, s)));
529
- set.add("cursor");
530
- return ["claude-code", "codex", "opencode", "cursor"].filter((t) => set.has(t));
531
- })();
532
- const channelLabel = {
533
- "claude-code": "Claude Code",
534
- codex: "Codex",
535
- opencode: "OpenCode",
536
- cursor: "Cursor"
537
- };
538
- const channelDir = {
539
- "claude-code": ".claude",
540
- codex: ".codex",
541
- opencode: ".opencode",
542
- cursor: ".cursor"
543
- };
544
- let targets;
545
- if (opts.agents) {
546
- targets = opts.agents;
547
- } else if (interactive) {
548
- const defaults = actuallyDetected.filter((t) => supportedTargets.includes(t));
549
- const targetResult = await p.multiselect({
550
- message: "Agent channels \xB7 \uC5B4\uB514\uC5D0 \uC124\uCE58\uD560\uAE4C\uC694? \xB7 space = \uD1A0\uAE00 \xB7 enter = \uD655\uC778",
551
- options: supportedTargets.map((t) => ({
552
- value: t,
553
- label: channelLabel[t],
554
- hint: actuallyDetected.includes(t) ? `${channelDir[t]}/ detected` : ""
555
- })),
556
- initialValues: defaults.length > 0 ? defaults : supportedTargets,
557
- required: true
558
- });
559
- if (p.isCancel(targetResult)) {
560
- p.cancel("Install cancelled.");
561
- return 130;
562
- }
563
- targets = targetResult;
564
- } else {
565
- targets = opts.all ? ["claude-code", "codex", "opencode"] : minimal ? actuallyDetected.length > 0 ? actuallyDetected : ["claude-code"] : detected;
566
- const narrowed = targets.filter((t) => supportedTargets.includes(t));
567
- if (narrowed.length > 0) targets = narrowed;
568
- }
569
- const installRoot = scope === "global" ? homedir() : projectRoot;
570
- const skillChannelTargets = targets.filter(
571
- (t) => t !== "cursor"
572
- );
573
- const plans = skillChannelTargets.map((t) => planForTarget(installRoot, t));
574
- p.log.message(
575
- pc.bold("Scope: ") + pc.cyan(scope) + pc.dim(scope === "global" ? " (~/.claude)" : ` (${relative(process.cwd(), projectRoot) || "."})`)
576
- );
577
- p.log.message(
578
- pc.bold(`Skills (${skills.length}): `) + skills.map((s) => pc.cyan(s)).join(", ")
579
- );
580
- if (minimal) {
581
- canonicalAgents = [];
582
- p.log.message(pc.bold("Agents: ") + pc.dim("skipped (--skills-only)"));
583
- } else if (canonicalAgents.length > 0) {
584
- p.log.message(
585
- pc.bold(`Agents (${canonicalAgents.length}): `) + canonicalAgents.map((a) => pc.cyan(a.replace(/\.md$/, ""))).join(", ")
586
- );
587
- }
588
- p.log.message(
589
- pc.bold("Targets: ") + targets.map((t) => pc.cyan(t)).join(", ")
590
- );
591
- const results = [];
592
- let catalogCount = 0;
593
- for (const plan of plans) {
594
- for (const skill of skills) {
595
- results.push(installOne(packageRoot, plan, skill, force));
596
- }
597
- }
598
- for (const target of targets) {
599
- if (target === "claude-code") {
600
- for (const filename of canonicalAgents) {
601
- results.push(installAgentFile(packageRoot, installRoot, "claude", filename, force));
602
- }
603
- } else if (target === "codex") {
604
- for (const filename of canonicalAgents) {
605
- results.push(installAgentFile(packageRoot, installRoot, "codex", filename, force));
606
- }
607
- }
608
- }
609
- if (!minimal) {
610
- if (targets.includes("cursor")) {
611
- results.push(installCursorRule(installRoot, force));
612
- }
613
- const dataFiles = [
614
- "reference-fingerprints.json",
615
- "reference-tags.md",
616
- "vocabulary.json",
617
- "synonyms.json",
618
- "opt-out-corpus.json"
619
- ];
620
- for (const target of targets) {
621
- const dataDir = dataDirFor(target, targets);
622
- if (!dataDir) continue;
623
- for (const dataFile of dataFiles) {
624
- results.push(installDataFile(packageRoot, installRoot, dataDir, dataFile, force, target));
625
- }
626
- }
627
- for (const target of targets) {
628
- const dataDir = dataDirFor(target, targets);
629
- if (dataDir) {
630
- catalogCount += installReferenceCatalog(packageRoot, installRoot, dataDir, force);
631
- }
632
- }
633
- for (const target of targets) {
634
- const cd = CHANNEL_DATA_DIRS[target];
635
- if (!cd) continue;
636
- for (const helper of ["ctx-prime.cjs", "context.cjs"]) {
637
- const srcHelper = join2(packageRoot, "scripts", helper);
638
- if (!existsSync2(srcHelper)) continue;
639
- const destHelper = join2(installRoot, cd, "data", "scripts", helper);
640
- const srcTxt = readFileSync(srcHelper, "utf8");
641
- if (existsSync2(destHelper) && readFileSync(destHelper, "utf8") === srcTxt) continue;
642
- mkdirSync(dirname(destHelper), { recursive: true });
643
- writeFileSync(destHelper, srcTxt, "utf8");
644
- }
645
- }
646
- if (scope === "project" && targets.includes("claude-code")) {
647
- for (const hookFile of [
648
- "skill-activation.cjs",
649
- "session-state-loader.cjs",
650
- "post-edit-watch.cjs",
651
- "session-end-foldin.cjs",
652
- // Shared modules required by the fold-in / state-loader / watch hooks.
653
- // Live in a lib/ subdir; installHookFile preserves the relative path
654
- // under .claude/hooks/.
655
- join2("lib", "preferences-parser.cjs"),
656
- join2("lib", "preferences-writer.cjs")
657
- ]) {
658
- results.push(installHookFile(packageRoot, installRoot, hookFile, force));
659
- }
660
- results.push(installSettingsJson(packageRoot, installRoot, force));
661
- }
662
- }
663
- p.log.message(pc.bold("\nResults:"));
664
- for (const r of results) {
665
- const rel = relative(installRoot, r.destPath);
666
- p.log.message(
667
- ` ${STATUS_LABEL[r.status]} ${pc.dim(r.target.padEnd(12))} ${rel}`
668
- );
669
- }
670
- const driftCount = results.filter((r) => r.status === "skipped-drift").length;
671
- const writtenCount = results.filter(
672
- (r) => r.status === "created" || r.status === "updated"
673
- ).length;
674
- if (driftCount > 0) {
675
- p.outro(
676
- pc.yellow(
677
- `${writtenCount} written, ${driftCount} skipped (existing files lack the omd marker \u2014 rerun with --force to overwrite).`
678
- )
679
- );
680
- return 0;
681
- }
682
- if (minimal) {
683
- for (const r of results.filter((x) => x.status === "skipped-incompat")) {
684
- p.log.warn(
685
- `${pc.bold(r.skill)} ${pc.dim("skipped for ")}${pc.cyan(r.target)}${pc.dim(" \u2014 declares x-omd-channels (channel not supported).")}`
686
- );
687
- }
688
- const installed = results.filter(
689
- (r) => r.status === "created" || r.status === "updated"
690
- );
691
- if (installed.length === 0) {
692
- p.outro(pc.yellow("Nothing installed \u2014 no compatible skill/channel match."));
693
- return 0;
694
- }
695
- p.outro(
696
- pc.green(
697
- `Done. Installed ${skills.map((s) => pc.bold(s)).join(", ")} ${scope === "global" ? "globally (~/.claude/skills)" : `for ${targets.join(", ")}`}.`
698
- ) + pc.dim(" \u2192 restart your agent, then use the skill (e.g. ") + pc.cyan("/claude-design") + pc.dim(").")
699
- );
700
- return 0;
701
- }
702
- const nextSteps = [
703
- `${pc.bold("Restart your agent, then type your first prompt:")}`,
704
- "",
705
- ` ${pc.cyan("EN")} ${pc.dim("Set up our design system \u2014 Toss-style, for a family meal-tracking app.")}`,
706
- ` ${pc.cyan("KR")} ${pc.dim("\uD1A0\uC2A4 \uC2A4\uD0C0\uC77C\uB85C \uAC00\uC871 \uC2DD\uB2E8 \uACF5\uC720 \uC571 \uB514\uC790\uC778 \uC2DC\uC2A4\uD15C \uC7A1\uC544\uC918")}`,
707
- "",
708
- `${pc.dim("Your agent runs omd:init and writes DESIGN.md. Then build against it:")}`,
709
- ` ${pc.cyan("EN")} ${pc.dim("Design the home screen.")} ${pc.cyan("KR")} ${pc.dim("\uD648 \uD654\uBA74 \uB514\uC790\uC778\uD574\uC918")}`,
710
- "",
711
- `${pc.dim('Full walkthrough \u2192 "Your first 60 seconds" in the README. Routing is automatic \u2014 no slash command needed.')}`,
712
- `${pc.dim("Power user: ")}${pc.cyan("/omd-harness <task>")}${pc.dim(" \u2014 jump straight into the pipeline.")}`,
713
- "",
714
- `${pc.yellow("\u26A0 Already-running session?")} ${pc.dim("Run `/agents` to reload \u2014 or quit (Cmd+Q on macOS) and relaunch. Without reload, hooks/agents do not load.")}`
715
- ].join("\n");
716
- p.note(nextSteps, "Next");
717
- const hookCount = scope === "project" && targets.includes("claude-code") ? 4 : 0;
718
- if (catalogCount > 0) {
719
- p.log.message(
720
- pc.bold("Reference catalog: ") + pc.cyan(`${catalogCount}`) + pc.dim(" DESIGN.md copied \u2192 .claude/data/references/<id>/DESIGN.md")
721
- );
722
- }
723
- p.outro(
724
- pc.green(
725
- `Done. ${skills.length} skills \xB7 ${canonicalAgents.length} sub-agents \xB7 ${hookCount} hooks \xB7 ${catalogCount} catalog refs installed (${writtenCount} files)${scope === "global" ? " globally (~/.claude)" : ""}.`
726
- )
727
- );
728
- return 0;
729
- }
730
- export {
731
- dataDirFor,
732
- runInstallSkills
733
- };
734
- //# sourceMappingURL=install-skills-7UUDOLG2.js.map