@iloom/cli 0.1.14

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 (161) hide show
  1. package/LICENSE +33 -0
  2. package/README.md +711 -0
  3. package/dist/ClaudeContextManager-XOSXQ67R.js +13 -0
  4. package/dist/ClaudeContextManager-XOSXQ67R.js.map +1 -0
  5. package/dist/ClaudeService-YSZ6EXWP.js +12 -0
  6. package/dist/ClaudeService-YSZ6EXWP.js.map +1 -0
  7. package/dist/GitHubService-F7Z3XJOS.js +11 -0
  8. package/dist/GitHubService-F7Z3XJOS.js.map +1 -0
  9. package/dist/LoomLauncher-MODG2SEM.js +263 -0
  10. package/dist/LoomLauncher-MODG2SEM.js.map +1 -0
  11. package/dist/NeonProvider-PAGPUH7F.js +12 -0
  12. package/dist/NeonProvider-PAGPUH7F.js.map +1 -0
  13. package/dist/PromptTemplateManager-7FINLRDE.js +9 -0
  14. package/dist/PromptTemplateManager-7FINLRDE.js.map +1 -0
  15. package/dist/SettingsManager-VAZF26S2.js +19 -0
  16. package/dist/SettingsManager-VAZF26S2.js.map +1 -0
  17. package/dist/SettingsMigrationManager-MTQIMI54.js +146 -0
  18. package/dist/SettingsMigrationManager-MTQIMI54.js.map +1 -0
  19. package/dist/add-issue-22JBNOML.js +54 -0
  20. package/dist/add-issue-22JBNOML.js.map +1 -0
  21. package/dist/agents/iloom-issue-analyze-and-plan.md +580 -0
  22. package/dist/agents/iloom-issue-analyzer.md +290 -0
  23. package/dist/agents/iloom-issue-complexity-evaluator.md +224 -0
  24. package/dist/agents/iloom-issue-enhancer.md +266 -0
  25. package/dist/agents/iloom-issue-implementer.md +262 -0
  26. package/dist/agents/iloom-issue-planner.md +358 -0
  27. package/dist/agents/iloom-issue-reviewer.md +63 -0
  28. package/dist/chunk-2ZPFJQ3B.js +63 -0
  29. package/dist/chunk-2ZPFJQ3B.js.map +1 -0
  30. package/dist/chunk-37DYYFVK.js +29 -0
  31. package/dist/chunk-37DYYFVK.js.map +1 -0
  32. package/dist/chunk-BLCTGFZN.js +121 -0
  33. package/dist/chunk-BLCTGFZN.js.map +1 -0
  34. package/dist/chunk-CP2NU2JC.js +545 -0
  35. package/dist/chunk-CP2NU2JC.js.map +1 -0
  36. package/dist/chunk-CWR2SANQ.js +39 -0
  37. package/dist/chunk-CWR2SANQ.js.map +1 -0
  38. package/dist/chunk-F3XBU2R7.js +110 -0
  39. package/dist/chunk-F3XBU2R7.js.map +1 -0
  40. package/dist/chunk-GEHQXLEI.js +130 -0
  41. package/dist/chunk-GEHQXLEI.js.map +1 -0
  42. package/dist/chunk-GYCR2LOU.js +143 -0
  43. package/dist/chunk-GYCR2LOU.js.map +1 -0
  44. package/dist/chunk-GZP4UGGM.js +48 -0
  45. package/dist/chunk-GZP4UGGM.js.map +1 -0
  46. package/dist/chunk-H4E4THUZ.js +55 -0
  47. package/dist/chunk-H4E4THUZ.js.map +1 -0
  48. package/dist/chunk-HPJJSYNS.js +644 -0
  49. package/dist/chunk-HPJJSYNS.js.map +1 -0
  50. package/dist/chunk-JBH2ZYYZ.js +220 -0
  51. package/dist/chunk-JBH2ZYYZ.js.map +1 -0
  52. package/dist/chunk-JNKJ7NJV.js +78 -0
  53. package/dist/chunk-JNKJ7NJV.js.map +1 -0
  54. package/dist/chunk-JQ7VOSTC.js +437 -0
  55. package/dist/chunk-JQ7VOSTC.js.map +1 -0
  56. package/dist/chunk-KQDEK2ZW.js +199 -0
  57. package/dist/chunk-KQDEK2ZW.js.map +1 -0
  58. package/dist/chunk-O2QWO64Z.js +179 -0
  59. package/dist/chunk-O2QWO64Z.js.map +1 -0
  60. package/dist/chunk-OC4H6HJD.js +248 -0
  61. package/dist/chunk-OC4H6HJD.js.map +1 -0
  62. package/dist/chunk-PR7FKQBG.js +120 -0
  63. package/dist/chunk-PR7FKQBG.js.map +1 -0
  64. package/dist/chunk-PXZBAC2M.js +250 -0
  65. package/dist/chunk-PXZBAC2M.js.map +1 -0
  66. package/dist/chunk-QEPVTTHD.js +383 -0
  67. package/dist/chunk-QEPVTTHD.js.map +1 -0
  68. package/dist/chunk-RSRO7564.js +203 -0
  69. package/dist/chunk-RSRO7564.js.map +1 -0
  70. package/dist/chunk-SJUQ2NDR.js +146 -0
  71. package/dist/chunk-SJUQ2NDR.js.map +1 -0
  72. package/dist/chunk-SPYPLHMK.js +177 -0
  73. package/dist/chunk-SPYPLHMK.js.map +1 -0
  74. package/dist/chunk-SSCQCCJ7.js +75 -0
  75. package/dist/chunk-SSCQCCJ7.js.map +1 -0
  76. package/dist/chunk-SSR5AVRJ.js +41 -0
  77. package/dist/chunk-SSR5AVRJ.js.map +1 -0
  78. package/dist/chunk-T7QPXANZ.js +315 -0
  79. package/dist/chunk-T7QPXANZ.js.map +1 -0
  80. package/dist/chunk-U3WU5OWO.js +203 -0
  81. package/dist/chunk-U3WU5OWO.js.map +1 -0
  82. package/dist/chunk-W3DQTW63.js +124 -0
  83. package/dist/chunk-W3DQTW63.js.map +1 -0
  84. package/dist/chunk-WKEWRSDB.js +151 -0
  85. package/dist/chunk-WKEWRSDB.js.map +1 -0
  86. package/dist/chunk-Y7SAGNUT.js +66 -0
  87. package/dist/chunk-Y7SAGNUT.js.map +1 -0
  88. package/dist/chunk-YETJNRQM.js +39 -0
  89. package/dist/chunk-YETJNRQM.js.map +1 -0
  90. package/dist/chunk-YYSKGAZT.js +384 -0
  91. package/dist/chunk-YYSKGAZT.js.map +1 -0
  92. package/dist/chunk-ZZZWQGTS.js +169 -0
  93. package/dist/chunk-ZZZWQGTS.js.map +1 -0
  94. package/dist/claude-7LUVDZZ4.js +17 -0
  95. package/dist/claude-7LUVDZZ4.js.map +1 -0
  96. package/dist/cleanup-3LUWPSM7.js +412 -0
  97. package/dist/cleanup-3LUWPSM7.js.map +1 -0
  98. package/dist/cli-overrides-XFZWY7CM.js +16 -0
  99. package/dist/cli-overrides-XFZWY7CM.js.map +1 -0
  100. package/dist/cli.js +603 -0
  101. package/dist/cli.js.map +1 -0
  102. package/dist/color-ZVALX37U.js +21 -0
  103. package/dist/color-ZVALX37U.js.map +1 -0
  104. package/dist/enhance-XJIQHVPD.js +166 -0
  105. package/dist/enhance-XJIQHVPD.js.map +1 -0
  106. package/dist/env-MDFL4ZXL.js +23 -0
  107. package/dist/env-MDFL4ZXL.js.map +1 -0
  108. package/dist/feedback-23CLXKFT.js +158 -0
  109. package/dist/feedback-23CLXKFT.js.map +1 -0
  110. package/dist/finish-CY4CIH6O.js +1608 -0
  111. package/dist/finish-CY4CIH6O.js.map +1 -0
  112. package/dist/git-LVRZ57GJ.js +43 -0
  113. package/dist/git-LVRZ57GJ.js.map +1 -0
  114. package/dist/ignite-WXEF2ID5.js +359 -0
  115. package/dist/ignite-WXEF2ID5.js.map +1 -0
  116. package/dist/index.d.ts +1341 -0
  117. package/dist/index.js +3058 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/init-RHACUR4E.js +123 -0
  120. package/dist/init-RHACUR4E.js.map +1 -0
  121. package/dist/installation-detector-VARGFFRZ.js +11 -0
  122. package/dist/installation-detector-VARGFFRZ.js.map +1 -0
  123. package/dist/logger-MKYH4UDV.js +12 -0
  124. package/dist/logger-MKYH4UDV.js.map +1 -0
  125. package/dist/mcp/chunk-6SDFJ42P.js +62 -0
  126. package/dist/mcp/chunk-6SDFJ42P.js.map +1 -0
  127. package/dist/mcp/claude-YHHHLSXH.js +249 -0
  128. package/dist/mcp/claude-YHHHLSXH.js.map +1 -0
  129. package/dist/mcp/color-QS5BFCNN.js +168 -0
  130. package/dist/mcp/color-QS5BFCNN.js.map +1 -0
  131. package/dist/mcp/github-comment-server.js +165 -0
  132. package/dist/mcp/github-comment-server.js.map +1 -0
  133. package/dist/mcp/terminal-SDCMDVD7.js +202 -0
  134. package/dist/mcp/terminal-SDCMDVD7.js.map +1 -0
  135. package/dist/open-X6BTENPV.js +278 -0
  136. package/dist/open-X6BTENPV.js.map +1 -0
  137. package/dist/prompt-ANTQWHUF.js +13 -0
  138. package/dist/prompt-ANTQWHUF.js.map +1 -0
  139. package/dist/prompts/issue-prompt.txt +230 -0
  140. package/dist/prompts/pr-prompt.txt +35 -0
  141. package/dist/prompts/regular-prompt.txt +14 -0
  142. package/dist/run-2JCPQAX3.js +278 -0
  143. package/dist/run-2JCPQAX3.js.map +1 -0
  144. package/dist/schema/settings.schema.json +221 -0
  145. package/dist/start-LWVRBJ6S.js +982 -0
  146. package/dist/start-LWVRBJ6S.js.map +1 -0
  147. package/dist/terminal-3D6TUAKJ.js +16 -0
  148. package/dist/terminal-3D6TUAKJ.js.map +1 -0
  149. package/dist/test-git-XPF4SZXJ.js +52 -0
  150. package/dist/test-git-XPF4SZXJ.js.map +1 -0
  151. package/dist/test-prefix-XGFXFAYN.js +68 -0
  152. package/dist/test-prefix-XGFXFAYN.js.map +1 -0
  153. package/dist/test-tabs-JRKY3QMM.js +69 -0
  154. package/dist/test-tabs-JRKY3QMM.js.map +1 -0
  155. package/dist/test-webserver-M2I3EV4J.js +62 -0
  156. package/dist/test-webserver-M2I3EV4J.js.map +1 -0
  157. package/dist/update-3ZT2XX2G.js +79 -0
  158. package/dist/update-3ZT2XX2G.js.map +1 -0
  159. package/dist/update-notifier-QSSEB5KC.js +11 -0
  160. package/dist/update-notifier-QSSEB5KC.js.map +1 -0
  161. package/package.json +113 -0
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ ClaudeContextManager
4
+ } from "./chunk-Y7SAGNUT.js";
5
+ import "./chunk-WKEWRSDB.js";
6
+ import "./chunk-PXZBAC2M.js";
7
+ import "./chunk-F3XBU2R7.js";
8
+ import "./chunk-JBH2ZYYZ.js";
9
+ import "./chunk-GEHQXLEI.js";
10
+ export {
11
+ ClaudeContextManager
12
+ };
13
+ //# sourceMappingURL=ClaudeContextManager-XOSXQ67R.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ ClaudeService
4
+ } from "./chunk-WKEWRSDB.js";
5
+ import "./chunk-PXZBAC2M.js";
6
+ import "./chunk-F3XBU2R7.js";
7
+ import "./chunk-JBH2ZYYZ.js";
8
+ import "./chunk-GEHQXLEI.js";
9
+ export {
10
+ ClaudeService
11
+ };
12
+ //# sourceMappingURL=ClaudeService-YSZ6EXWP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ GitHubService
4
+ } from "./chunk-T7QPXANZ.js";
5
+ import "./chunk-KQDEK2ZW.js";
6
+ import "./chunk-JNKJ7NJV.js";
7
+ import "./chunk-GEHQXLEI.js";
8
+ export {
9
+ GitHubService
10
+ };
11
+ //# sourceMappingURL=GitHubService-F7Z3XJOS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,263 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ getDevServerLaunchCommand
4
+ } from "./chunk-GZP4UGGM.js";
5
+ import "./chunk-BLCTGFZN.js";
6
+ import {
7
+ openMultipleTerminalWindows,
8
+ openTerminalWindow
9
+ } from "./chunk-RSRO7564.js";
10
+ import {
11
+ generateColorFromBranchName
12
+ } from "./chunk-ZZZWQGTS.js";
13
+ import {
14
+ ClaudeContextManager
15
+ } from "./chunk-Y7SAGNUT.js";
16
+ import "./chunk-WKEWRSDB.js";
17
+ import "./chunk-PXZBAC2M.js";
18
+ import "./chunk-F3XBU2R7.js";
19
+ import "./chunk-JBH2ZYYZ.js";
20
+ import {
21
+ logger
22
+ } from "./chunk-GEHQXLEI.js";
23
+
24
+ // src/lib/LoomLauncher.ts
25
+ import { existsSync } from "fs";
26
+ import { join } from "path";
27
+
28
+ // src/utils/vscode.ts
29
+ import { execa } from "execa";
30
+ async function isVSCodeAvailable() {
31
+ try {
32
+ await execa("command", ["-v", "code"], {
33
+ shell: true,
34
+ timeout: 5e3
35
+ });
36
+ return true;
37
+ } catch (error) {
38
+ logger.debug("VSCode CLI not available", { error });
39
+ return false;
40
+ }
41
+ }
42
+ async function openVSCodeWindow(workspacePath) {
43
+ const available = await isVSCodeAvailable();
44
+ if (!available) {
45
+ throw new Error(
46
+ `VSCode is not available. Please install VSCode and ensure the "code" command is in your PATH.
47
+ Install command-line tools: Open VSCode > Command Palette > "Shell Command: Install 'code' command in PATH"`
48
+ );
49
+ }
50
+ try {
51
+ await execa("code", [workspacePath]);
52
+ logger.debug(`Opened VSCode for workspace: ${workspacePath}`);
53
+ } catch (error) {
54
+ throw new Error(
55
+ `Failed to open VSCode: ${error instanceof Error ? error.message : "Unknown error"}`
56
+ );
57
+ }
58
+ }
59
+
60
+ // src/lib/LoomLauncher.ts
61
+ var LoomLauncher = class {
62
+ constructor(claudeContext) {
63
+ this.claudeContext = claudeContext ?? new ClaudeContextManager();
64
+ }
65
+ /**
66
+ * Launch loom components based on individual flags
67
+ */
68
+ async launchLoom(options) {
69
+ const { enableClaude, enableCode, enableDevServer, enableTerminal } = options;
70
+ logger.debug(`Launching loom components: Claude=${enableClaude}, Code=${enableCode}, DevServer=${enableDevServer}, Terminal=${enableTerminal}`);
71
+ const launchPromises = [];
72
+ if (enableCode) {
73
+ logger.debug("Launching VSCode");
74
+ launchPromises.push(this.launchVSCode(options));
75
+ }
76
+ const terminalsToLaunch = [];
77
+ if (enableDevServer) {
78
+ terminalsToLaunch.push({
79
+ type: "devServer",
80
+ options: await this.buildDevServerTerminalOptions(options)
81
+ });
82
+ }
83
+ if (enableTerminal) {
84
+ terminalsToLaunch.push({
85
+ type: "terminal",
86
+ options: this.buildStandaloneTerminalOptions(options)
87
+ });
88
+ }
89
+ if (enableClaude) {
90
+ terminalsToLaunch.push({
91
+ type: "claude",
92
+ options: await this.buildClaudeTerminalOptions(options)
93
+ });
94
+ }
95
+ if (terminalsToLaunch.length > 1) {
96
+ logger.debug(`Launching ${terminalsToLaunch.length} terminals in single window`);
97
+ launchPromises.push(this.launchMultipleTerminals(terminalsToLaunch, options));
98
+ } else if (terminalsToLaunch.length === 1) {
99
+ const terminal = terminalsToLaunch[0];
100
+ if (!terminal) {
101
+ throw new Error("Terminal configuration is undefined");
102
+ }
103
+ const terminalType = terminal.type;
104
+ logger.debug(`Launching single ${terminalType} terminal`);
105
+ if (terminalType === "claude") {
106
+ launchPromises.push(this.launchClaudeTerminal(options));
107
+ } else if (terminalType === "devServer") {
108
+ launchPromises.push(this.launchDevServerTerminal(options));
109
+ } else {
110
+ launchPromises.push(this.launchStandaloneTerminal(options));
111
+ }
112
+ }
113
+ await Promise.all(launchPromises);
114
+ logger.success("loom launched successfully");
115
+ }
116
+ /**
117
+ * Launch VSCode
118
+ */
119
+ async launchVSCode(options) {
120
+ await openVSCodeWindow(options.worktreePath);
121
+ logger.info("VSCode opened");
122
+ }
123
+ /**
124
+ * Launch Claude terminal
125
+ */
126
+ async launchClaudeTerminal(options) {
127
+ await this.claudeContext.launchWithContext({
128
+ workspacePath: options.worktreePath,
129
+ type: options.workflowType,
130
+ identifier: options.identifier,
131
+ branchName: options.branchName,
132
+ ...options.title && { title: options.title },
133
+ ...options.port !== void 0 && { port: options.port },
134
+ oneShot: options.oneShot ?? "default",
135
+ ...options.setArguments && { setArguments: options.setArguments },
136
+ ...options.executablePath && { executablePath: options.executablePath }
137
+ });
138
+ logger.info("Claude terminal opened");
139
+ }
140
+ /**
141
+ * Launch dev server terminal
142
+ */
143
+ async launchDevServerTerminal(options) {
144
+ const colorData = generateColorFromBranchName(options.branchName);
145
+ const devServerCommand = await getDevServerLaunchCommand(
146
+ options.worktreePath,
147
+ options.port,
148
+ options.capabilities
149
+ );
150
+ await openTerminalWindow({
151
+ workspacePath: options.worktreePath,
152
+ command: devServerCommand,
153
+ backgroundColor: colorData.rgb,
154
+ includeEnvSetup: existsSync(join(options.worktreePath, ".env")),
155
+ includePortExport: options.capabilities.includes("web"),
156
+ ...options.port !== void 0 && { port: options.port }
157
+ });
158
+ logger.info("Dev server terminal opened");
159
+ }
160
+ /**
161
+ * Launch standalone terminal (no command, just workspace with env vars)
162
+ */
163
+ async launchStandaloneTerminal(options) {
164
+ const colorData = generateColorFromBranchName(options.branchName);
165
+ await openTerminalWindow({
166
+ workspacePath: options.worktreePath,
167
+ backgroundColor: colorData.rgb,
168
+ includeEnvSetup: existsSync(join(options.worktreePath, ".env")),
169
+ includePortExport: options.capabilities.includes("web"),
170
+ ...options.port !== void 0 && { port: options.port }
171
+ });
172
+ logger.info("Standalone terminal opened");
173
+ }
174
+ /**
175
+ * Build terminal options for Claude
176
+ */
177
+ async buildClaudeTerminalOptions(options) {
178
+ const colorData = generateColorFromBranchName(options.branchName);
179
+ const hasEnvFile = existsSync(join(options.worktreePath, ".env"));
180
+ const claudeTitle = `Claude - ${this.formatIdentifier(options.workflowType, options.identifier)}`;
181
+ const executable = options.executablePath ?? "iloom";
182
+ let claudeCommand = `${executable} spin`;
183
+ if (options.oneShot !== void 0 && options.oneShot !== "default") {
184
+ claudeCommand += ` --one-shot=${options.oneShot}`;
185
+ }
186
+ if (options.setArguments && options.setArguments.length > 0) {
187
+ for (const setArg of options.setArguments) {
188
+ claudeCommand += ` --set ${setArg}`;
189
+ }
190
+ }
191
+ return {
192
+ workspacePath: options.worktreePath,
193
+ command: claudeCommand,
194
+ backgroundColor: colorData.rgb,
195
+ title: claudeTitle,
196
+ includeEnvSetup: hasEnvFile,
197
+ ...options.port !== void 0 && { port: options.port, includePortExport: true }
198
+ };
199
+ }
200
+ /**
201
+ * Build terminal options for dev server
202
+ */
203
+ async buildDevServerTerminalOptions(options) {
204
+ const colorData = generateColorFromBranchName(options.branchName);
205
+ const devServerCommand = await getDevServerLaunchCommand(
206
+ options.worktreePath,
207
+ options.port,
208
+ options.capabilities
209
+ );
210
+ const hasEnvFile = existsSync(join(options.worktreePath, ".env"));
211
+ const devServerTitle = `Dev Server - ${this.formatIdentifier(options.workflowType, options.identifier)}`;
212
+ return {
213
+ workspacePath: options.worktreePath,
214
+ command: devServerCommand,
215
+ backgroundColor: colorData.rgb,
216
+ title: devServerTitle,
217
+ includeEnvSetup: hasEnvFile,
218
+ includePortExport: options.capabilities.includes("web"),
219
+ ...options.port !== void 0 && { port: options.port }
220
+ };
221
+ }
222
+ /**
223
+ * Build terminal options for standalone terminal (no command)
224
+ */
225
+ buildStandaloneTerminalOptions(options) {
226
+ const colorData = generateColorFromBranchName(options.branchName);
227
+ const hasEnvFile = existsSync(join(options.worktreePath, ".env"));
228
+ const terminalTitle = `Terminal - ${this.formatIdentifier(options.workflowType, options.identifier)}`;
229
+ return {
230
+ workspacePath: options.worktreePath,
231
+ backgroundColor: colorData.rgb,
232
+ title: terminalTitle,
233
+ includeEnvSetup: hasEnvFile,
234
+ includePortExport: options.capabilities.includes("web"),
235
+ ...options.port !== void 0 && { port: options.port }
236
+ };
237
+ }
238
+ /**
239
+ * Launch multiple terminals (2+) as tabs in single window
240
+ */
241
+ async launchMultipleTerminals(terminals, _options) {
242
+ const terminalOptions = terminals.map((t) => t.options);
243
+ await openMultipleTerminalWindows(terminalOptions);
244
+ const terminalTypes = terminals.map((t) => t.type).join(" + ");
245
+ logger.info(`Multiple terminals opened: ${terminalTypes}`);
246
+ }
247
+ /**
248
+ * Format identifier for terminal tab titles
249
+ */
250
+ formatIdentifier(workflowType, identifier) {
251
+ if (workflowType === "issue") {
252
+ return `Issue #${identifier}`;
253
+ } else if (workflowType === "pr") {
254
+ return `PR #${identifier}`;
255
+ } else {
256
+ return `Branch: ${identifier}`;
257
+ }
258
+ }
259
+ };
260
+ export {
261
+ LoomLauncher
262
+ };
263
+ //# sourceMappingURL=LoomLauncher-MODG2SEM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/LoomLauncher.ts","../src/utils/vscode.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { openTerminalWindow, openMultipleTerminalWindows } from '../utils/terminal.js'\nimport type { TerminalWindowOptions } from '../utils/terminal.js'\nimport { openVSCodeWindow } from '../utils/vscode.js'\nimport { getDevServerLaunchCommand } from '../utils/dev-server.js'\nimport { generateColorFromBranchName } from '../utils/color.js'\nimport { logger } from '../utils/logger.js'\nimport { ClaudeContextManager } from './ClaudeContextManager.js'\nimport type { Capability } from '../types/loom.js'\n\nexport interface LaunchLoomOptions {\n\tenableClaude: boolean\n\tenableCode: boolean\n\tenableDevServer: boolean\n\tenableTerminal: boolean\n\tworktreePath: string\n\tbranchName: string\n\tport?: number\n\tcapabilities: Capability[]\n\tworkflowType: 'issue' | 'pr' | 'regular'\n\tidentifier: string | number\n\ttitle?: string\n\toneShot?: import('../types/index.js').OneShotMode\n\tsetArguments?: string[] // Raw --set arguments to forward\n\texecutablePath?: string // Executable path to use for spin command\n}\n\n/**\n * LoomLauncher orchestrates opening loom components\n */\nexport class LoomLauncher {\n\tprivate claudeContext: ClaudeContextManager\n\n\tconstructor(claudeContext?: ClaudeContextManager) {\n\t\tthis.claudeContext = claudeContext ?? new ClaudeContextManager()\n\t}\n\n\t/**\n\t * Launch loom components based on individual flags\n\t */\n\tasync launchLoom(options: LaunchLoomOptions): Promise<void> {\n\t\tconst { enableClaude, enableCode, enableDevServer, enableTerminal } = options\n\n\t\tlogger.debug(`Launching loom components: Claude=${enableClaude}, Code=${enableCode}, DevServer=${enableDevServer}, Terminal=${enableTerminal}`)\n\n\t\tconst launchPromises: Promise<void>[] = []\n\n\t\t// Launch VSCode if enabled\n\t\tif (enableCode) {\n\t\t\tlogger.debug('Launching VSCode')\n\t\t\tlaunchPromises.push(this.launchVSCode(options))\n\t\t}\n\n\t\t// Build array of terminals to launch\n\t\tconst terminalsToLaunch: Array<{\n\t\t\ttype: 'claude' | 'devServer' | 'terminal'\n\t\t\toptions: TerminalWindowOptions\n\t\t}> = []\n\n\t\tif (enableDevServer) {\n\t\t\tterminalsToLaunch.push({\n\t\t\t\ttype: 'devServer',\n\t\t\t\toptions: await this.buildDevServerTerminalOptions(options),\n\t\t\t})\n\t\t}\n\n\t\tif (enableTerminal) {\n\t\t\tterminalsToLaunch.push({\n\t\t\t\ttype: 'terminal',\n\t\t\t\toptions: this.buildStandaloneTerminalOptions(options),\n\t\t\t})\n\t\t}\n\n\t\tif (enableClaude) {\n\t\t\tterminalsToLaunch.push({\n\t\t\t\ttype: 'claude',\n\t\t\t\toptions: await this.buildClaudeTerminalOptions(options),\n\t\t\t})\n\t\t}\n\n\t\t// Launch terminals based on count\n\t\tif (terminalsToLaunch.length > 1) {\n\t\t\t// Multiple terminals - launch as tabs in single window\n\t\t\tlogger.debug(`Launching ${terminalsToLaunch.length} terminals in single window`)\n\t\t\tlaunchPromises.push(this.launchMultipleTerminals(terminalsToLaunch, options))\n\t\t} else if (terminalsToLaunch.length === 1) {\n\t\t\t// Single terminal - launch standalone\n\t\t\tconst terminal = terminalsToLaunch[0]\n\t\t\tif (!terminal) {\n\t\t\t\tthrow new Error('Terminal configuration is undefined')\n\t\t\t}\n\t\t\tconst terminalType = terminal.type\n\t\t\tlogger.debug(`Launching single ${terminalType} terminal`)\n\n\t\t\tif (terminalType === 'claude') {\n\t\t\t\tlaunchPromises.push(this.launchClaudeTerminal(options))\n\t\t\t} else if (terminalType === 'devServer') {\n\t\t\t\tlaunchPromises.push(this.launchDevServerTerminal(options))\n\t\t\t} else {\n\t\t\t\tlaunchPromises.push(this.launchStandaloneTerminal(options))\n\t\t\t}\n\t\t}\n\n\t\t// Wait for all components to launch\n\t\tawait Promise.all(launchPromises)\n\n\t\tlogger.success('loom launched successfully')\n\t}\n\n\t/**\n\t * Launch VSCode\n\t */\n\tprivate async launchVSCode(options: LaunchLoomOptions): Promise<void> {\n\t\tawait openVSCodeWindow(options.worktreePath)\n\t\tlogger.info('VSCode opened')\n\t}\n\n\t/**\n\t * Launch Claude terminal\n\t */\n\tprivate async launchClaudeTerminal(options: LaunchLoomOptions): Promise<void> {\n\t\tawait this.claudeContext.launchWithContext({\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\ttype: options.workflowType,\n\t\t\tidentifier: options.identifier,\n\t\t\tbranchName: options.branchName,\n\t\t\t...(options.title && { title: options.title }),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t\toneShot: options.oneShot ?? 'default',\n\t\t\t...(options.setArguments && { setArguments: options.setArguments }),\n\t\t\t...(options.executablePath && { executablePath: options.executablePath }),\n\t\t})\n\t\tlogger.info('Claude terminal opened')\n\t}\n\n\t/**\n\t * Launch dev server terminal\n\t */\n\tprivate async launchDevServerTerminal(options: LaunchLoomOptions): Promise<void> {\n\t\tconst colorData = generateColorFromBranchName(options.branchName)\n\t\tconst devServerCommand = await getDevServerLaunchCommand(\n\t\t\toptions.worktreePath,\n\t\t\toptions.port,\n\t\t\toptions.capabilities\n\t\t)\n\n\t\tawait openTerminalWindow({\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tcommand: devServerCommand,\n\t\t\tbackgroundColor: colorData.rgb,\n\t\t\tincludeEnvSetup: existsSync(join(options.worktreePath, '.env')),\n\t\t\tincludePortExport: options.capabilities.includes('web'),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t})\n\t\tlogger.info('Dev server terminal opened')\n\t}\n\n\t/**\n\t * Launch standalone terminal (no command, just workspace with env vars)\n\t */\n\tprivate async launchStandaloneTerminal(options: LaunchLoomOptions): Promise<void> {\n\t\tconst colorData = generateColorFromBranchName(options.branchName)\n\n\t\tawait openTerminalWindow({\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tbackgroundColor: colorData.rgb,\n\t\t\tincludeEnvSetup: existsSync(join(options.worktreePath, '.env')),\n\t\t\tincludePortExport: options.capabilities.includes('web'),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t})\n\t\tlogger.info('Standalone terminal opened')\n\t}\n\n\t/**\n\t * Build terminal options for Claude\n\t */\n\tprivate async buildClaudeTerminalOptions(\n\t\toptions: LaunchLoomOptions\n\t): Promise<TerminalWindowOptions> {\n\t\tconst colorData = generateColorFromBranchName(options.branchName)\n\t\tconst hasEnvFile = existsSync(join(options.worktreePath, '.env'))\n\t\tconst claudeTitle = `Claude - ${this.formatIdentifier(options.workflowType, options.identifier)}`\n\n\t\tconst executable = options.executablePath ?? 'iloom'\n\t\tlet claudeCommand = `${executable} spin`\n\t\tif (options.oneShot !== undefined && options.oneShot !== 'default') {\n\t\t\tclaudeCommand += ` --one-shot=${options.oneShot}`\n\t\t}\n\t\tif (options.setArguments && options.setArguments.length > 0) {\n\t\t\tfor (const setArg of options.setArguments) {\n\t\t\t\tclaudeCommand += ` --set ${setArg}`\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tcommand: claudeCommand,\n\t\t\tbackgroundColor: colorData.rgb,\n\t\t\ttitle: claudeTitle,\n\t\t\tincludeEnvSetup: hasEnvFile,\n\t\t\t...(options.port !== undefined && { port: options.port, includePortExport: true }),\n\t\t}\n\t}\n\n\t/**\n\t * Build terminal options for dev server\n\t */\n\tprivate async buildDevServerTerminalOptions(\n\t\toptions: LaunchLoomOptions\n\t): Promise<TerminalWindowOptions> {\n\t\tconst colorData = generateColorFromBranchName(options.branchName)\n\t\tconst devServerCommand = await getDevServerLaunchCommand(\n\t\t\toptions.worktreePath,\n\t\t\toptions.port,\n\t\t\toptions.capabilities\n\t\t)\n\t\tconst hasEnvFile = existsSync(join(options.worktreePath, '.env'))\n\t\tconst devServerTitle = `Dev Server - ${this.formatIdentifier(options.workflowType, options.identifier)}`\n\n\t\treturn {\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tcommand: devServerCommand,\n\t\t\tbackgroundColor: colorData.rgb,\n\t\t\ttitle: devServerTitle,\n\t\t\tincludeEnvSetup: hasEnvFile,\n\t\t\tincludePortExport: options.capabilities.includes('web'),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t}\n\t}\n\n\t/**\n\t * Build terminal options for standalone terminal (no command)\n\t */\n\tprivate buildStandaloneTerminalOptions(\n\t\toptions: LaunchLoomOptions\n\t): TerminalWindowOptions {\n\t\tconst colorData = generateColorFromBranchName(options.branchName)\n\t\tconst hasEnvFile = existsSync(join(options.worktreePath, '.env'))\n\t\tconst terminalTitle = `Terminal - ${this.formatIdentifier(options.workflowType, options.identifier)}`\n\n\t\treturn {\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tbackgroundColor: colorData.rgb,\n\t\t\ttitle: terminalTitle,\n\t\t\tincludeEnvSetup: hasEnvFile,\n\t\t\tincludePortExport: options.capabilities.includes('web'),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t}\n\t}\n\n\t/**\n\t * Launch multiple terminals (2+) as tabs in single window\n\t */\n\tprivate async launchMultipleTerminals(\n\t\tterminals: Array<{ type: string; options: TerminalWindowOptions }>,\n\t\t_options: LaunchLoomOptions\n\t): Promise<void> {\n\t\tconst terminalOptions = terminals.map((t) => t.options)\n\n\t\tawait openMultipleTerminalWindows(terminalOptions)\n\n\t\tconst terminalTypes = terminals.map((t) => t.type).join(' + ')\n\t\tlogger.info(`Multiple terminals opened: ${terminalTypes}`)\n\t}\n\n\t/**\n\t * Format identifier for terminal tab titles\n\t */\n\tprivate formatIdentifier(workflowType: 'issue' | 'pr' | 'regular', identifier: string | number): string {\n\t\tif (workflowType === 'issue') {\n\t\t\treturn `Issue #${identifier}`\n\t\t} else if (workflowType === 'pr') {\n\t\t\treturn `PR #${identifier}`\n\t\t} else {\n\t\t\treturn `Branch: ${identifier}`\n\t\t}\n\t}\n}\n","import { execa } from 'execa'\nimport { logger } from './logger.js'\n\n/**\n * Check if VSCode command-line tool is available\n */\nexport async function isVSCodeAvailable(): Promise<boolean> {\n\ttry {\n\t\tawait execa('command', ['-v', 'code'], {\n\t\t\tshell: true,\n\t\t\ttimeout: 5000,\n\t\t})\n\t\treturn true\n\t} catch (error) {\n\t\tlogger.debug('VSCode CLI not available', { error })\n\t\treturn false\n\t}\n}\n\n/**\n * Open VSCode window for workspace\n * Throws error if VSCode not available\n */\nexport async function openVSCodeWindow(workspacePath: string): Promise<void> {\n\t// Check availability first\n\tconst available = await isVSCodeAvailable()\n\tif (!available) {\n\t\tthrow new Error(\n\t\t\t'VSCode is not available. Please install VSCode and ensure the \"code\" command is in your PATH.\\n' +\n\t\t\t\t'Install command-line tools: Open VSCode > Command Palette > \"Shell Command: Install \\'code\\' command in PATH\"'\n\t\t)\n\t}\n\n\ttry {\n\t\t// Launch VSCode with workspace path\n\t\tawait execa('code', [workspacePath])\n\t\tlogger.debug(`Opened VSCode for workspace: ${workspacePath}`)\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to open VSCode: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t)\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ NeonProvider,
4
+ validateNeonConfig
5
+ } from "./chunk-YYSKGAZT.js";
6
+ import "./chunk-JNKJ7NJV.js";
7
+ import "./chunk-GEHQXLEI.js";
8
+ export {
9
+ NeonProvider,
10
+ validateNeonConfig
11
+ };
12
+ //# sourceMappingURL=NeonProvider-PAGPUH7F.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ PromptTemplateManager
4
+ } from "./chunk-F3XBU2R7.js";
5
+ import "./chunk-GEHQXLEI.js";
6
+ export {
7
+ PromptTemplateManager
8
+ };
9
+ //# sourceMappingURL=PromptTemplateManager-7FINLRDE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ AgentSettingsSchema,
4
+ CapabilitiesSettingsSchema,
5
+ IloomSettingsSchema,
6
+ SettingsManager,
7
+ WorkflowPermissionSchema,
8
+ WorkflowsSettingsSchema
9
+ } from "./chunk-JBH2ZYYZ.js";
10
+ import "./chunk-GEHQXLEI.js";
11
+ export {
12
+ AgentSettingsSchema,
13
+ CapabilitiesSettingsSchema,
14
+ IloomSettingsSchema,
15
+ SettingsManager,
16
+ WorkflowPermissionSchema,
17
+ WorkflowsSettingsSchema
18
+ };
19
+ //# sourceMappingURL=SettingsManager-VAZF26S2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ promptConfirmation
4
+ } from "./chunk-JNKJ7NJV.js";
5
+ import {
6
+ logger
7
+ } from "./chunk-GEHQXLEI.js";
8
+
9
+ // src/lib/SettingsMigrationManager.ts
10
+ import fs from "fs-extra";
11
+ import path from "path";
12
+ var SettingsMigrationManager = class {
13
+ constructor() {
14
+ this.oldDir = ".hatchbox";
15
+ this.newDir = ".iloom";
16
+ this.settingsFiles = ["settings.local.json", "settings.json"];
17
+ }
18
+ /**
19
+ * Migrate settings from .hatchbox to .iloom if needed
20
+ * Only copies files that don't already exist in target
21
+ * Prompts user for cleanup after successful migration
22
+ */
23
+ async migrateSettingsIfNeeded(projectRoot) {
24
+ const root = projectRoot ?? process.cwd();
25
+ const oldDirPath = path.join(root, this.oldDir);
26
+ const newDirPath = path.join(root, this.newDir);
27
+ const oldDirExists = await fs.pathExists(oldDirPath);
28
+ if (!oldDirExists) {
29
+ logger.debug("No .hatchbox directory found, skipping migration");
30
+ return;
31
+ }
32
+ const needsMigration = await this.checkIfMigrationNeeded(
33
+ newDirPath,
34
+ oldDirPath
35
+ );
36
+ if (!needsMigration) {
37
+ logger.debug("All .iloom settings files already exist, skipping migration");
38
+ return;
39
+ }
40
+ await fs.mkdir(newDirPath, { recursive: true });
41
+ const migratedFiles = [];
42
+ for (const filename of this.settingsFiles) {
43
+ const wasCopied = await this.copySettingsFile(
44
+ oldDirPath,
45
+ newDirPath,
46
+ filename
47
+ );
48
+ if (wasCopied) {
49
+ migratedFiles.push(filename);
50
+ }
51
+ }
52
+ if (migratedFiles.length > 0) {
53
+ await this.updateGitignore(root);
54
+ await this.promptForCleanup(root, migratedFiles);
55
+ }
56
+ }
57
+ /**
58
+ * Check if any settings files need migration
59
+ */
60
+ async checkIfMigrationNeeded(newDirPath, oldDirPath) {
61
+ for (const filename of this.settingsFiles) {
62
+ const targetPath = path.join(newDirPath, filename);
63
+ const sourcePath = path.join(oldDirPath, filename);
64
+ const targetExists = await fs.pathExists(targetPath);
65
+ const sourceExists = await fs.pathExists(sourcePath);
66
+ if (!targetExists && sourceExists) {
67
+ return true;
68
+ }
69
+ }
70
+ return false;
71
+ }
72
+ /**
73
+ * Copy a single settings file from .hatchbox to .iloom
74
+ * Returns true if file was copied
75
+ */
76
+ async copySettingsFile(sourceDir, targetDir, filename) {
77
+ const sourcePath = path.join(sourceDir, filename);
78
+ const targetPath = path.join(targetDir, filename);
79
+ const sourceExists = await fs.pathExists(sourcePath);
80
+ if (!sourceExists) {
81
+ logger.debug(`Source file ${sourcePath} does not exist, skipping`);
82
+ return false;
83
+ }
84
+ const targetExists = await fs.pathExists(targetPath);
85
+ if (targetExists) {
86
+ logger.debug(`Target file ${targetPath} already exists, skipping`);
87
+ return false;
88
+ }
89
+ await fs.copy(sourcePath, targetPath, { overwrite: false });
90
+ logger.success(`Migrated ${filename} from .hatchbox to .iloom`);
91
+ return true;
92
+ }
93
+ /**
94
+ * Prompt user to delete old .hatchbox configuration directory
95
+ */
96
+ async promptForCleanup(projectRoot, migratedFiles) {
97
+ logger.info("\n\u2728 Configuration migration complete!");
98
+ logger.info("The following files were migrated from .hatchbox to .iloom:");
99
+ for (const file of migratedFiles) {
100
+ logger.info(` - ${file}`);
101
+ }
102
+ logger.info("Updated .gitignore to use .iloom paths");
103
+ if (!process.stdin.isTTY) {
104
+ logger.debug(
105
+ "Skipping cleanup prompt - not in interactive terminal"
106
+ );
107
+ return;
108
+ }
109
+ const shouldDelete = await promptConfirmation(
110
+ "\nWould you like to delete the old .hatchbox directory? (recommended)",
111
+ true
112
+ );
113
+ if (shouldDelete) {
114
+ const oldDirPath = path.join(projectRoot, this.oldDir);
115
+ await fs.remove(oldDirPath);
116
+ logger.success("Removed .hatchbox directory");
117
+ } else {
118
+ logger.info(
119
+ "Keeping .hatchbox directory. You can manually delete it later if desired."
120
+ );
121
+ }
122
+ }
123
+ /**
124
+ * Update .gitignore to replace .hatchbox references with .iloom
125
+ */
126
+ async updateGitignore(projectRoot) {
127
+ const gitignorePath = path.join(projectRoot, ".gitignore");
128
+ const gitignoreExists = await fs.pathExists(gitignorePath);
129
+ if (!gitignoreExists) {
130
+ logger.debug("No .gitignore file found, skipping .gitignore update");
131
+ return;
132
+ }
133
+ const content = await fs.readFile(gitignorePath, "utf-8");
134
+ const updatedContent = content.replace(/\.hatchbox/g, ".iloom").replace(/Hatchbox/g, "iloom");
135
+ if (updatedContent !== content) {
136
+ await fs.writeFile(gitignorePath, updatedContent, "utf-8");
137
+ logger.success("Updated .gitignore: replaced .hatchbox references with .iloom");
138
+ } else {
139
+ logger.debug("No .hatchbox references found in .gitignore");
140
+ }
141
+ }
142
+ };
143
+ export {
144
+ SettingsMigrationManager
145
+ };
146
+ //# sourceMappingURL=SettingsMigrationManager-MTQIMI54.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/SettingsMigrationManager.ts"],"sourcesContent":["import fs from 'fs-extra'\nimport path from 'path'\nimport { logger } from '../utils/logger.js'\nimport { promptConfirmation } from '../utils/prompt.js'\n\n/**\n * Manages migration of legacy .hatchbox settings to .iloom\n * Part of rebranding effort - ensures existing users' configurations are preserved\n */\nexport class SettingsMigrationManager {\n\tprivate readonly oldDir = '.hatchbox'\n\tprivate readonly newDir = '.iloom'\n\tprivate readonly settingsFiles = ['settings.local.json', 'settings.json']\n\n\t/**\n\t * Migrate settings from .hatchbox to .iloom if needed\n\t * Only copies files that don't already exist in target\n\t * Prompts user for cleanup after successful migration\n\t */\n\tasync migrateSettingsIfNeeded(projectRoot?: string): Promise<void> {\n\t\tconst root = projectRoot ?? process.cwd()\n\t\tconst oldDirPath = path.join(root, this.oldDir)\n\t\tconst newDirPath = path.join(root, this.newDir)\n\n\t\t// Check if .hatchbox directory exists (skip if it doesn't)\n\t\tconst oldDirExists = await fs.pathExists(oldDirPath)\n\t\tif (!oldDirExists) {\n\t\t\tlogger.debug('No .hatchbox directory found, skipping migration')\n\t\t\treturn\n\t\t}\n\n\t\t// Check if any target files need migration\n\t\tconst needsMigration = await this.checkIfMigrationNeeded(\n\t\t\tnewDirPath,\n\t\t\toldDirPath\n\t\t)\n\t\tif (!needsMigration) {\n\t\t\tlogger.debug('All .iloom settings files already exist, skipping migration')\n\t\t\treturn\n\t\t}\n\n\t\t// Create .iloom directory if needed\n\t\tawait fs.mkdir(newDirPath, { recursive: true })\n\n\t\t// Copy each settings file if source exists and target doesn't\n\t\tconst migratedFiles: string[] = []\n\t\tfor (const filename of this.settingsFiles) {\n\t\t\tconst wasCopied = await this.copySettingsFile(\n\t\t\t\toldDirPath,\n\t\t\t\tnewDirPath,\n\t\t\t\tfilename\n\t\t\t)\n\t\t\tif (wasCopied) {\n\t\t\t\tmigratedFiles.push(filename)\n\t\t\t}\n\t\t}\n\n\t\t// If files were migrated, update .gitignore and prompt for cleanup\n\t\tif (migratedFiles.length > 0) {\n\t\t\t// Always update .gitignore when files are migrated\n\t\t\tawait this.updateGitignore(root)\n\n\t\t\t// Prompt for cleanup of old directory\n\t\t\tawait this.promptForCleanup(root, migratedFiles)\n\t\t}\n\t}\n\n\t/**\n\t * Check if any settings files need migration\n\t */\n\tprivate async checkIfMigrationNeeded(\n\t\tnewDirPath: string,\n\t\toldDirPath: string\n\t): Promise<boolean> {\n\t\tfor (const filename of this.settingsFiles) {\n\t\t\tconst targetPath = path.join(newDirPath, filename)\n\t\t\tconst sourcePath = path.join(oldDirPath, filename)\n\n\t\t\t// If target doesn't exist but source does, migration is needed\n\t\t\tconst targetExists = await fs.pathExists(targetPath)\n\t\t\tconst sourceExists = await fs.pathExists(sourcePath)\n\n\t\t\tif (!targetExists && sourceExists) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\t/**\n\t * Copy a single settings file from .hatchbox to .iloom\n\t * Returns true if file was copied\n\t */\n\tprivate async copySettingsFile(\n\t\tsourceDir: string,\n\t\ttargetDir: string,\n\t\tfilename: string\n\t): Promise<boolean> {\n\t\tconst sourcePath = path.join(sourceDir, filename)\n\t\tconst targetPath = path.join(targetDir, filename)\n\n\t\t// Check if source exists\n\t\tconst sourceExists = await fs.pathExists(sourcePath)\n\t\tif (!sourceExists) {\n\t\t\tlogger.debug(`Source file ${sourcePath} does not exist, skipping`)\n\t\t\treturn false\n\t\t}\n\n\t\t// Check if target exists (don't overwrite)\n\t\tconst targetExists = await fs.pathExists(targetPath)\n\t\tif (targetExists) {\n\t\t\tlogger.debug(`Target file ${targetPath} already exists, skipping`)\n\t\t\treturn false\n\t\t}\n\n\t\t// Copy file\n\t\tawait fs.copy(sourcePath, targetPath, { overwrite: false })\n\t\tlogger.success(`Migrated ${filename} from .hatchbox to .iloom`)\n\t\treturn true\n\t}\n\n\t/**\n\t * Prompt user to delete old .hatchbox configuration directory\n\t */\n\tprivate async promptForCleanup(\n\t\tprojectRoot: string,\n\t\tmigratedFiles: string[]\n\t): Promise<void> {\n\t\t// Display migration summary\n\t\tlogger.info('\\n✨ Configuration migration complete!')\n\t\tlogger.info('The following files were migrated from .hatchbox to .iloom:')\n\t\tfor (const file of migratedFiles) {\n\t\t\tlogger.info(` - ${file}`)\n\t\t}\n\t\tlogger.info('Updated .gitignore to use .iloom paths')\n\n\t\t// Skip prompt if not in interactive terminal (e.g., during tests)\n\t\tif (!process.stdin.isTTY) {\n\t\t\tlogger.debug(\n\t\t\t\t'Skipping cleanup prompt - not in interactive terminal'\n\t\t\t)\n\t\t\treturn\n\t\t}\n\n\t\t// Prompt user for deletion\n\t\tconst shouldDelete = await promptConfirmation(\n\t\t\t'\\nWould you like to delete the old .hatchbox directory? (recommended)',\n\t\t\ttrue\n\t\t)\n\n\t\tif (shouldDelete) {\n\t\t\t// Remove .hatchbox directory\n\t\t\tconst oldDirPath = path.join(projectRoot, this.oldDir)\n\t\t\tawait fs.remove(oldDirPath)\n\t\t\tlogger.success('Removed .hatchbox directory')\n\t\t} else {\n\t\t\tlogger.info(\n\t\t\t\t'Keeping .hatchbox directory. You can manually delete it later if desired.'\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Update .gitignore to replace .hatchbox references with .iloom\n\t */\n\tprivate async updateGitignore(projectRoot: string): Promise<void> {\n\t\tconst gitignorePath = path.join(projectRoot, '.gitignore')\n\n\t\t// Check if .gitignore exists\n\t\tconst gitignoreExists = await fs.pathExists(gitignorePath)\n\t\tif (!gitignoreExists) {\n\t\t\tlogger.debug('No .gitignore file found, skipping .gitignore update')\n\t\t\treturn\n\t\t}\n\n\t\t// Read .gitignore\n\t\tconst content = await fs.readFile(gitignorePath, 'utf-8')\n\n\t\t// Replace .hatchbox with .iloom and Hatchbox with iloom\n\t\tconst updatedContent = content\n\t\t\t.replace(/\\.hatchbox/g, '.iloom')\n\t\t\t.replace(/Hatchbox/g, 'iloom')\n\n\t\t// Only write if content actually changed\n\t\tif (updatedContent !== content) {\n\t\t\tawait fs.writeFile(gitignorePath, updatedContent, 'utf-8')\n\t\t\tlogger.success('Updated .gitignore: replaced .hatchbox references with .iloom')\n\t\t} else {\n\t\t\tlogger.debug('No .hatchbox references found in .gitignore')\n\t\t}\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ IssueEnhancementService
4
+ } from "./chunk-PR7FKQBG.js";
5
+ import {
6
+ AgentManager
7
+ } from "./chunk-OC4H6HJD.js";
8
+ import "./chunk-YETJNRQM.js";
9
+ import {
10
+ GitHubService
11
+ } from "./chunk-T7QPXANZ.js";
12
+ import "./chunk-KQDEK2ZW.js";
13
+ import "./chunk-PXZBAC2M.js";
14
+ import {
15
+ SettingsManager
16
+ } from "./chunk-JBH2ZYYZ.js";
17
+ import "./chunk-JNKJ7NJV.js";
18
+ import "./chunk-GEHQXLEI.js";
19
+
20
+ // src/commands/add-issue.ts
21
+ var AddIssueCommand = class {
22
+ constructor(enhancementService) {
23
+ this.enhancementService = enhancementService ?? new IssueEnhancementService(
24
+ new GitHubService(),
25
+ new AgentManager(),
26
+ new SettingsManager()
27
+ );
28
+ }
29
+ /**
30
+ * Execute the add-issue command workflow:
31
+ * 1. Validate description format
32
+ * 2. Enhance description with Claude AI
33
+ * 3. Create GitHub issue
34
+ * 4. Wait for keypress and open browser for review
35
+ * 5. Return issue number
36
+ */
37
+ async execute(input) {
38
+ const { description } = input;
39
+ if (!description || !this.enhancementService.validateDescription(description)) {
40
+ throw new Error("Description is required and must be more than 30 characters with at least 3 words");
41
+ }
42
+ const enhancedDescription = await this.enhancementService.enhanceDescription(description);
43
+ const result = await this.enhancementService.createEnhancedIssue(
44
+ description,
45
+ enhancedDescription
46
+ );
47
+ await this.enhancementService.waitForReviewAndOpen(result.number);
48
+ return result.number;
49
+ }
50
+ };
51
+ export {
52
+ AddIssueCommand
53
+ };
54
+ //# sourceMappingURL=add-issue-22JBNOML.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/add-issue.ts"],"sourcesContent":["import type { AddIssueOptions } from '../types/index.js'\nimport { IssueEnhancementService } from '../lib/IssueEnhancementService.js'\nimport { GitHubService } from '../lib/GitHubService.js'\nimport { AgentManager } from '../lib/AgentManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\n\n/**\n * Input structure for AddIssueCommand\n */\nexport interface AddIssueCommandInput {\n\tdescription: string\n\toptions: AddIssueOptions\n}\n\n/**\n * Command to create and enhance GitHub issues without creating workspaces.\n * This separates the \"document the work\" step from the \"start the work\" step.\n */\nexport class AddIssueCommand {\n\tprivate enhancementService: IssueEnhancementService\n\n\tconstructor(enhancementService?: IssueEnhancementService) {\n\t\t// Use provided service or create default\n\t\tthis.enhancementService = enhancementService ?? new IssueEnhancementService(\n\t\t\tnew GitHubService(),\n\t\t\tnew AgentManager(),\n\t\t\tnew SettingsManager()\n\t\t)\n\t}\n\n\t/**\n\t * Execute the add-issue command workflow:\n\t * 1. Validate description format\n\t * 2. Enhance description with Claude AI\n\t * 3. Create GitHub issue\n\t * 4. Wait for keypress and open browser for review\n\t * 5. Return issue number\n\t */\n\tpublic async execute(input: AddIssueCommandInput): Promise<number> {\n\t\tconst { description } = input\n\n\t\t// Step 1: Validate description format\n\t\tif (!description || !this.enhancementService.validateDescription(description)) {\n\t\t\tthrow new Error('Description is required and must be more than 30 characters with at least 3 words')\n\t\t}\n\n\t\t// Step 2: Enhance description using Claude AI\n\t\tconst enhancedDescription = await this.enhancementService.enhanceDescription(description)\n\n\t\t// Step 3: Create GitHub issue with original as title, enhanced as body\n\t\tconst result = await this.enhancementService.createEnhancedIssue(\n\t\t\tdescription,\n\t\t\tenhancedDescription\n\t\t)\n\n\t\t// Step 4: Wait for keypress and open issue in browser for review\n\t\tawait this.enhancementService.waitForReviewAndOpen(result.number)\n\n\t\t// Step 5: Return issue number for reference\n\t\treturn result.number\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAkBO,IAAM,kBAAN,MAAsB;AAAA,EAG5B,YAAY,oBAA8C;AAEzD,SAAK,qBAAqB,sBAAsB,IAAI;AAAA,MACnD,IAAI,cAAc;AAAA,MAClB,IAAI,aAAa;AAAA,MACjB,IAAI,gBAAgB;AAAA,IACrB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,QAAQ,OAA8C;AAClE,UAAM,EAAE,YAAY,IAAI;AAGxB,QAAI,CAAC,eAAe,CAAC,KAAK,mBAAmB,oBAAoB,WAAW,GAAG;AAC9E,YAAM,IAAI,MAAM,mFAAmF;AAAA,IACpG;AAGA,UAAM,sBAAsB,MAAM,KAAK,mBAAmB,mBAAmB,WAAW;AAGxF,UAAM,SAAS,MAAM,KAAK,mBAAmB;AAAA,MAC5C;AAAA,MACA;AAAA,IACD;AAGA,UAAM,KAAK,mBAAmB,qBAAqB,OAAO,MAAM;AAGhE,WAAO,OAAO;AAAA,EACf;AACD;","names":[]}