oh-my-customcode 0.1.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 (237) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +287 -0
  3. package/dist/cli/index.js +13299 -0
  4. package/dist/index.js +927 -0
  5. package/package.json +74 -0
  6. package/templates/.claude/contexts/dev.md +20 -0
  7. package/templates/.claude/contexts/ecomode.md +63 -0
  8. package/templates/.claude/contexts/index.yaml +41 -0
  9. package/templates/.claude/contexts/research.md +28 -0
  10. package/templates/.claude/contexts/review.md +23 -0
  11. package/templates/.claude/hooks/hooks.json +185 -0
  12. package/templates/.claude/hooks/hud/index.yaml +27 -0
  13. package/templates/.claude/hooks/hud/update-status.sh +32 -0
  14. package/templates/.claude/hooks/index.yaml +46 -0
  15. package/templates/.claude/hooks/memory-persistence/pre-compact.sh +37 -0
  16. package/templates/.claude/hooks/memory-persistence/session-end.sh +64 -0
  17. package/templates/.claude/hooks/memory-persistence/session-start.sh +41 -0
  18. package/templates/.claude/hooks/strategic-compact/suggest-compact.sh +50 -0
  19. package/templates/.claude/install-hooks.sh +100 -0
  20. package/templates/.claude/rules/MAY-optimization.md +93 -0
  21. package/templates/.claude/rules/MUST-agent-design.md +107 -0
  22. package/templates/.claude/rules/MUST-agent-identification.md +108 -0
  23. package/templates/.claude/rules/MUST-continuous-improvement.md +132 -0
  24. package/templates/.claude/rules/MUST-intent-transparency.md +199 -0
  25. package/templates/.claude/rules/MUST-language-policy.md +62 -0
  26. package/templates/.claude/rules/MUST-orchestrator-coordination.md +266 -0
  27. package/templates/.claude/rules/MUST-parallel-execution.md +341 -0
  28. package/templates/.claude/rules/MUST-permissions.md +84 -0
  29. package/templates/.claude/rules/MUST-safety.md +69 -0
  30. package/templates/.claude/rules/MUST-sync-verification.md +219 -0
  31. package/templates/.claude/rules/MUST-tool-identification.md +112 -0
  32. package/templates/.claude/rules/SHOULD-ecomode.md +145 -0
  33. package/templates/.claude/rules/SHOULD-error-handling.md +102 -0
  34. package/templates/.claude/rules/SHOULD-hud-statusline.md +89 -0
  35. package/templates/.claude/rules/SHOULD-interaction.md +103 -0
  36. package/templates/.claude/rules/SHOULD-memory-integration.md +114 -0
  37. package/templates/.claude/rules/SHOULD-pipeline-mode.md +165 -0
  38. package/templates/.claude/rules/index.yaml +125 -0
  39. package/templates/.claude/uninstall-hooks.sh +52 -0
  40. package/templates/CLAUDE.md.en +259 -0
  41. package/templates/CLAUDE.md.ko +259 -0
  42. package/templates/agents/index.yaml +237 -0
  43. package/templates/agents/infra-engineer/aws-expert/AGENT.md +47 -0
  44. package/templates/agents/infra-engineer/aws-expert/index.yaml +27 -0
  45. package/templates/agents/infra-engineer/docker-expert/AGENT.md +47 -0
  46. package/templates/agents/infra-engineer/docker-expert/index.yaml +27 -0
  47. package/templates/agents/manager/creator/AGENT.md +274 -0
  48. package/templates/agents/manager/creator/index.yaml +66 -0
  49. package/templates/agents/manager/gitnerd/AGENT.md +91 -0
  50. package/templates/agents/manager/gitnerd/index.yaml +55 -0
  51. package/templates/agents/manager/sauron/AGENT.md +153 -0
  52. package/templates/agents/manager/sauron/index.yaml +52 -0
  53. package/templates/agents/manager/supplier/AGENT.md +142 -0
  54. package/templates/agents/manager/supplier/index.yaml +31 -0
  55. package/templates/agents/manager/sync-checker/AGENT.md +34 -0
  56. package/templates/agents/manager/sync-checker/index.yaml +32 -0
  57. package/templates/agents/manager/updater/AGENT.md +125 -0
  58. package/templates/agents/manager/updater/index.yaml +31 -0
  59. package/templates/agents/orchestrator/dev-lead/AGENT.md +116 -0
  60. package/templates/agents/orchestrator/dev-lead/index.yaml +73 -0
  61. package/templates/agents/orchestrator/planner/AGENT.md +102 -0
  62. package/templates/agents/orchestrator/planner/index.yaml +38 -0
  63. package/templates/agents/orchestrator/qa-lead/AGENT.md +92 -0
  64. package/templates/agents/orchestrator/qa-lead/index.yaml +40 -0
  65. package/templates/agents/orchestrator/secretary/AGENT.md +132 -0
  66. package/templates/agents/orchestrator/secretary/index.yaml +55 -0
  67. package/templates/agents/qa-team/qa-engineer/AGENT.md +98 -0
  68. package/templates/agents/qa-team/qa-engineer/index.yaml +59 -0
  69. package/templates/agents/qa-team/qa-planner/AGENT.md +75 -0
  70. package/templates/agents/qa-team/qa-planner/index.yaml +47 -0
  71. package/templates/agents/qa-team/qa-writer/AGENT.md +98 -0
  72. package/templates/agents/qa-team/qa-writer/index.yaml +44 -0
  73. package/templates/agents/sw-architect/documenter/AGENT.md +120 -0
  74. package/templates/agents/sw-architect/documenter/index.yaml +39 -0
  75. package/templates/agents/sw-architect/speckit-agent/AGENT.md +127 -0
  76. package/templates/agents/sw-architect/speckit-agent/index.yaml +78 -0
  77. package/templates/agents/sw-engineer/backend/express-expert/AGENT.md +132 -0
  78. package/templates/agents/sw-engineer/backend/express-expert/index.yaml +36 -0
  79. package/templates/agents/sw-engineer/backend/fastapi-expert/AGENT.md +47 -0
  80. package/templates/agents/sw-engineer/backend/fastapi-expert/index.yaml +27 -0
  81. package/templates/agents/sw-engineer/backend/go-backend-expert/AGENT.md +47 -0
  82. package/templates/agents/sw-engineer/backend/go-backend-expert/index.yaml +27 -0
  83. package/templates/agents/sw-engineer/backend/nestjs-expert/AGENT.md +107 -0
  84. package/templates/agents/sw-engineer/backend/nestjs-expert/index.yaml +43 -0
  85. package/templates/agents/sw-engineer/backend/springboot-expert/AGENT.md +103 -0
  86. package/templates/agents/sw-engineer/backend/springboot-expert/index.yaml +69 -0
  87. package/templates/agents/sw-engineer/frontend/svelte-agent/AGENT.md +71 -0
  88. package/templates/agents/sw-engineer/frontend/svelte-agent/index.yaml +41 -0
  89. package/templates/agents/sw-engineer/frontend/vercel-agent/AGENT.md +67 -0
  90. package/templates/agents/sw-engineer/frontend/vercel-agent/index.yaml +43 -0
  91. package/templates/agents/sw-engineer/frontend/vuejs-agent/AGENT.md +71 -0
  92. package/templates/agents/sw-engineer/frontend/vuejs-agent/index.yaml +48 -0
  93. package/templates/agents/sw-engineer/language/golang-expert/AGENT.md +47 -0
  94. package/templates/agents/sw-engineer/language/golang-expert/index.yaml +27 -0
  95. package/templates/agents/sw-engineer/language/java21-expert/AGENT.md +122 -0
  96. package/templates/agents/sw-engineer/language/java21-expert/index.yaml +51 -0
  97. package/templates/agents/sw-engineer/language/kotlin-expert/AGENT.md +47 -0
  98. package/templates/agents/sw-engineer/language/kotlin-expert/index.yaml +27 -0
  99. package/templates/agents/sw-engineer/language/python-expert/AGENT.md +47 -0
  100. package/templates/agents/sw-engineer/language/python-expert/index.yaml +27 -0
  101. package/templates/agents/sw-engineer/language/rust-expert/AGENT.md +47 -0
  102. package/templates/agents/sw-engineer/language/rust-expert/index.yaml +27 -0
  103. package/templates/agents/sw-engineer/language/typescript-expert/AGENT.md +47 -0
  104. package/templates/agents/sw-engineer/language/typescript-expert/index.yaml +27 -0
  105. package/templates/agents/sw-engineer/tooling/bun-expert/AGENT.md +73 -0
  106. package/templates/agents/sw-engineer/tooling/bun-expert/index.yaml +46 -0
  107. package/templates/agents/sw-engineer/tooling/npm-expert/AGENT.md +160 -0
  108. package/templates/agents/sw-engineer/tooling/npm-expert/index.yaml +45 -0
  109. package/templates/agents/sw-engineer/tooling/optimizer/AGENT.md +170 -0
  110. package/templates/agents/sw-engineer/tooling/optimizer/index.yaml +45 -0
  111. package/templates/agents/system/memory-keeper/AGENT.md +126 -0
  112. package/templates/agents/system/memory-keeper/index.yaml +45 -0
  113. package/templates/agents/system/naggy/AGENT.md +72 -0
  114. package/templates/agents/system/naggy/index.yaml +35 -0
  115. package/templates/commands/COMMANDS.md +136 -0
  116. package/templates/commands/creator/agent.md +121 -0
  117. package/templates/commands/dev/refactor.md +126 -0
  118. package/templates/commands/dev/review.md +82 -0
  119. package/templates/commands/git/branch.yaml +8 -0
  120. package/templates/commands/git/commit.yaml +4 -0
  121. package/templates/commands/git/pr.yaml +4 -0
  122. package/templates/commands/git/status.yaml +4 -0
  123. package/templates/commands/git/sync.yaml +4 -0
  124. package/templates/commands/index.yaml +225 -0
  125. package/templates/commands/intent/explain.md +144 -0
  126. package/templates/commands/memory/recall.md +164 -0
  127. package/templates/commands/memory/save.md +128 -0
  128. package/templates/commands/naggy/add.yaml +8 -0
  129. package/templates/commands/naggy/done.yaml +8 -0
  130. package/templates/commands/naggy/list.yaml +4 -0
  131. package/templates/commands/naggy/priority.yaml +11 -0
  132. package/templates/commands/naggy/remind.yaml +4 -0
  133. package/templates/commands/npm/audit.yaml +62 -0
  134. package/templates/commands/npm/publish.yaml +52 -0
  135. package/templates/commands/npm/version.yaml +62 -0
  136. package/templates/commands/optimize/analyze.yaml +34 -0
  137. package/templates/commands/optimize/bundle.yaml +50 -0
  138. package/templates/commands/optimize/report.yaml +56 -0
  139. package/templates/commands/pipeline/list.md +81 -0
  140. package/templates/commands/pipeline/run.md +127 -0
  141. package/templates/commands/sauron/quick.yaml +4 -0
  142. package/templates/commands/sauron/report.yaml +4 -0
  143. package/templates/commands/sauron/watch.yaml +4 -0
  144. package/templates/commands/supplier/audit.md +133 -0
  145. package/templates/commands/supplier/fix.md +121 -0
  146. package/templates/commands/sync/agents.yaml +4 -0
  147. package/templates/commands/sync/check.yaml +4 -0
  148. package/templates/commands/sync/commands.yaml +4 -0
  149. package/templates/commands/sync/docs.yaml +4 -0
  150. package/templates/commands/sync/fix.yaml +4 -0
  151. package/templates/commands/system/help.md +137 -0
  152. package/templates/commands/system/lists.md +86 -0
  153. package/templates/commands/system/status.md +163 -0
  154. package/templates/commands/updater/docs.md +165 -0
  155. package/templates/commands/updater/external.md +214 -0
  156. package/templates/guides/aws/common-patterns.md +169 -0
  157. package/templates/guides/aws/index.yaml +26 -0
  158. package/templates/guides/aws/well-architected.md +143 -0
  159. package/templates/guides/claude-code/01-overview.md +42 -0
  160. package/templates/guides/claude-code/03-tools.md +107 -0
  161. package/templates/guides/claude-code/04-agent-skills.md +90 -0
  162. package/templates/guides/claude-code/05-agent-sdk.md +129 -0
  163. package/templates/guides/claude-code/06-mcp.md +165 -0
  164. package/templates/guides/claude-code/07-prompt-engineering.md +100 -0
  165. package/templates/guides/claude-code/08-testing.md +58 -0
  166. package/templates/guides/claude-code/09-guardrails.md +80 -0
  167. package/templates/guides/claude-code/10-monitoring.md +89 -0
  168. package/templates/guides/claude-code/index.yaml +51 -0
  169. package/templates/guides/docker/compose-best-practices.md +284 -0
  170. package/templates/guides/docker/dockerfile-best-practices.md +262 -0
  171. package/templates/guides/docker/index.yaml +26 -0
  172. package/templates/guides/fastapi/best-practices.md +232 -0
  173. package/templates/guides/fastapi/index.yaml +21 -0
  174. package/templates/guides/go-backend/index.yaml +26 -0
  175. package/templates/guides/go-backend/project-layout.md +243 -0
  176. package/templates/guides/go-backend/uber-style.md +212 -0
  177. package/templates/guides/golang/concurrency.md +282 -0
  178. package/templates/guides/golang/effective-go.md +309 -0
  179. package/templates/guides/golang/error-handling.md +250 -0
  180. package/templates/guides/golang/index.yaml +27 -0
  181. package/templates/guides/index.yaml +101 -0
  182. package/templates/guides/kotlin/coding-conventions.md +247 -0
  183. package/templates/guides/kotlin/idioms.md +234 -0
  184. package/templates/guides/kotlin/index.yaml +26 -0
  185. package/templates/guides/python/index.yaml +26 -0
  186. package/templates/guides/python/pep8-style-guide.md +202 -0
  187. package/templates/guides/python/zen-of-python.md +79 -0
  188. package/templates/guides/rust/error-handling.md +262 -0
  189. package/templates/guides/rust/index.yaml +26 -0
  190. package/templates/guides/rust/ownership.md +180 -0
  191. package/templates/guides/springboot/best-practices.md +361 -0
  192. package/templates/guides/springboot/index.yaml +22 -0
  193. package/templates/guides/typescript/advanced-types.md +225 -0
  194. package/templates/guides/typescript/index.yaml +26 -0
  195. package/templates/guides/typescript/type-system.md +219 -0
  196. package/templates/guides/web-design/accessibility.md +66 -0
  197. package/templates/guides/web-design/index.yaml +20 -0
  198. package/templates/guides/web-design/performance.md +102 -0
  199. package/templates/pipelines/examples/code-review.yaml +66 -0
  200. package/templates/pipelines/index.yaml +18 -0
  201. package/templates/pipelines/templates/pipeline-template.yaml +50 -0
  202. package/templates/skills/backend/fastapi-best-practices/SKILL.md +269 -0
  203. package/templates/skills/backend/fastapi-best-practices/index.yaml +25 -0
  204. package/templates/skills/backend/go-backend-best-practices/SKILL.md +337 -0
  205. package/templates/skills/backend/go-backend-best-practices/index.yaml +26 -0
  206. package/templates/skills/backend/springboot-best-practices/SKILL.md +356 -0
  207. package/templates/skills/backend/springboot-best-practices/index.yaml +27 -0
  208. package/templates/skills/development/go-best-practices/SKILL.md +202 -0
  209. package/templates/skills/development/go-best-practices/index.yaml +25 -0
  210. package/templates/skills/development/kotlin-best-practices/SKILL.md +255 -0
  211. package/templates/skills/development/kotlin-best-practices/index.yaml +27 -0
  212. package/templates/skills/development/python-best-practices/SKILL.md +221 -0
  213. package/templates/skills/development/python-best-practices/index.yaml +25 -0
  214. package/templates/skills/development/react-best-practices/SKILL.md +100 -0
  215. package/templates/skills/development/react-best-practices/index.yaml +39 -0
  216. package/templates/skills/development/rust-best-practices/SKILL.md +266 -0
  217. package/templates/skills/development/rust-best-practices/index.yaml +26 -0
  218. package/templates/skills/development/typescript-best-practices/SKILL.md +320 -0
  219. package/templates/skills/development/typescript-best-practices/index.yaml +28 -0
  220. package/templates/skills/development/vercel-deploy/SKILL.md +73 -0
  221. package/templates/skills/development/vercel-deploy/index.yaml +30 -0
  222. package/templates/skills/development/web-design-guidelines/SKILL.md +117 -0
  223. package/templates/skills/development/web-design-guidelines/index.yaml +34 -0
  224. package/templates/skills/index.yaml +129 -0
  225. package/templates/skills/infrastructure/aws-best-practices/SKILL.md +279 -0
  226. package/templates/skills/infrastructure/aws-best-practices/index.yaml +27 -0
  227. package/templates/skills/infrastructure/docker-best-practices/SKILL.md +274 -0
  228. package/templates/skills/infrastructure/docker-best-practices/index.yaml +26 -0
  229. package/templates/skills/orchestration/intent-detection/SKILL.md +214 -0
  230. package/templates/skills/orchestration/intent-detection/index.yaml +30 -0
  231. package/templates/skills/orchestration/intent-detection/patterns/agent-triggers.yaml +333 -0
  232. package/templates/skills/orchestration/pipeline-execution/SKILL.md +188 -0
  233. package/templates/skills/orchestration/pipeline-execution/index.yaml +27 -0
  234. package/templates/skills/system/memory-management/SKILL.md +194 -0
  235. package/templates/skills/system/memory-management/index.yaml +30 -0
  236. package/templates/skills/system/result-aggregation/SKILL.md +163 -0
  237. package/templates/skills/system/result-aggregation/index.yaml +36 -0
package/dist/index.js ADDED
@@ -0,0 +1,927 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
+
20
+ // src/core/installer.ts
21
+ import { copyFile as fsCopyFile, rename } from "node:fs/promises";
22
+ import { basename, join as join3 } from "node:path";
23
+
24
+ // src/utils/fs.ts
25
+ import { dirname, join, resolve } from "node:path";
26
+ import { fileURLToPath } from "node:url";
27
+ async function fileExists(path) {
28
+ const fs = await import("node:fs/promises");
29
+ try {
30
+ await fs.access(path);
31
+ return true;
32
+ } catch {
33
+ return false;
34
+ }
35
+ }
36
+ async function ensureDirectory(path) {
37
+ const fs = await import("node:fs/promises");
38
+ await fs.mkdir(path, { recursive: true });
39
+ }
40
+ function shouldSkipEntry(entryName, options) {
41
+ if (options.exclude?.some((pattern) => matchesPattern(entryName, pattern))) {
42
+ return true;
43
+ }
44
+ if (options.include && !options.include.some((pattern) => matchesPattern(entryName, pattern))) {
45
+ return true;
46
+ }
47
+ return false;
48
+ }
49
+ async function handleSymlink(srcPath, destPath, options, fs) {
50
+ const destExists = await fileExists(destPath);
51
+ if (destExists && !options.overwrite) {
52
+ return;
53
+ }
54
+ if (options.preserveSymlinks !== false) {
55
+ await copyPreservedSymlink(srcPath, destPath, destExists, fs);
56
+ } else {
57
+ await copyFollowedSymlink(srcPath, destPath, destExists, options, fs);
58
+ }
59
+ }
60
+ async function copyPreservedSymlink(srcPath, destPath, destExists, fs) {
61
+ const linkTarget = await fs.readlink(srcPath);
62
+ if (destExists) {
63
+ await fs.unlink(destPath);
64
+ }
65
+ await fs.symlink(linkTarget, destPath);
66
+ }
67
+ async function copyFollowedSymlink(srcPath, destPath, destExists, options, fs) {
68
+ const realPath = await fs.realpath(srcPath);
69
+ const stat = await fs.stat(realPath);
70
+ if (stat.isDirectory()) {
71
+ await copyDirectory(realPath, destPath, options);
72
+ return;
73
+ }
74
+ if (destExists) {
75
+ await fs.unlink(destPath);
76
+ }
77
+ await fs.copyFile(realPath, destPath);
78
+ }
79
+ async function handleFile(srcPath, destPath, options, fs) {
80
+ const destExists = await fileExists(destPath);
81
+ if (destExists && !options.overwrite) {
82
+ return;
83
+ }
84
+ await fs.copyFile(srcPath, destPath);
85
+ if (options.preserveTimestamps) {
86
+ const stats = await fs.stat(srcPath);
87
+ await fs.utimes(destPath, stats.atime, stats.mtime);
88
+ }
89
+ }
90
+ async function copyDirectory(src, dest, options = {}) {
91
+ const fs = await import("node:fs/promises");
92
+ const path = await import("node:path");
93
+ await ensureDirectory(dest);
94
+ const entries = await fs.readdir(src, { withFileTypes: true });
95
+ for (const entry of entries) {
96
+ if (shouldSkipEntry(entry.name, options)) {
97
+ continue;
98
+ }
99
+ const srcPath = path.join(src, entry.name);
100
+ const destPath = path.join(dest, entry.name);
101
+ if (entry.isSymbolicLink()) {
102
+ await handleSymlink(srcPath, destPath, options, fs);
103
+ } else if (entry.isDirectory()) {
104
+ await copyDirectory(srcPath, destPath, options);
105
+ } else if (entry.isFile()) {
106
+ await handleFile(srcPath, destPath, options, fs);
107
+ }
108
+ }
109
+ }
110
+ async function readJsonFile(path) {
111
+ const fs = await import("node:fs/promises");
112
+ const content = await fs.readFile(path, "utf-8");
113
+ return JSON.parse(content);
114
+ }
115
+ async function writeJsonFile(path, data) {
116
+ const fs = await import("node:fs/promises");
117
+ const content = JSON.stringify(data, null, 2);
118
+ await fs.writeFile(path, content, "utf-8");
119
+ }
120
+ function getPackageRoot() {
121
+ const currentFile = fileURLToPath(import.meta.url);
122
+ const currentDir = dirname(currentFile);
123
+ return resolve(currentDir, "..", "..");
124
+ }
125
+ function resolveTemplatePath(relativePath) {
126
+ const packageRoot = getPackageRoot();
127
+ return join(packageRoot, "templates", relativePath);
128
+ }
129
+ function matchesPattern(filename, pattern) {
130
+ const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".");
131
+ const regex = new RegExp(`^${regexPattern}$`);
132
+ return regex.test(filename);
133
+ }
134
+
135
+ // src/utils/logger.ts
136
+ var currentOptions = {
137
+ level: "info",
138
+ colors: true,
139
+ locale: "en",
140
+ timestamps: false
141
+ };
142
+ var LOG_LEVELS = {
143
+ debug: 0,
144
+ info: 1,
145
+ warn: 2,
146
+ error: 3
147
+ };
148
+ var COLORS = {
149
+ reset: "\x1B[0m",
150
+ bold: "\x1B[1m",
151
+ dim: "\x1B[2m",
152
+ black: "\x1B[30m",
153
+ red: "\x1B[31m",
154
+ green: "\x1B[32m",
155
+ yellow: "\x1B[33m",
156
+ blue: "\x1B[34m",
157
+ magenta: "\x1B[35m",
158
+ cyan: "\x1B[36m",
159
+ white: "\x1B[37m",
160
+ brightRed: "\x1B[91m",
161
+ brightGreen: "\x1B[92m",
162
+ brightYellow: "\x1B[93m",
163
+ brightBlue: "\x1B[94m",
164
+ brightMagenta: "\x1B[95m",
165
+ brightCyan: "\x1B[96m"
166
+ };
167
+ var LEVEL_COLORS = {
168
+ debug: COLORS.dim,
169
+ info: COLORS.blue,
170
+ warn: COLORS.yellow,
171
+ error: COLORS.red
172
+ };
173
+ var LEVEL_ICONS = {
174
+ debug: "\uD83D\uDD0D",
175
+ info: "ℹ️",
176
+ warn: "⚠️",
177
+ error: "❌"
178
+ };
179
+ var MESSAGES = {
180
+ en: {
181
+ "install.start": "Initializing oh-my-customcode...",
182
+ "install.success": "Successfully initialized!",
183
+ "install.failed": "Installation failed: {{error}}",
184
+ "install.exists": "Existing .claude/ directory found",
185
+ "install.backup": "Backed up existing files to: {{path}}",
186
+ "install.directories_created": "Directory structure created",
187
+ "install.component_skipped": "Skipped {{component}} (already exists)",
188
+ "install.component_installed": "Installed {{component}}",
189
+ "install.template_not_found": "Template not found for {{component}}: {{path}}",
190
+ "install.claude_md_installed": "CLAUDE.md installed ({{language}})",
191
+ "install.claude_md_not_found": "CLAUDE.md template not found for {{language}}",
192
+ "update.start": "Checking for updates...",
193
+ "update.success": "Updated from {{from}} to {{to}}",
194
+ "update.failed": "Update failed: {{error}}",
195
+ "update.no_updates": "Already up to date",
196
+ "update.backup_created": "Backup created at: {{path}}",
197
+ "update.dry_run": "Would update {{component}}",
198
+ "update.component_updated": "Updated {{component}}",
199
+ "update.file_applied": "Applied update to {{path}}",
200
+ "config.load_failed": "Failed to load config: {{error}}",
201
+ "config.not_found": "Config not found at {{path}}, using defaults",
202
+ "config.saved": "Config saved to {{path}}",
203
+ "config.deleted": "Config deleted from {{path}}",
204
+ "general.done": "Done!",
205
+ "general.failed": "Failed",
206
+ "general.skipped": "Skipped"
207
+ },
208
+ ko: {
209
+ "install.start": "oh-my-customcode 초기화 중...",
210
+ "install.success": "초기화 완료!",
211
+ "install.failed": "설치 실패: {{error}}",
212
+ "install.exists": "기존 .claude/ 디렉토리 발견",
213
+ "install.backup": "기존 파일 백업 완료: {{path}}",
214
+ "install.directories_created": "디렉토리 구조 생성 완료",
215
+ "install.component_skipped": "{{component}} 건너뜀 (이미 존재)",
216
+ "install.component_installed": "{{component}} 설치 완료",
217
+ "install.template_not_found": "{{component}} 템플릿 없음: {{path}}",
218
+ "install.claude_md_installed": "CLAUDE.md 설치 완료 ({{language}})",
219
+ "install.claude_md_not_found": "{{language}}용 CLAUDE.md 템플릿 없음",
220
+ "update.start": "업데이트 확인 중...",
221
+ "update.success": "{{from}}에서 {{to}}로 업데이트 완료",
222
+ "update.failed": "업데이트 실패: {{error}}",
223
+ "update.no_updates": "이미 최신 버전입니다",
224
+ "update.backup_created": "백업 생성됨: {{path}}",
225
+ "update.dry_run": "{{component}} 업데이트 예정",
226
+ "update.component_updated": "{{component}} 업데이트 완료",
227
+ "update.file_applied": "{{path}} 업데이트 적용",
228
+ "config.load_failed": "설정 로드 실패: {{error}}",
229
+ "config.not_found": "{{path}}에 설정 없음, 기본값 사용",
230
+ "config.saved": "설정 저장: {{path}}",
231
+ "config.deleted": "설정 삭제: {{path}}",
232
+ "general.done": "완료!",
233
+ "general.failed": "실패",
234
+ "general.skipped": "건너뜀"
235
+ }
236
+ };
237
+ function createLogger(options = {}) {
238
+ currentOptions = { ...currentOptions, ...options };
239
+ }
240
+ function setLogLevel(level) {
241
+ currentOptions.level = level;
242
+ }
243
+ function setLocale(locale) {
244
+ currentOptions.locale = locale;
245
+ }
246
+ function getMessage(key, params) {
247
+ const messages = MESSAGES[currentOptions.locale] || MESSAGES.en;
248
+ let message = messages[key] || key;
249
+ if (params) {
250
+ for (const [k, v] of Object.entries(params)) {
251
+ message = message.replace(new RegExp(`{{${k}}}`, "g"), v);
252
+ }
253
+ }
254
+ return message;
255
+ }
256
+ function formatMessage(level, message) {
257
+ const parts = [];
258
+ if (currentOptions.timestamps) {
259
+ const timestamp = new Date().toISOString().slice(11, 19);
260
+ if (currentOptions.colors) {
261
+ parts.push(`${COLORS.dim}[${timestamp}]${COLORS.reset}`);
262
+ } else {
263
+ parts.push(`[${timestamp}]`);
264
+ }
265
+ }
266
+ if (currentOptions.prefix) {
267
+ if (currentOptions.colors) {
268
+ parts.push(`${COLORS.cyan}[${currentOptions.prefix}]${COLORS.reset}`);
269
+ } else {
270
+ parts.push(`[${currentOptions.prefix}]`);
271
+ }
272
+ }
273
+ if (currentOptions.colors) {
274
+ const color = LEVEL_COLORS[level];
275
+ const icon = LEVEL_ICONS[level];
276
+ parts.push(`${color}${icon}${COLORS.reset}`);
277
+ } else {
278
+ parts.push(`[${level.toUpperCase()}]`);
279
+ }
280
+ if (currentOptions.colors && level === "error") {
281
+ parts.push(`${COLORS.red}${message}${COLORS.reset}`);
282
+ } else if (currentOptions.colors && level === "warn") {
283
+ parts.push(`${COLORS.yellow}${message}${COLORS.reset}`);
284
+ } else {
285
+ parts.push(message);
286
+ }
287
+ return parts.join(" ");
288
+ }
289
+ function shouldLog(level) {
290
+ return LOG_LEVELS[level] >= LOG_LEVELS[currentOptions.level];
291
+ }
292
+ function debug(messageKey, params) {
293
+ if (shouldLog("debug")) {
294
+ const message = getMessage(messageKey, params);
295
+ console.debug(formatMessage("debug", message));
296
+ }
297
+ }
298
+ function info(messageKey, params) {
299
+ if (shouldLog("info")) {
300
+ const message = getMessage(messageKey, params);
301
+ console.info(formatMessage("info", message));
302
+ }
303
+ }
304
+ function warn(messageKey, params) {
305
+ if (shouldLog("warn")) {
306
+ const message = getMessage(messageKey, params);
307
+ console.warn(formatMessage("warn", message));
308
+ }
309
+ }
310
+ function error(messageKey, params) {
311
+ if (shouldLog("error")) {
312
+ const message = getMessage(messageKey, params);
313
+ console.error(formatMessage("error", message));
314
+ }
315
+ }
316
+ function success(messageKey, params) {
317
+ if (shouldLog("info")) {
318
+ const message = getMessage(messageKey, params);
319
+ if (currentOptions.colors) {
320
+ console.info(`${COLORS.green}✓${COLORS.reset} ${message}`);
321
+ } else {
322
+ console.info(`[SUCCESS] ${message}`);
323
+ }
324
+ }
325
+ }
326
+
327
+ // src/core/config.ts
328
+ import { join as join2 } from "node:path";
329
+ var CONFIG_FILE = ".omccrc.json";
330
+ var CURRENT_CONFIG_VERSION = 1;
331
+ function getDefaultConfig() {
332
+ return {
333
+ configVersion: CURRENT_CONFIG_VERSION,
334
+ version: "0.0.0",
335
+ language: "en",
336
+ installedAt: "",
337
+ lastUpdated: "",
338
+ installedComponents: [],
339
+ componentVersions: {},
340
+ agents: {},
341
+ preferences: getDefaultPreferences(),
342
+ sourceRepo: "https://github.com/baekenough/baekgom-agents",
343
+ autoUpdate: {
344
+ enabled: false,
345
+ checkIntervalHours: 24,
346
+ autoApplyMinor: false
347
+ }
348
+ };
349
+ }
350
+ function getDefaultPreferences() {
351
+ return {
352
+ logLevel: "info",
353
+ colors: true,
354
+ showProgress: true,
355
+ confirmPrompts: true,
356
+ autoBackup: true
357
+ };
358
+ }
359
+ function getConfigPath(targetDir) {
360
+ return join2(targetDir, CONFIG_FILE);
361
+ }
362
+ async function loadConfig(targetDir) {
363
+ const configPath = getConfigPath(targetDir);
364
+ if (await fileExists(configPath)) {
365
+ try {
366
+ const config = await readJsonFile(configPath);
367
+ const merged = mergeConfig(getDefaultConfig(), config);
368
+ if (merged.configVersion < CURRENT_CONFIG_VERSION) {
369
+ const migrated = migrateConfig(merged);
370
+ await saveConfig(targetDir, migrated);
371
+ return migrated;
372
+ }
373
+ return merged;
374
+ } catch (err) {
375
+ warn("config.load_failed", { error: String(err) });
376
+ return getDefaultConfig();
377
+ }
378
+ }
379
+ debug("config.not_found", { path: configPath });
380
+ return getDefaultConfig();
381
+ }
382
+ async function saveConfig(targetDir, config) {
383
+ const configPath = getConfigPath(targetDir);
384
+ await ensureDirectory(targetDir);
385
+ config.lastUpdated = new Date().toISOString();
386
+ await writeJsonFile(configPath, config);
387
+ debug("config.saved", { path: configPath });
388
+ }
389
+ function mergeConfig(defaults, overrides) {
390
+ return {
391
+ ...defaults,
392
+ ...overrides,
393
+ preferences: overrides.preferences ? { ...defaults.preferences, ...overrides.preferences } : defaults.preferences,
394
+ autoUpdate: overrides.autoUpdate ? { ...defaults.autoUpdate, ...overrides.autoUpdate } : defaults.autoUpdate,
395
+ componentVersions: {
396
+ ...defaults.componentVersions,
397
+ ...overrides.componentVersions
398
+ },
399
+ agents: {
400
+ ...defaults.agents,
401
+ ...overrides.agents
402
+ }
403
+ };
404
+ }
405
+ function migrateConfig(config) {
406
+ const migrated = { ...config };
407
+ if (config.configVersion < 1) {
408
+ migrated.configVersion = 1;
409
+ migrated.preferences = getDefaultPreferences();
410
+ migrated.autoUpdate = {
411
+ enabled: false,
412
+ checkIntervalHours: 24,
413
+ autoApplyMinor: false
414
+ };
415
+ }
416
+ migrated.configVersion = CURRENT_CONFIG_VERSION;
417
+ return migrated;
418
+ }
419
+
420
+ // src/core/installer.ts
421
+ var DIRECTORY_STRUCTURE = [
422
+ ".claude",
423
+ ".claude/rules",
424
+ ".claude/hooks",
425
+ ".claude/contexts",
426
+ "agents",
427
+ "agents/master",
428
+ "agents/orchestrator",
429
+ "agents/manager",
430
+ "agents/system",
431
+ "agents/sw-engineer",
432
+ "agents/sw-architect",
433
+ "agents/backend-engineer",
434
+ "agents/infra-engineer",
435
+ "agents/qa-engineer",
436
+ "agents/tutor",
437
+ "skills",
438
+ "skills/development",
439
+ "skills/backend",
440
+ "skills/infrastructure",
441
+ "skills/system",
442
+ "skills/orchestration",
443
+ "guides",
444
+ "pipelines",
445
+ "pipelines/templates",
446
+ "pipelines/examples",
447
+ "commands"
448
+ ];
449
+ var COMPONENT_PATHS = {
450
+ "claude-md": "",
451
+ rules: ".claude/rules",
452
+ agents: "agents",
453
+ skills: "skills",
454
+ guides: "guides",
455
+ pipelines: "pipelines",
456
+ commands: "commands",
457
+ hooks: ".claude/hooks",
458
+ contexts: ".claude/contexts"
459
+ };
460
+ function getTemplateDir() {
461
+ const packageRoot = getPackageRoot();
462
+ return join3(packageRoot, "templates");
463
+ }
464
+ function createInstallResult(targetDir) {
465
+ return {
466
+ success: false,
467
+ installedPath: targetDir,
468
+ installedComponents: [],
469
+ skippedComponents: [],
470
+ backedUpPaths: [],
471
+ warnings: []
472
+ };
473
+ }
474
+ async function ensureTargetDirectory(targetDir) {
475
+ const targetExists = await fileExists(targetDir);
476
+ if (!targetExists) {
477
+ await ensureDirectory(targetDir);
478
+ }
479
+ }
480
+ async function handleBackup(targetDir, shouldBackup, result) {
481
+ if (!shouldBackup)
482
+ return;
483
+ const backupPaths = await backupExistingInstallation(targetDir);
484
+ result.backedUpPaths.push(...backupPaths);
485
+ if (backupPaths.length > 0) {
486
+ info("install.backup", { path: backupPaths[0] });
487
+ }
488
+ }
489
+ async function checkAndWarnExisting(targetDir, force, backup, result) {
490
+ if (force || backup)
491
+ return;
492
+ const existingPaths = await checkExistingPaths(targetDir);
493
+ if (existingPaths.length > 0) {
494
+ warn("install.exists");
495
+ result.warnings.push(`Existing files found: ${existingPaths.join(", ")}. Use --force to overwrite or --backup to backup first.`);
496
+ }
497
+ }
498
+ async function verifyTemplateDirectory() {
499
+ const templateDir = getTemplateDir();
500
+ if (!await fileExists(templateDir)) {
501
+ throw new Error(`Template directory not found: ${templateDir}`);
502
+ }
503
+ }
504
+ async function installAllComponents(targetDir, options, result) {
505
+ const components = options.components || getAllComponents();
506
+ for (const component of components) {
507
+ await installSingleComponent(targetDir, component, options, result);
508
+ }
509
+ }
510
+ async function installSingleComponent(targetDir, component, options, result) {
511
+ try {
512
+ const installed = await installComponent(targetDir, component, options);
513
+ if (installed) {
514
+ result.installedComponents.push(component);
515
+ } else {
516
+ result.skippedComponents.push(component);
517
+ }
518
+ } catch (err) {
519
+ const message = err instanceof Error ? err.message : String(err);
520
+ result.warnings.push(`Failed to install ${component}: ${message}`);
521
+ }
522
+ }
523
+ async function installClaudeMdWithTracking(targetDir, options, result) {
524
+ const language = options.language || "en";
525
+ const overwrite = !!(options.force || options.backup);
526
+ const installed = await installClaudeMd(targetDir, language, overwrite);
527
+ if (installed) {
528
+ result.installedComponents.push("claude-md");
529
+ } else {
530
+ result.skippedComponents.push("claude-md");
531
+ }
532
+ }
533
+ async function updateInstallConfig(targetDir, options, installedComponents) {
534
+ const config = await loadConfig(targetDir);
535
+ config.language = options.language || "en";
536
+ config.installedAt = new Date().toISOString();
537
+ config.installedComponents = installedComponents;
538
+ await saveConfig(targetDir, config);
539
+ }
540
+ async function install(options) {
541
+ const result = createInstallResult(options.targetDir);
542
+ try {
543
+ info("install.start", { targetDir: options.targetDir });
544
+ await ensureTargetDirectory(options.targetDir);
545
+ await handleBackup(options.targetDir, !!options.backup, result);
546
+ await checkAndWarnExisting(options.targetDir, !!options.force, !!options.backup, result);
547
+ await verifyTemplateDirectory();
548
+ await createDirectoryStructure(options.targetDir);
549
+ debug("install.directories_created");
550
+ await installAllComponents(options.targetDir, options, result);
551
+ await installClaudeMdWithTracking(options.targetDir, options, result);
552
+ await updateInstallConfig(options.targetDir, options, result.installedComponents);
553
+ result.success = true;
554
+ success("install.success");
555
+ } catch (err) {
556
+ const message = err instanceof Error ? err.message : String(err);
557
+ result.error = message;
558
+ error("install.failed", { error: message });
559
+ }
560
+ return result;
561
+ }
562
+ async function copyTemplates(targetDir, templatePath, options) {
563
+ const srcPath = resolveTemplatePath(templatePath);
564
+ const destPath = join3(targetDir, templatePath);
565
+ await copyDirectory(srcPath, destPath, {
566
+ overwrite: options?.overwrite ?? false,
567
+ preserveSymlinks: options?.preserveSymlinks ?? true,
568
+ preserveTimestamps: true
569
+ });
570
+ }
571
+ async function createDirectoryStructure(targetDir) {
572
+ for (const dir of DIRECTORY_STRUCTURE) {
573
+ const fullPath = join3(targetDir, dir);
574
+ await ensureDirectory(fullPath);
575
+ }
576
+ }
577
+ async function getTemplateManifest() {
578
+ const packageRoot = getPackageRoot();
579
+ const manifestPath = join3(packageRoot, "templates", "manifest.json");
580
+ if (await fileExists(manifestPath)) {
581
+ return readJsonFile(manifestPath);
582
+ }
583
+ return {
584
+ version: "0.0.0",
585
+ lastUpdated: new Date().toISOString(),
586
+ components: getAllComponents().map((name) => ({
587
+ name,
588
+ path: COMPONENT_PATHS[name],
589
+ description: `${name} component`,
590
+ files: 0
591
+ })),
592
+ source: "https://github.com/baekenough/baekgom-agents"
593
+ };
594
+ }
595
+ function getAllComponents() {
596
+ return ["rules", "agents", "skills", "guides", "pipelines", "commands", "hooks", "contexts"];
597
+ }
598
+ async function installComponent(targetDir, component, options) {
599
+ const templatePath = COMPONENT_PATHS[component];
600
+ if (!templatePath) {
601
+ return false;
602
+ }
603
+ const destPath = join3(targetDir, templatePath);
604
+ const destExists = await fileExists(destPath);
605
+ if (destExists && !options.force && !options.backup) {
606
+ debug("install.component_skipped", { component });
607
+ return false;
608
+ }
609
+ const srcPath = resolveTemplatePath(templatePath);
610
+ if (!await fileExists(srcPath)) {
611
+ warn("install.template_not_found", { component, path: srcPath });
612
+ return false;
613
+ }
614
+ await copyDirectory(srcPath, destPath, {
615
+ overwrite: !!(options.force || options.backup),
616
+ preserveSymlinks: true,
617
+ preserveTimestamps: true
618
+ });
619
+ debug("install.component_installed", { component });
620
+ return true;
621
+ }
622
+ async function installClaudeMd(targetDir, language, overwrite = false) {
623
+ const templateFile = `CLAUDE.md.${language}`;
624
+ const srcPath = resolveTemplatePath(templateFile);
625
+ const destPath = join3(targetDir, "CLAUDE.md");
626
+ if (!await fileExists(srcPath)) {
627
+ warn("install.claude_md_not_found", { language, path: srcPath });
628
+ return false;
629
+ }
630
+ const destExists = await fileExists(destPath);
631
+ if (destExists && !overwrite) {
632
+ debug("install.claude_md_skipped", { reason: "exists", language });
633
+ return false;
634
+ }
635
+ await fsCopyFile(srcPath, destPath);
636
+ debug("install.claude_md_installed", { language });
637
+ return true;
638
+ }
639
+ async function backupExisting(sourcePath, backupDir) {
640
+ const name = basename(sourcePath);
641
+ const backupPath = join3(backupDir, name);
642
+ await rename(sourcePath, backupPath);
643
+ return backupPath;
644
+ }
645
+ async function checkExistingPaths(targetDir) {
646
+ const pathsToCheck = [
647
+ "CLAUDE.md",
648
+ ".claude",
649
+ "agents",
650
+ "skills",
651
+ "guides",
652
+ "pipelines",
653
+ "commands"
654
+ ];
655
+ const existingPaths = [];
656
+ for (const relativePath of pathsToCheck) {
657
+ const fullPath = join3(targetDir, relativePath);
658
+ if (await fileExists(fullPath)) {
659
+ existingPaths.push(relativePath);
660
+ }
661
+ }
662
+ return existingPaths;
663
+ }
664
+ async function backupExistingInstallation(targetDir) {
665
+ const existingPaths = await checkExistingPaths(targetDir);
666
+ if (existingPaths.length === 0) {
667
+ return [];
668
+ }
669
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
670
+ const backupDir = join3(targetDir, `.claude-backup-${timestamp}`);
671
+ await ensureDirectory(backupDir);
672
+ const backedUpPaths = [];
673
+ for (const relativePath of existingPaths) {
674
+ const fullPath = join3(targetDir, relativePath);
675
+ try {
676
+ const backupPath = await backupExisting(fullPath, backupDir);
677
+ backedUpPaths.push(backupPath);
678
+ debug("install.backed_up", { from: relativePath, to: backupPath });
679
+ } catch (err) {
680
+ const message = err instanceof Error ? err.message : String(err);
681
+ warn("install.backup_failed", { path: relativePath, error: message });
682
+ }
683
+ }
684
+ return backedUpPaths.length > 0 ? [backupDir] : [];
685
+ }
686
+ // src/core/updater.ts
687
+ import { join as join4 } from "node:path";
688
+ var CUSTOMIZATION_MANIFEST_FILE = ".omcc-customizations.json";
689
+ function createUpdateResult() {
690
+ return {
691
+ success: false,
692
+ updatedComponents: [],
693
+ skippedComponents: [],
694
+ preservedFiles: [],
695
+ backedUpPaths: [],
696
+ previousVersion: "",
697
+ newVersion: "",
698
+ warnings: []
699
+ };
700
+ }
701
+ async function handleBackupIfRequested(targetDir, backup, result) {
702
+ if (!backup)
703
+ return;
704
+ const backupPath = await backupInstallation(targetDir);
705
+ result.backedUpPaths.push(backupPath);
706
+ info("update.backup_created", { path: backupPath });
707
+ }
708
+ async function processComponentUpdate(targetDir, component, updateCheck, customizations, options, result) {
709
+ const componentUpdate = updateCheck.updatableComponents.find((c) => c.name === component);
710
+ if (!componentUpdate && !options.force) {
711
+ result.skippedComponents.push(component);
712
+ return;
713
+ }
714
+ if (options.dryRun) {
715
+ debug("update.dry_run", { component });
716
+ result.updatedComponents.push(component);
717
+ return;
718
+ }
719
+ try {
720
+ const preserved = await updateComponent(targetDir, component, customizations, options);
721
+ result.updatedComponents.push(component);
722
+ result.preservedFiles.push(...preserved);
723
+ } catch (err) {
724
+ const message = err instanceof Error ? err.message : String(err);
725
+ result.warnings.push(`Failed to update ${component}: ${message}`);
726
+ result.skippedComponents.push(component);
727
+ }
728
+ }
729
+ async function updateAllComponents(targetDir, components, updateCheck, customizations, options, result) {
730
+ for (const component of components) {
731
+ await processComponentUpdate(targetDir, component, updateCheck, customizations, options, result);
732
+ }
733
+ }
734
+ async function update(options) {
735
+ const result = createUpdateResult();
736
+ try {
737
+ info("update.start", { targetDir: options.targetDir });
738
+ const config = await loadConfig(options.targetDir);
739
+ result.previousVersion = config.version;
740
+ const updateCheck = await checkForUpdates(options.targetDir);
741
+ result.newVersion = updateCheck.latestVersion;
742
+ if (!updateCheck.hasUpdates && !options.force) {
743
+ info("update.no_updates");
744
+ result.success = true;
745
+ result.skippedComponents = options.components || getAllUpdateComponents();
746
+ return result;
747
+ }
748
+ await handleBackupIfRequested(options.targetDir, !!options.backup, result);
749
+ const customizations = options.preserveCustomizations !== false ? await loadCustomizationManifest(options.targetDir) : null;
750
+ const components = options.components || getAllUpdateComponents();
751
+ await updateAllComponents(options.targetDir, components, updateCheck, customizations, options, result);
752
+ config.version = result.newVersion;
753
+ config.lastUpdated = new Date().toISOString();
754
+ await saveConfig(options.targetDir, config);
755
+ result.success = true;
756
+ success("update.success", { from: result.previousVersion, to: result.newVersion });
757
+ } catch (err) {
758
+ const message = err instanceof Error ? err.message : String(err);
759
+ result.error = message;
760
+ error("update.failed", { error: message });
761
+ }
762
+ return result;
763
+ }
764
+ async function checkForUpdates(targetDir) {
765
+ const config = await loadConfig(targetDir);
766
+ const currentVersion = config.version;
767
+ const latestVersion = await getLatestVersion();
768
+ const updatableComponents = [];
769
+ for (const component of getAllUpdateComponents()) {
770
+ const hasUpdate = await componentHasUpdate(targetDir, component, config);
771
+ if (hasUpdate) {
772
+ updatableComponents.push({
773
+ name: component,
774
+ currentVersion: config.componentVersions?.[component] || "0.0.0",
775
+ latestVersion
776
+ });
777
+ }
778
+ }
779
+ return {
780
+ hasUpdates: updatableComponents.length > 0 || currentVersion !== latestVersion,
781
+ currentVersion,
782
+ latestVersion,
783
+ updatableComponents,
784
+ checkedAt: new Date().toISOString()
785
+ };
786
+ }
787
+ async function applyUpdates(targetDir, updates) {
788
+ const fs = await import("node:fs/promises");
789
+ for (const update2 of updates) {
790
+ const fullPath = join4(targetDir, update2.path);
791
+ await ensureDirectory(join4(fullPath, ".."));
792
+ await fs.writeFile(fullPath, update2.content, "utf-8");
793
+ debug("update.file_applied", { path: update2.path });
794
+ }
795
+ }
796
+ async function preserveCustomizations(targetDir, customizations) {
797
+ const preserved = new Map;
798
+ const fs = await import("node:fs/promises");
799
+ for (const filePath of customizations) {
800
+ const fullPath = join4(targetDir, filePath);
801
+ if (await fileExists(fullPath)) {
802
+ const content = await fs.readFile(fullPath, "utf-8");
803
+ preserved.set(filePath, content);
804
+ }
805
+ }
806
+ return preserved;
807
+ }
808
+ function getAllUpdateComponents() {
809
+ return ["rules", "agents", "skills", "guides", "pipelines", "commands", "hooks", "contexts"];
810
+ }
811
+ async function getLatestVersion() {
812
+ const manifestPath = resolveTemplatePath("manifest.json");
813
+ if (await fileExists(manifestPath)) {
814
+ const manifest = await readJsonFile(manifestPath);
815
+ return manifest.version;
816
+ }
817
+ return "0.0.0";
818
+ }
819
+ async function componentHasUpdate(targetDir, component, config) {
820
+ const installedVersion = config.componentVersions?.[component];
821
+ if (!installedVersion) {
822
+ return true;
823
+ }
824
+ const latestVersion = await getLatestVersion();
825
+ return installedVersion !== latestVersion;
826
+ }
827
+ async function updateComponent(targetDir, component, customizations, options) {
828
+ const preservedFiles = [];
829
+ const componentPath = getComponentPath(component);
830
+ const srcPath = resolveTemplatePath(componentPath);
831
+ const destPath = join4(targetDir, componentPath);
832
+ if (customizations && options.preserveCustomizations !== false) {
833
+ const toPreserve = customizations.preserveFiles.filter((f) => f.startsWith(componentPath));
834
+ if (toPreserve.length > 0) {
835
+ const preserved = await preserveCustomizations(targetDir, toPreserve);
836
+ preservedFiles.push(...preserved.keys());
837
+ await copyDirectory(srcPath, destPath, { overwrite: true });
838
+ const fs = await import("node:fs/promises");
839
+ for (const [path, content] of preserved) {
840
+ await fs.writeFile(join4(targetDir, path), content, "utf-8");
841
+ }
842
+ } else {
843
+ await copyDirectory(srcPath, destPath, { overwrite: true });
844
+ }
845
+ } else {
846
+ await copyDirectory(srcPath, destPath, { overwrite: true });
847
+ }
848
+ debug("update.component_updated", { component });
849
+ return preservedFiles;
850
+ }
851
+ function getComponentPath(component) {
852
+ const paths = {
853
+ rules: ".claude/rules",
854
+ agents: "agents",
855
+ skills: "skills",
856
+ guides: "guides",
857
+ pipelines: "pipelines",
858
+ commands: "commands",
859
+ hooks: ".claude/hooks",
860
+ contexts: ".claude/contexts"
861
+ };
862
+ return paths[component];
863
+ }
864
+ async function backupInstallation(targetDir) {
865
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
866
+ const backupDir = join4(targetDir, `.omcc-backup-${timestamp}`);
867
+ const fs = await import("node:fs/promises");
868
+ await ensureDirectory(backupDir);
869
+ const dirsToBackup = [".claude", "agents", "skills", "guides", "pipelines", "commands"];
870
+ for (const dir of dirsToBackup) {
871
+ const srcPath = join4(targetDir, dir);
872
+ if (await fileExists(srcPath)) {
873
+ const destPath = join4(backupDir, dir);
874
+ await copyDirectory(srcPath, destPath, { overwrite: true });
875
+ }
876
+ }
877
+ const claudeMdPath = join4(targetDir, "CLAUDE.md");
878
+ if (await fileExists(claudeMdPath)) {
879
+ await fs.copyFile(claudeMdPath, join4(backupDir, "CLAUDE.md"));
880
+ }
881
+ return backupDir;
882
+ }
883
+ async function loadCustomizationManifest(targetDir) {
884
+ const manifestPath = join4(targetDir, CUSTOMIZATION_MANIFEST_FILE);
885
+ if (await fileExists(manifestPath)) {
886
+ return readJsonFile(manifestPath);
887
+ }
888
+ return null;
889
+ }
890
+
891
+ // src/index.ts
892
+ var VERSION = "0.0.0";
893
+ var src_default = {
894
+ VERSION
895
+ };
896
+ export {
897
+ writeJsonFile,
898
+ warn,
899
+ update,
900
+ success,
901
+ setLogLevel,
902
+ setLocale,
903
+ saveConfig,
904
+ resolveTemplatePath,
905
+ readJsonFile,
906
+ preserveCustomizations,
907
+ mergeConfig,
908
+ loadConfig,
909
+ install,
910
+ info,
911
+ getTemplateManifest,
912
+ getPackageRoot,
913
+ getDefaultConfig,
914
+ getConfigPath,
915
+ fileExists,
916
+ error,
917
+ ensureDirectory,
918
+ src_default as default,
919
+ debug,
920
+ createLogger,
921
+ createDirectoryStructure,
922
+ copyTemplates,
923
+ copyDirectory,
924
+ checkForUpdates,
925
+ applyUpdates,
926
+ VERSION
927
+ };