@iloom/cli 0.3.1 → 0.3.3

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 (128) hide show
  1. package/README.md +8 -6
  2. package/dist/{BranchNamingService-OMWKUYMM.js → BranchNamingService-A77VI6AI.js} +2 -2
  3. package/dist/ClaudeContextManager-BN7RE5ZQ.js +15 -0
  4. package/dist/ClaudeService-DLYLJUPA.js +14 -0
  5. package/dist/{GitHubService-EBOETDIW.js → GitHubService-FZHHBOFG.js} +3 -3
  6. package/dist/{LoomLauncher-JF7JZMTZ.js → LoomLauncher-ZV3ZZIBA.js} +40 -26
  7. package/dist/LoomLauncher-ZV3ZZIBA.js.map +1 -0
  8. package/dist/{PromptTemplateManager-A52RUAMS.js → PromptTemplateManager-6HH3PVXV.js} +2 -2
  9. package/dist/README.md +8 -6
  10. package/dist/{SettingsManager-ZCWJ56WP.js → SettingsManager-I2LRCW2A.js} +2 -2
  11. package/dist/{SettingsMigrationManager-AGIIIPDQ.js → SettingsMigrationManager-TJ7UWZG5.js} +3 -3
  12. package/dist/agents/iloom-issue-complexity-evaluator.md +18 -3
  13. package/dist/agents/iloom-issue-enhancer.md +1 -1
  14. package/dist/{chunk-TSKY3JI7.js → chunk-2CXREBLZ.js} +2 -2
  15. package/dist/{chunk-HBYZH6GD.js → chunk-2IJEMXOB.js} +431 -128
  16. package/dist/chunk-2IJEMXOB.js.map +1 -0
  17. package/dist/{chunk-IXKLYTWO.js → chunk-2MAIX45J.js} +8 -8
  18. package/dist/{chunk-4BGK7T6X.js → chunk-5Q3NDNNV.js} +48 -8
  19. package/dist/chunk-5Q3NDNNV.js.map +1 -0
  20. package/dist/{chunk-JQFO7QQN.js → chunk-5VK4NRSF.js} +3 -3
  21. package/dist/{chunk-JQFO7QQN.js.map → chunk-5VK4NRSF.js.map} +1 -1
  22. package/dist/{chunk-XPKDPZ5D.js → chunk-AKUJXDNW.js} +2 -2
  23. package/dist/{chunk-O5OH5MRX.js → chunk-CDZERT7Z.js} +23 -11
  24. package/dist/chunk-CDZERT7Z.js.map +1 -0
  25. package/dist/{chunk-JKXJ7BGL.js → chunk-CE26YH2U.js} +42 -3
  26. package/dist/chunk-CE26YH2U.js.map +1 -0
  27. package/dist/{chunk-ZZZWQGTS.js → chunk-CFFQ2Z7A.js} +74 -75
  28. package/dist/chunk-CFFQ2Z7A.js.map +1 -0
  29. package/dist/{chunk-RO26VS3W.js → chunk-DLHA5VQ3.js} +174 -5
  30. package/dist/chunk-DLHA5VQ3.js.map +1 -0
  31. package/dist/{chunk-ZBQVSHVT.js → chunk-IFB4Z76W.js} +35 -10
  32. package/dist/chunk-IFB4Z76W.js.map +1 -0
  33. package/dist/{chunk-G2IEYOLQ.js → chunk-M7JJCX53.js} +17 -2
  34. package/dist/chunk-M7JJCX53.js.map +1 -0
  35. package/dist/{chunk-KLBYVHPK.js → chunk-OSCLCMDG.js} +2 -2
  36. package/dist/chunk-OXAM2WVC.js +68 -0
  37. package/dist/chunk-OXAM2WVC.js.map +1 -0
  38. package/dist/{chunk-ZWFBBPJI.js → chunk-OYF4VIFI.js} +5 -3
  39. package/dist/chunk-OYF4VIFI.js.map +1 -0
  40. package/dist/{chunk-U5QDY7ZD.js → chunk-PGPI5LR4.js} +8 -8
  41. package/dist/{chunk-WEN5C5DM.js → chunk-RIEO2WML.js} +4 -1
  42. package/dist/chunk-RIEO2WML.js.map +1 -0
  43. package/dist/{chunk-ZE74H5BR.js → chunk-RW54ZMBM.js} +26 -20
  44. package/dist/chunk-RW54ZMBM.js.map +1 -0
  45. package/dist/{chunk-INW24J2W.js → chunk-SUOXY5WJ.js} +2 -2
  46. package/dist/{init-L55Q73H4.js → chunk-UAN4A3YU.js} +345 -45
  47. package/dist/chunk-UAN4A3YU.js.map +1 -0
  48. package/dist/{chunk-IP7SMKIF.js → chunk-UJL4HI2R.js} +59 -60
  49. package/dist/chunk-UJL4HI2R.js.map +1 -0
  50. package/dist/{claude-LUZ35IMK.js → claude-W52VKI6L.js} +4 -2
  51. package/dist/{cleanup-3MONU4PU.js → cleanup-H4VXU3C3.js} +19 -17
  52. package/dist/{cleanup-3MONU4PU.js.map → cleanup-H4VXU3C3.js.map} +1 -1
  53. package/dist/cli.js +347 -114
  54. package/dist/cli.js.map +1 -1
  55. package/dist/{color-ZVALX37U.js → color-F7RU6B6Z.js} +10 -4
  56. package/dist/{contribute-UWJAGIG7.js → contribute-Y7IQV5QY.js} +4 -3
  57. package/dist/{contribute-UWJAGIG7.js.map → contribute-Y7IQV5QY.js.map} +1 -1
  58. package/dist/{feedback-W3BXTGIM.js → feedback-XTUCKJNT.js} +16 -12
  59. package/dist/{feedback-W3BXTGIM.js.map → feedback-XTUCKJNT.js.map} +1 -1
  60. package/dist/{git-34Z6QVDS.js → git-IYA53VIC.js} +9 -2
  61. package/dist/{ignite-KVJEFXNO.js → ignite-T74RYXCA.js} +25 -75
  62. package/dist/ignite-T74RYXCA.js.map +1 -0
  63. package/dist/index.d.ts +71 -14
  64. package/dist/index.js +407 -377
  65. package/dist/index.js.map +1 -1
  66. package/dist/init-4FHTAM3F.js +19 -0
  67. package/dist/mcp/issue-management-server.js +8 -1
  68. package/dist/mcp/issue-management-server.js.map +1 -1
  69. package/dist/{neon-helpers-WPUACUVC.js → neon-helpers-77PBPGJ5.js} +3 -3
  70. package/dist/{open-LNRZL3UU.js → open-UMXANW5S.js} +27 -14
  71. package/dist/open-UMXANW5S.js.map +1 -0
  72. package/dist/{prompt-7INJ7YRU.js → prompt-QALMYTVC.js} +4 -2
  73. package/dist/prompts/init-prompt.txt +89 -9
  74. package/dist/prompts/issue-prompt.txt +18 -11
  75. package/dist/{rebase-C4WNCVGM.js → rebase-VJ2VKR6R.js} +15 -13
  76. package/dist/rebase-VJ2VKR6R.js.map +1 -0
  77. package/dist/{run-IOGNIOYN.js → run-MJYY4PUT.js} +27 -14
  78. package/dist/run-MJYY4PUT.js.map +1 -0
  79. package/dist/schema/settings.schema.json +22 -4
  80. package/dist/{test-git-J7I5MFYH.js → test-git-IT5EWQ5C.js} +5 -5
  81. package/dist/{test-prefix-ZCONBCBX.js → test-prefix-NPWDPUUH.js} +5 -5
  82. package/dist/{test-tabs-RXDBZ6J7.js → test-tabs-PRMRSHKI.js} +3 -2
  83. package/dist/{test-tabs-RXDBZ6J7.js.map → test-tabs-PRMRSHKI.js.map} +1 -1
  84. package/package.json +2 -1
  85. package/dist/ClaudeContextManager-3VXA6UPR.js +0 -13
  86. package/dist/ClaudeService-6CPK43N4.js +0 -12
  87. package/dist/LoomLauncher-JF7JZMTZ.js.map +0 -1
  88. package/dist/chunk-4BGK7T6X.js.map +0 -1
  89. package/dist/chunk-4E4LD3QR.js +0 -302
  90. package/dist/chunk-4E4LD3QR.js.map +0 -1
  91. package/dist/chunk-G2IEYOLQ.js.map +0 -1
  92. package/dist/chunk-HBYZH6GD.js.map +0 -1
  93. package/dist/chunk-IP7SMKIF.js.map +0 -1
  94. package/dist/chunk-JKXJ7BGL.js.map +0 -1
  95. package/dist/chunk-O5OH5MRX.js.map +0 -1
  96. package/dist/chunk-RO26VS3W.js.map +0 -1
  97. package/dist/chunk-WEN5C5DM.js.map +0 -1
  98. package/dist/chunk-ZBQVSHVT.js.map +0 -1
  99. package/dist/chunk-ZE74H5BR.js.map +0 -1
  100. package/dist/chunk-ZWFBBPJI.js.map +0 -1
  101. package/dist/chunk-ZZZWQGTS.js.map +0 -1
  102. package/dist/ignite-KVJEFXNO.js.map +0 -1
  103. package/dist/init-L55Q73H4.js.map +0 -1
  104. package/dist/open-LNRZL3UU.js.map +0 -1
  105. package/dist/rebase-C4WNCVGM.js.map +0 -1
  106. package/dist/run-IOGNIOYN.js.map +0 -1
  107. package/dist/terminal-BIRBZ4AZ.js +0 -16
  108. /package/dist/{BranchNamingService-OMWKUYMM.js.map → BranchNamingService-A77VI6AI.js.map} +0 -0
  109. /package/dist/{ClaudeContextManager-3VXA6UPR.js.map → ClaudeContextManager-BN7RE5ZQ.js.map} +0 -0
  110. /package/dist/{ClaudeService-6CPK43N4.js.map → ClaudeService-DLYLJUPA.js.map} +0 -0
  111. /package/dist/{GitHubService-EBOETDIW.js.map → GitHubService-FZHHBOFG.js.map} +0 -0
  112. /package/dist/{PromptTemplateManager-A52RUAMS.js.map → PromptTemplateManager-6HH3PVXV.js.map} +0 -0
  113. /package/dist/{SettingsManager-ZCWJ56WP.js.map → SettingsManager-I2LRCW2A.js.map} +0 -0
  114. /package/dist/{SettingsMigrationManager-AGIIIPDQ.js.map → SettingsMigrationManager-TJ7UWZG5.js.map} +0 -0
  115. /package/dist/{chunk-TSKY3JI7.js.map → chunk-2CXREBLZ.js.map} +0 -0
  116. /package/dist/{chunk-IXKLYTWO.js.map → chunk-2MAIX45J.js.map} +0 -0
  117. /package/dist/{chunk-XPKDPZ5D.js.map → chunk-AKUJXDNW.js.map} +0 -0
  118. /package/dist/{chunk-KLBYVHPK.js.map → chunk-OSCLCMDG.js.map} +0 -0
  119. /package/dist/{chunk-U5QDY7ZD.js.map → chunk-PGPI5LR4.js.map} +0 -0
  120. /package/dist/{chunk-INW24J2W.js.map → chunk-SUOXY5WJ.js.map} +0 -0
  121. /package/dist/{claude-LUZ35IMK.js.map → claude-W52VKI6L.js.map} +0 -0
  122. /package/dist/{color-ZVALX37U.js.map → color-F7RU6B6Z.js.map} +0 -0
  123. /package/dist/{git-34Z6QVDS.js.map → git-IYA53VIC.js.map} +0 -0
  124. /package/dist/{neon-helpers-WPUACUVC.js.map → init-4FHTAM3F.js.map} +0 -0
  125. /package/dist/{prompt-7INJ7YRU.js.map → neon-helpers-77PBPGJ5.js.map} +0 -0
  126. /package/dist/{terminal-BIRBZ4AZ.js.map → prompt-QALMYTVC.js.map} +0 -0
  127. /package/dist/{test-git-J7I5MFYH.js.map → test-git-IT5EWQ5C.js.map} +0 -0
  128. /package/dist/{test-prefix-ZCONBCBX.js.map → test-prefix-NPWDPUUH.js.map} +0 -0
package/dist/cli.js CHANGED
@@ -1,49 +1,50 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- IssueTrackerFactory,
4
- generateIssueManagementMcpConfig
5
- } from "./chunk-RO26VS3W.js";
6
2
  import {
7
3
  CLIIsolationManager,
8
4
  DatabaseManager,
9
5
  EnvironmentManager,
10
6
  LoomManager,
7
+ MetadataManager,
11
8
  ResourceCleanup
12
- } from "./chunk-HBYZH6GD.js";
9
+ } from "./chunk-2IJEMXOB.js";
13
10
  import {
14
- IdentifierParser,
15
- loadEnvIntoProcess
16
- } from "./chunk-IP7SMKIF.js";
11
+ IdentifierParser
12
+ } from "./chunk-OXAM2WVC.js";
17
13
  import {
18
14
  ProcessManager
19
15
  } from "./chunk-VU3QMIP2.js";
20
16
  import {
21
- createNeonProviderFromSettings
22
- } from "./chunk-JQFO7QQN.js";
23
- import {
17
+ InitCommand,
24
18
  ShellCompletion
25
- } from "./chunk-4E4LD3QR.js";
19
+ } from "./chunk-UAN4A3YU.js";
26
20
  import {
27
21
  getConfiguredRepoFromSettings,
28
22
  getEffectivePRTargetRemote,
29
23
  hasMultipleRemotes,
30
24
  parseGitRemotes
31
25
  } from "./chunk-PA6Q6AWM.js";
26
+ import "./chunk-OSCLCMDG.js";
32
27
  import {
33
- IssueEnhancementService
34
- } from "./chunk-ZBQVSHVT.js";
35
- import {
36
- AgentManager
37
- } from "./chunk-OC4H6HJD.js";
28
+ IssueEnhancementService,
29
+ capitalizeFirstLetter
30
+ } from "./chunk-IFB4Z76W.js";
38
31
  import {
39
32
  openBrowser
40
33
  } from "./chunk-YETJNRQM.js";
41
34
  import {
42
35
  MergeManager
43
- } from "./chunk-IXKLYTWO.js";
36
+ } from "./chunk-2MAIX45J.js";
37
+ import {
38
+ FirstRunManager,
39
+ IssueTrackerFactory,
40
+ generateIssueManagementMcpConfig
41
+ } from "./chunk-DLHA5VQ3.js";
42
+ import {
43
+ AgentManager
44
+ } from "./chunk-OC4H6HJD.js";
44
45
  import {
45
46
  GitWorktreeManager
46
- } from "./chunk-TSKY3JI7.js";
47
+ } from "./chunk-2CXREBLZ.js";
47
48
  import {
48
49
  detectPackageManager,
49
50
  installDependencies,
@@ -51,16 +52,12 @@ import {
51
52
  } from "./chunk-ZT3YZB4K.js";
52
53
  import {
53
54
  ClaudeContextManager
54
- } from "./chunk-XPKDPZ5D.js";
55
- import "./chunk-U5QDY7ZD.js";
56
- import {
57
- detectClaudeCli,
58
- launchClaude
59
- } from "./chunk-ZWFBBPJI.js";
60
- import "./chunk-WEN5C5DM.js";
55
+ } from "./chunk-AKUJXDNW.js";
56
+ import "./chunk-PGPI5LR4.js";
57
+ import "./chunk-RIEO2WML.js";
61
58
  import {
62
59
  DefaultBranchNamingService
63
- } from "./chunk-INW24J2W.js";
60
+ } from "./chunk-SUOXY5WJ.js";
64
61
  import {
65
62
  ProjectCapabilityDetector
66
63
  } from "./chunk-EBISESAP.js";
@@ -72,23 +69,38 @@ import {
72
69
  extractSettingsOverrides
73
70
  } from "./chunk-GYCR2LOU.js";
74
71
  import {
75
- SettingsManager
76
- } from "./chunk-O5OH5MRX.js";
72
+ createNeonProviderFromSettings
73
+ } from "./chunk-5VK4NRSF.js";
77
74
  import {
78
75
  executeGitCommand,
79
76
  extractIssueNumber,
80
77
  findMainWorktreePathWithSettings,
78
+ getRepoRoot,
81
79
  pushBranchToRemote
82
- } from "./chunk-4BGK7T6X.js";
83
- import "./chunk-G2IEYOLQ.js";
80
+ } from "./chunk-5Q3NDNNV.js";
81
+ import {
82
+ SettingsManager
83
+ } from "./chunk-CDZERT7Z.js";
84
+ import {
85
+ GitHubService
86
+ } from "./chunk-M7JJCX53.js";
84
87
  import {
85
88
  executeGhCommand
86
89
  } from "./chunk-3RUPPQRG.js";
87
90
  import {
91
+ promptCommitAction,
88
92
  promptConfirmation,
89
93
  waitForKeypress
90
- } from "./chunk-JKXJ7BGL.js";
91
- import "./chunk-ZZZWQGTS.js";
94
+ } from "./chunk-CE26YH2U.js";
95
+ import "./chunk-CFFQ2Z7A.js";
96
+ import {
97
+ detectClaudeCli,
98
+ launchClaude
99
+ } from "./chunk-OYF4VIFI.js";
100
+ import "./chunk-RW54ZMBM.js";
101
+ import {
102
+ loadEnvIntoProcess
103
+ } from "./chunk-UJL4HI2R.js";
92
104
  import {
93
105
  logger
94
106
  } from "./chunk-GEHQXLEI.js";
@@ -103,8 +115,25 @@ import path2 from "path";
103
115
  import { existsSync } from "fs";
104
116
  import { readFile } from "fs/promises";
105
117
  import path from "path";
118
+ async function getProjectRoot() {
119
+ const repoRoot = await getRepoRoot();
120
+ if (repoRoot) {
121
+ logger.debug(`getProjectRoot: Using git repo root: ${repoRoot}`);
122
+ return repoRoot;
123
+ }
124
+ const cwd = process.cwd();
125
+ logger.debug(`getProjectRoot: Not in git repo, using cwd: ${cwd}`);
126
+ return cwd;
127
+ }
106
128
  async function needsFirstRunSetup() {
107
- const iloomDir = path.join(process.cwd(), ".iloom");
129
+ const projectRoot = await getProjectRoot();
130
+ const firstRunManager = new FirstRunManager();
131
+ const { isConfigured } = await firstRunManager.fixupLegacyProject(projectRoot);
132
+ if (isConfigured) {
133
+ logger.debug("needsFirstRunSetup: Project is tracked as configured globally");
134
+ return false;
135
+ }
136
+ const iloomDir = path.join(projectRoot, ".iloom");
108
137
  if (!existsSync(iloomDir)) {
109
138
  return true;
110
139
  }
@@ -129,13 +158,17 @@ async function launchFirstRunSetup() {
129
158
  logger.info(
130
159
  "iloom will now launch an interactive configuration session with Claude."
131
160
  );
132
- const { waitForKeypress: waitForKeypress2 } = await import("./prompt-7INJ7YRU.js");
161
+ const { waitForKeypress: waitForKeypress2 } = await import("./prompt-QALMYTVC.js");
133
162
  await waitForKeypress2("Press any key to start configuration...");
134
- const { InitCommand } = await import("./init-L55Q73H4.js");
135
163
  const initCommand = new InitCommand();
136
164
  await initCommand.execute(
137
165
  "Help me configure iloom settings for this project. This is my first time using iloom here. Note: Your iloom command will execute once we are done with configuration changes."
138
166
  );
167
+ const projectRoot = await getProjectRoot();
168
+ logger.debug(`Marking project as configured at root: ${projectRoot}`);
169
+ const firstRunManager = new FirstRunManager();
170
+ await firstRunManager.markProjectAsConfigured(projectRoot);
171
+ logger.debug(`Project marked as configured at root: ${projectRoot}`);
139
172
  logger.info("Configuration complete! Continuing with your original command...");
140
173
  }
141
174
 
@@ -208,8 +241,7 @@ var StartCommand = class {
208
241
  }
209
242
  }
210
243
  let repo;
211
- const multipleRemotes = await hasMultipleRemotes();
212
- if (multipleRemotes) {
244
+ if (this.issueTracker.providerName === "github" && await hasMultipleRemotes()) {
213
245
  repo = await getConfiguredRepoFromSettings(initialSettings);
214
246
  logger.info(`Using GitHub repository: ${repo}`);
215
247
  }
@@ -218,7 +250,7 @@ var StartCommand = class {
218
250
  const parsed = await this.parseInput(input.identifier, repo);
219
251
  await this.validateInput(parsed, repo);
220
252
  if (parentLoom) {
221
- const { isInteractiveEnvironment, promptConfirmation: promptConfirmation2 } = await import("./prompt-7INJ7YRU.js");
253
+ const { isInteractiveEnvironment, promptConfirmation: promptConfirmation2 } = await import("./prompt-QALMYTVC.js");
222
254
  const parentDisplay = parentLoom.type === "issue" ? `issue #${parentLoom.identifier}` : parentLoom.type === "pr" ? `PR #${parentLoom.identifier}` : `branch ${parentLoom.identifier}`;
223
255
  if (input.options.childLoom === true) {
224
256
  logger.info(`Creating as child loom of ${parentDisplay} (--child-loom flag)`);
@@ -247,19 +279,20 @@ var StartCommand = class {
247
279
  }
248
280
  if (parsed.type === "description") {
249
281
  logger.info("Creating GitHub issue from description...");
250
- const body = input.options.body ?? "";
282
+ const title = capitalizeFirstLetter(parsed.originalInput);
283
+ const body = input.options.body ? capitalizeFirstLetter(input.options.body) : "";
251
284
  const result = await this.issueTracker.createIssue(
252
- parsed.originalInput,
253
- // Use description as title
285
+ title,
286
+ // Use capitalized description as title
254
287
  body
255
- // Use provided body or empty
288
+ // Use capitalized body or empty
256
289
  );
257
290
  logger.success(`Created issue #${result.number}: ${result.url}`);
258
291
  parsed.type = "issue";
259
292
  parsed.number = result.number;
260
293
  }
261
294
  if (input.options.oneShot === "bypassPermissions") {
262
- const { promptConfirmation: promptConfirmation2 } = await import("./prompt-7INJ7YRU.js");
295
+ const { promptConfirmation: promptConfirmation2 } = await import("./prompt-QALMYTVC.js");
263
296
  const confirmed = await promptConfirmation2(
264
297
  "\u26A0\uFE0F WARNING: bypassPermissions mode will allow Claude to execute all tool calls without confirmation. This can be dangerous. Do you want to proceed?"
265
298
  );
@@ -323,6 +356,7 @@ var StartCommand = class {
323
356
  * Parse input to determine type and extract relevant data
324
357
  */
325
358
  async parseInput(identifier, repo) {
359
+ const hasLeadingSpace = identifier.startsWith(" ");
326
360
  const trimmedIdentifier = identifier.trim();
327
361
  if (!trimmedIdentifier) {
328
362
  throw new Error("Missing required argument: identifier");
@@ -331,7 +365,7 @@ var StartCommand = class {
331
365
  if (trimmedIdentifier.length > 25 && spaceCount > 2) {
332
366
  return {
333
367
  type: "description",
334
- originalInput: trimmedIdentifier
368
+ originalInput: hasLeadingSpace ? " " + trimmedIdentifier : trimmedIdentifier
335
369
  };
336
370
  }
337
371
  const prPattern = /^pr[/-](\d+)$/i;
@@ -520,27 +554,30 @@ var AddIssueCommand = class {
520
554
  /**
521
555
  * Execute the add-issue command workflow:
522
556
  * 1. Validate description format
523
- * 2. Enhance description with Claude Code
557
+ * 2. Skip enhancement if body provided, otherwise enhance description with Claude Code
524
558
  * 3. Create GitHub issue
525
559
  * 4. Wait for keypress and open browser for review
526
560
  * 5. Return issue number
527
561
  */
528
562
  async execute(input) {
529
- const { description } = input;
563
+ const description = capitalizeFirstLetter(input.description);
564
+ const body = input.options.body ? capitalizeFirstLetter(input.options.body) : void 0;
565
+ if (process.env.FORCE_FIRST_TIME_SETUP === "true" || await needsFirstRunSetup()) {
566
+ await launchFirstRunSetup();
567
+ }
530
568
  const settings = await this.settingsManager.loadSettings();
531
569
  let repo;
532
- const multipleRemotes = await hasMultipleRemotes();
533
- if (multipleRemotes) {
570
+ if (this.enhancementService.issueTracker.providerName === "github" && await hasMultipleRemotes()) {
534
571
  repo = await getConfiguredRepoFromSettings(settings);
535
572
  logger.info(`Using GitHub repository: ${repo}`);
536
573
  }
537
574
  if (!description || !this.enhancementService.validateDescription(description)) {
538
575
  throw new Error("Description is required and must be more than 30 characters with at least 3 words");
539
576
  }
540
- const enhancedDescription = await this.enhancementService.enhanceDescription(description);
577
+ const issueBody = body ?? await this.enhancementService.enhanceDescription(description);
541
578
  const result = await this.enhancementService.createEnhancedIssue(
542
579
  description,
543
- enhancedDescription,
580
+ issueBody,
544
581
  repo
545
582
  );
546
583
  await this.enhancementService.waitForReviewAndOpen(result.number);
@@ -567,10 +604,12 @@ var EnhanceCommand = class {
567
604
  async execute(input) {
568
605
  const { issueNumber, options } = input;
569
606
  const { author } = options;
607
+ if (process.env.FORCE_FIRST_TIME_SETUP === "true" || await needsFirstRunSetup()) {
608
+ await launchFirstRunSetup();
609
+ }
570
610
  const settings = await this.settingsManager.loadSettings();
571
611
  let repo;
572
- const multipleRemotes = await hasMultipleRemotes();
573
- if (multipleRemotes) {
612
+ if (this.issueTracker.providerName === "github" && await hasMultipleRemotes()) {
574
613
  repo = await getConfiguredRepoFromSettings(settings);
575
614
  logger.info(`Using GitHub repository: ${repo}`);
576
615
  }
@@ -1029,6 +1068,14 @@ Run '${runCommand}' to see detailed errors.`
1029
1068
  }
1030
1069
  };
1031
1070
 
1071
+ // src/types/index.ts
1072
+ var UserAbortedCommitError = class extends Error {
1073
+ constructor(message = "User aborted the commit") {
1074
+ super(message);
1075
+ this.name = "UserAbortedCommitError";
1076
+ }
1077
+ };
1078
+
1032
1079
  // src/lib/CommitManager.ts
1033
1080
  var CommitManager = class {
1034
1081
  /**
@@ -1087,19 +1134,34 @@ var CommitManager = class {
1087
1134
  }
1088
1135
  await executeGitCommand(commitArgs, { cwd: worktreePath });
1089
1136
  } else {
1090
- logger.info("Opening git editor for commit message review...");
1091
- const commitArgs = ["commit", "-e", "-m", message];
1092
- if (options.skipVerify) {
1093
- commitArgs.push("--no-verify");
1137
+ const action = await promptCommitAction(message);
1138
+ if (action === "abort") {
1139
+ throw new UserAbortedCommitError();
1140
+ }
1141
+ if (action === "accept") {
1142
+ const commitArgs = ["commit", "-m", message];
1143
+ if (options.skipVerify) {
1144
+ commitArgs.push("--no-verify");
1145
+ }
1146
+ await executeGitCommand(commitArgs, { cwd: worktreePath });
1147
+ } else {
1148
+ logger.info("Opening git editor for commit message review...");
1149
+ const commitArgs = ["commit", "-e", "-m", message];
1150
+ if (options.skipVerify) {
1151
+ commitArgs.push("--no-verify");
1152
+ }
1153
+ await executeGitCommand(commitArgs, {
1154
+ cwd: worktreePath,
1155
+ stdio: "inherit",
1156
+ timeout: 3e5
1157
+ // 5 minutes for interactive editing
1158
+ });
1094
1159
  }
1095
- await executeGitCommand(commitArgs, {
1096
- cwd: worktreePath,
1097
- stdio: "inherit",
1098
- timeout: 3e5
1099
- // 5 minutes for interactive editing
1100
- });
1101
1160
  }
1102
1161
  } catch (error) {
1162
+ if (error instanceof UserAbortedCommitError) {
1163
+ throw error;
1164
+ }
1103
1165
  if (error instanceof Error && error.message.includes("nothing to commit")) {
1104
1166
  logger.info("No changes to commit");
1105
1167
  return;
@@ -1719,7 +1781,7 @@ var FinishCommand = class {
1719
1781
  const neonProvider = createNeonProviderFromSettings(settings);
1720
1782
  const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName);
1721
1783
  const cliIsolationManager = new CLIIsolationManager();
1722
- const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-OMWKUYMM.js");
1784
+ const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-A77VI6AI.js");
1723
1785
  this.loomManager ??= new LoomManager(
1724
1786
  this.gitWorktreeManager,
1725
1787
  this.issueTracker,
@@ -1777,11 +1839,12 @@ var FinishCommand = class {
1777
1839
  * Main entry point for finish command
1778
1840
  */
1779
1841
  async execute(input) {
1842
+ var _a;
1780
1843
  try {
1781
1844
  const settings = await this.settingsManager.loadSettings();
1782
1845
  let repo;
1783
- const multipleRemotes = await hasMultipleRemotes();
1784
- if (multipleRemotes) {
1846
+ const needsRepo = ((_a = settings.mergeBehavior) == null ? void 0 : _a.mode) === "github-pr" || this.issueTracker.providerName === "github";
1847
+ if (needsRepo && await hasMultipleRemotes()) {
1785
1848
  repo = await getConfiguredRepoFromSettings(settings);
1786
1849
  logger.info(`Using GitHub repository: ${repo}`);
1787
1850
  }
@@ -2072,8 +2135,16 @@ var FinishCommand = class {
2072
2135
  if (parsed.type === "issue" && parsed.number) {
2073
2136
  commitOptions.issueNumber = parsed.number;
2074
2137
  }
2075
- await this.commitManager.commitChanges(worktree.path, commitOptions);
2076
- logger.success("Changes committed successfully");
2138
+ try {
2139
+ await this.commitManager.commitChanges(worktree.path, commitOptions);
2140
+ logger.success("Changes committed successfully");
2141
+ } catch (error) {
2142
+ if (error instanceof UserAbortedCommitError) {
2143
+ logger.info("Commit aborted by user");
2144
+ return;
2145
+ }
2146
+ throw error;
2147
+ }
2077
2148
  }
2078
2149
  } else {
2079
2150
  logger.debug("No uncommitted changes found");
@@ -2081,6 +2152,11 @@ var FinishCommand = class {
2081
2152
  const settings = await this.settingsManager.loadSettings(worktree.path);
2082
2153
  const mergeBehavior = settings.mergeBehavior ?? { mode: "local" };
2083
2154
  if (mergeBehavior.mode === "github-pr") {
2155
+ if (!this.issueTracker.supportsPullRequests) {
2156
+ throw new Error(
2157
+ `The 'github-pr' merge mode requires a GitHub-compatible issue tracker. Your current provider (${this.issueTracker.providerName}) does not support pull requests. Either change mergeBehavior.mode to 'local' in your settings, or use GitHub as your issue tracker.`
2158
+ );
2159
+ }
2084
2160
  await this.executeGitHubPRWorkflow(parsed, options, worktree, settings);
2085
2161
  return;
2086
2162
  }
@@ -2137,12 +2213,20 @@ var FinishCommand = class {
2137
2213
  logger.info("Committing uncommitted changes...");
2138
2214
  const settings = await this.settingsManager.loadSettings(worktree.path);
2139
2215
  const skipVerify = ((_b = (_a = settings.workflows) == null ? void 0 : _a.pr) == null ? void 0 : _b.noVerify) ?? false;
2140
- await this.commitManager.commitChanges(worktree.path, {
2141
- dryRun: false,
2142
- skipVerify
2143
- // Do NOT pass issueNumber for PRs - no "Fixes #" trailer needed
2144
- });
2145
- logger.success("Changes committed");
2216
+ try {
2217
+ await this.commitManager.commitChanges(worktree.path, {
2218
+ dryRun: false,
2219
+ skipVerify
2220
+ // Do NOT pass issueNumber for PRs - no "Fixes #" trailer needed
2221
+ });
2222
+ logger.success("Changes committed");
2223
+ } catch (error) {
2224
+ if (error instanceof UserAbortedCommitError) {
2225
+ logger.info("Commit aborted by user");
2226
+ return;
2227
+ }
2228
+ throw error;
2229
+ }
2146
2230
  }
2147
2231
  } else {
2148
2232
  logger.debug("No uncommitted changes found");
@@ -2459,6 +2543,77 @@ function getPackageInfo(scriptPath) {
2459
2543
 
2460
2544
  // src/cli.ts
2461
2545
  import { fileURLToPath as fileURLToPath2 } from "url";
2546
+ import { realpathSync } from "fs";
2547
+
2548
+ // src/utils/loom-formatter.ts
2549
+ function determineLoomType(worktree) {
2550
+ const prPathPattern = /_pr_\d+$/;
2551
+ if (prPathPattern.test(worktree.path)) {
2552
+ return "pr";
2553
+ }
2554
+ const issueNumber = extractIssueNumber(worktree.branch);
2555
+ if (issueNumber !== null) {
2556
+ return "issue";
2557
+ }
2558
+ return "branch";
2559
+ }
2560
+ function extractPRNumbers(path4) {
2561
+ if (!path4) {
2562
+ return [];
2563
+ }
2564
+ const prPathPattern = /_pr_(\d+)$/;
2565
+ const match = path4.match(prPathPattern);
2566
+ if (match == null ? void 0 : match[1]) {
2567
+ return [match[1]];
2568
+ }
2569
+ return [];
2570
+ }
2571
+ function extractIssueNumbers(branch) {
2572
+ if (!branch) {
2573
+ return [];
2574
+ }
2575
+ const issueNumber = extractIssueNumber(branch);
2576
+ if (issueNumber === null) {
2577
+ return [];
2578
+ }
2579
+ return [issueNumber];
2580
+ }
2581
+ function formatLoomForJson(worktree, mainWorktreePath, metadata) {
2582
+ const loomType = (metadata == null ? void 0 : metadata.issueType) ?? determineLoomType(worktree);
2583
+ let issueNumbers;
2584
+ let prNumbers;
2585
+ if (metadata) {
2586
+ issueNumbers = metadata.issue_numbers;
2587
+ prNumbers = metadata.pr_numbers;
2588
+ } else {
2589
+ issueNumbers = [];
2590
+ prNumbers = [];
2591
+ if (loomType === "pr") {
2592
+ prNumbers = extractPRNumbers(worktree.path);
2593
+ } else if (loomType === "issue") {
2594
+ issueNumbers = extractIssueNumbers(worktree.branch);
2595
+ }
2596
+ }
2597
+ const isMainWorktree = mainWorktreePath ? worktree.path === mainWorktreePath : false;
2598
+ return {
2599
+ name: worktree.branch || worktree.path,
2600
+ worktreePath: worktree.bare ? null : worktree.path,
2601
+ branch: ((metadata == null ? void 0 : metadata.branchName) ?? worktree.branch) || null,
2602
+ type: loomType,
2603
+ issue_numbers: issueNumbers,
2604
+ pr_numbers: prNumbers,
2605
+ isMainWorktree,
2606
+ description: (metadata == null ? void 0 : metadata.description) ?? null,
2607
+ created_at: (metadata == null ? void 0 : metadata.created_at) ?? null,
2608
+ issueTracker: (metadata == null ? void 0 : metadata.issueTracker) ?? null,
2609
+ colorHex: (metadata == null ? void 0 : metadata.colorHex) ?? null
2610
+ };
2611
+ }
2612
+ function formatLoomsForJson(worktrees, mainWorktreePath, metadata) {
2613
+ return worktrees.map((wt) => formatLoomForJson(wt, mainWorktreePath, metadata == null ? void 0 : metadata.get(wt.path)));
2614
+ }
2615
+
2616
+ // src/cli.ts
2462
2617
  var __filename = fileURLToPath2(import.meta.url);
2463
2618
  var packageJson = getPackageInfo(__filename);
2464
2619
  function parseIssueIdentifier(value) {
@@ -2483,13 +2638,14 @@ program.name("iloom").description(packageJson.description).version(packageJson.v
2483
2638
  } catch {
2484
2639
  }
2485
2640
  try {
2486
- const { SettingsMigrationManager } = await import("./SettingsMigrationManager-AGIIIPDQ.js");
2641
+ const { SettingsMigrationManager } = await import("./SettingsMigrationManager-TJ7UWZG5.js");
2487
2642
  const migrationManager = new SettingsMigrationManager();
2488
2643
  await migrationManager.migrateSettingsIfNeeded();
2489
2644
  } catch (error) {
2490
2645
  logger.debug(`Settings migration failed: ${error instanceof Error ? error.message : "Unknown"}`);
2491
2646
  }
2492
2647
  await validateSettingsForCommand(thisCommand);
2648
+ await validateGhCliForCommand(thisCommand);
2493
2649
  });
2494
2650
  async function validateSettingsForCommand(command) {
2495
2651
  var _a, _b;
@@ -2501,8 +2657,7 @@ async function validateSettingsForCommand(command) {
2501
2657
  try {
2502
2658
  const settingsManager = new SettingsManager();
2503
2659
  const settings = await settingsManager.loadSettings();
2504
- const { hasMultipleRemotes: hasMultipleRemotes2 } = await import("./remote-VUNCQZ6J.js");
2505
- const multipleRemotes = await hasMultipleRemotes2();
2660
+ const multipleRemotes = await hasMultipleRemotes();
2506
2661
  if (multipleRemotes && !((_b = (_a = settings.issueManagement) == null ? void 0 : _a.github) == null ? void 0 : _b.remote)) {
2507
2662
  await autoLaunchInitForMultipleRemotes();
2508
2663
  return;
@@ -2513,6 +2668,59 @@ async function validateSettingsForCommand(command) {
2513
2668
  process.exit(1);
2514
2669
  }
2515
2670
  }
2671
+ async function validateGhCliForCommand(command) {
2672
+ var _a, _b;
2673
+ const commandName = command.args[0] ?? "";
2674
+ const alwaysRequireGh = ["feedback", "contribute"];
2675
+ const conditionallyRequireGh = ["start", "finish", "enhance", "add-issue", "ignite", "spin"];
2676
+ const warnOnly = ["init", "list", "rebase", "cleanup", "run", "update", "open"];
2677
+ if (commandName.startsWith("test-") || commandName === "help") {
2678
+ return;
2679
+ }
2680
+ const ghAvailable = GitHubService.isCliAvailable();
2681
+ let needsGhCli = alwaysRequireGh.includes(commandName);
2682
+ if (!needsGhCli && conditionallyRequireGh.includes(commandName)) {
2683
+ try {
2684
+ const settingsManager = new SettingsManager();
2685
+ const settings = await settingsManager.loadSettings();
2686
+ const provider = IssueTrackerFactory.getProviderName(settings);
2687
+ const mergeBehaviorMode = (_a = settings.mergeBehavior) == null ? void 0 : _a.mode;
2688
+ needsGhCli = provider === "github" || mergeBehaviorMode === "github-pr";
2689
+ } catch {
2690
+ needsGhCli = true;
2691
+ }
2692
+ }
2693
+ if (!ghAvailable) {
2694
+ if (needsGhCli) {
2695
+ const errorMessage = alwaysRequireGh.includes(commandName) ? `The "${commandName}" command requires GitHub CLI (gh) to be installed.` : `GitHub CLI (gh) is required when using GitHub as the issue tracker or "github-pr" merge mode.`;
2696
+ logger.error(errorMessage);
2697
+ logger.info("");
2698
+ logger.info("To install GitHub CLI:");
2699
+ logger.info(" \u2022 macOS: brew install gh");
2700
+ logger.info(" \u2022 Windows: winget install GitHub.cli");
2701
+ logger.info(" \u2022 Linux: https://github.com/cli/cli#installation");
2702
+ logger.info("");
2703
+ logger.info("After installation, authenticate with: gh auth login");
2704
+ process.exit(1);
2705
+ } else if (warnOnly.includes(commandName)) {
2706
+ try {
2707
+ const settingsManager = new SettingsManager();
2708
+ const settings = await settingsManager.loadSettings();
2709
+ const provider = IssueTrackerFactory.getProviderName(settings);
2710
+ const mergeBehaviorMode = (_b = settings.mergeBehavior) == null ? void 0 : _b.mode;
2711
+ if (provider === "github" || mergeBehaviorMode === "github-pr") {
2712
+ logger.warn("GitHub CLI (gh) is not installed.");
2713
+ logger.warn(
2714
+ "Some features may not work correctly with your current configuration (GitHub provider or github-pr merge mode)."
2715
+ );
2716
+ logger.info("To install: brew install gh (macOS) or see https://github.com/cli/cli#installation");
2717
+ logger.info("");
2718
+ }
2719
+ } catch {
2720
+ }
2721
+ }
2722
+ }
2723
+ }
2516
2724
  async function autoLaunchInitForMultipleRemotes() {
2517
2725
  var _a, _b;
2518
2726
  logger.info("Multiple git remotes detected, but no GitHub remote is configured.");
@@ -2520,18 +2728,18 @@ async function autoLaunchInitForMultipleRemotes() {
2520
2728
  logger.info("iloom will now launch an interactive configuration session with Claude");
2521
2729
  logger.info("to help you select which remote to use for GitHub operations.");
2522
2730
  logger.info("");
2523
- const { waitForKeypress: waitForKeypress2 } = await import("./prompt-7INJ7YRU.js");
2731
+ const { waitForKeypress: waitForKeypress2 } = await import("./prompt-QALMYTVC.js");
2524
2732
  await waitForKeypress2("Press any key to start configuration...");
2525
2733
  logger.info("");
2526
2734
  try {
2527
- const { InitCommand } = await import("./init-L55Q73H4.js");
2528
- const initCommand = new InitCommand();
2735
+ const { InitCommand: InitCommand2 } = await import("./init-4FHTAM3F.js");
2736
+ const initCommand = new InitCommand2();
2529
2737
  const customInitialMessage = "Help me configure which git remote iloom should use for GitHub operations. I have multiple remotes and need to select the correct one.";
2530
2738
  await initCommand.execute(customInitialMessage);
2531
2739
  logger.info("");
2532
2740
  logger.info("Configuration complete! Continuing with your original command...");
2533
2741
  logger.info("");
2534
- const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-ZCWJ56WP.js");
2742
+ const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-I2LRCW2A.js");
2535
2743
  const settingsManager = new SettingsManager2();
2536
2744
  const settings = await settingsManager.loadSettings();
2537
2745
  const { hasMultipleRemotes: hasMultipleRemotes2 } = await import("./remote-VUNCQZ6J.js");
@@ -2550,13 +2758,13 @@ async function autoLaunchInitForMultipleRemotes() {
2550
2758
  }
2551
2759
  var shellCompletion = new ShellCompletion();
2552
2760
  shellCompletion.init();
2553
- program.command("start").alias("create").alias("up").description("Create isolated workspace for an issue/PR").argument("[identifier]", "Issue number, PR number, or branch name (optional - will prompt if not provided)").option("--claude", "Enable Claude integration (default: true)").option("--no-claude", "Disable Claude integration").option("--code", "Enable VSCode (default: true)").option("--no-code", "Disable VSCode").option("--dev-server", "Enable dev server in terminal (default: true)").option("--no-dev-server", "Disable dev server").option("--terminal", "Enable terminal without dev server (default: false)").option("--no-terminal", "Disable terminal").option("--child-loom", "Force create as child loom (skip prompt)").option("--no-child-loom", "Force create as independent loom (skip prompt)").option("--body <text>", "Body text for issue (skips AI enhancement)").addOption(
2761
+ program.command("start").alias("new").alias("create").alias("up").description("Create isolated workspace for an issue/PR").argument("[identifier]", "Issue number, PR number, or branch name (optional - will prompt if not provided)").option("--claude", "Enable Claude integration (default: true)").option("--no-claude", "Disable Claude integration").option("--code", "Enable VSCode (default: true)").option("--no-code", "Disable VSCode").option("--dev-server", "Enable dev server in terminal (default: true)").option("--no-dev-server", "Disable dev server").option("--terminal", "Enable terminal without dev server (default: false)").option("--no-terminal", "Disable terminal").option("--child-loom", "Force create as child loom (skip prompt)").option("--no-child-loom", "Force create as independent loom (skip prompt)").option("--body <text>", "Body text for issue (skips AI enhancement)").addOption(
2554
2762
  new Option("--one-shot <mode>", "One-shot automation mode").choices(["default", "noReview", "bypassPermissions"]).default("default")
2555
2763
  ).action(async (identifier, options) => {
2556
2764
  try {
2557
2765
  let finalIdentifier = identifier;
2558
2766
  if (!finalIdentifier) {
2559
- const { promptInput } = await import("./prompt-7INJ7YRU.js");
2767
+ const { promptInput } = await import("./prompt-QALMYTVC.js");
2560
2768
  finalIdentifier = await promptInput("Enter issue number, PR number (pr/123), or branch name");
2561
2769
  if (!(finalIdentifier == null ? void 0 : finalIdentifier.trim())) {
2562
2770
  logger.error("Identifier is required");
@@ -2573,7 +2781,7 @@ program.command("start").alias("create").alias("up").description("Create isolate
2573
2781
  process.exit(1);
2574
2782
  }
2575
2783
  });
2576
- program.command("add-issue").alias("a").description("Create and enhance GitHub issue without starting workspace").argument("<description>", "Natural language description of the issue (>50 chars, >2 spaces)").action(async (description) => {
2784
+ program.command("add-issue").alias("a").description("Create and enhance GitHub issue without starting workspace").argument("<description>", "Natural language description of the issue (>50 chars, >2 spaces)").option("--body <text>", "Body text for issue (skips AI enhancement)").action(async (description, options) => {
2577
2785
  try {
2578
2786
  const settingsManager = new SettingsManager();
2579
2787
  const settings = await settingsManager.loadSettings();
@@ -2582,7 +2790,7 @@ program.command("add-issue").alias("a").description("Create and enhance GitHub i
2582
2790
  const command = new AddIssueCommand(enhancementService, settingsManager);
2583
2791
  const issueNumber = await command.execute({
2584
2792
  description,
2585
- options: {}
2793
+ options: options.body ? { body: options.body } : {}
2586
2794
  });
2587
2795
  logger.success(`Issue #${issueNumber} created successfully`);
2588
2796
  process.exit(0);
@@ -2593,7 +2801,7 @@ program.command("add-issue").alias("a").description("Create and enhance GitHub i
2593
2801
  });
2594
2802
  program.command("feedback").alias("f").description("Submit feedback/bug report to iloom-cli repository").argument("<description>", "Natural language description of feedback (>50 chars, >2 spaces)").option("--body <text>", "Body text for feedback (added after diagnostics)").action(async (description, options) => {
2595
2803
  try {
2596
- const { FeedbackCommand } = await import("./feedback-W3BXTGIM.js");
2804
+ const { FeedbackCommand } = await import("./feedback-XTUCKJNT.js");
2597
2805
  const command = new FeedbackCommand();
2598
2806
  const feedbackOptions = {};
2599
2807
  if (options.body !== void 0) {
@@ -2644,7 +2852,7 @@ program.command("finish").alias("dn").description("Merge work and cleanup worksp
2644
2852
  });
2645
2853
  program.command("rebase").description("Rebase current branch on main with Claude-assisted conflict resolution").option("-f, --force", "Skip confirmation prompts").option("-n, --dry-run", "Preview actions without executing").action(async (options) => {
2646
2854
  try {
2647
- const { RebaseCommand } = await import("./rebase-C4WNCVGM.js");
2855
+ const { RebaseCommand } = await import("./rebase-VJ2VKR6R.js");
2648
2856
  const command = new RebaseCommand();
2649
2857
  await command.execute(options);
2650
2858
  } catch (error) {
@@ -2656,7 +2864,7 @@ program.command("spin").alias("ignite").description("Launch Claude with auto-det
2656
2864
  new Option("--one-shot <mode>", "One-shot automation mode").choices(["default", "noReview", "bypassPermissions"]).default("default")
2657
2865
  ).action(async (options) => {
2658
2866
  try {
2659
- const { IgniteCommand } = await import("./ignite-KVJEFXNO.js");
2867
+ const { IgniteCommand } = await import("./ignite-T74RYXCA.js");
2660
2868
  const command = new IgniteCommand();
2661
2869
  await command.execute(options.oneShot ?? "default");
2662
2870
  } catch (error) {
@@ -2667,7 +2875,7 @@ program.command("spin").alias("ignite").description("Launch Claude with auto-det
2667
2875
  program.command("open").description("Open workspace in browser or run CLI tool").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").allowUnknownOption().action(async (identifier, _options, command) => {
2668
2876
  try {
2669
2877
  const args = (command == null ? void 0 : command.args) ? command.args.slice(identifier ? 1 : 0) : [];
2670
- const { OpenCommand } = await import("./open-LNRZL3UU.js");
2878
+ const { OpenCommand } = await import("./open-UMXANW5S.js");
2671
2879
  const cmd = new OpenCommand();
2672
2880
  const input = identifier ? { identifier, args } : { args };
2673
2881
  await cmd.execute(input);
@@ -2679,7 +2887,7 @@ program.command("open").description("Open workspace in browser or run CLI tool")
2679
2887
  program.command("run").description("Run CLI tool or open workspace in browser").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").allowUnknownOption().action(async (identifier, _options, command) => {
2680
2888
  try {
2681
2889
  const args = (command == null ? void 0 : command.args) ? command.args.slice(identifier ? 1 : 0) : [];
2682
- const { RunCommand } = await import("./run-IOGNIOYN.js");
2890
+ const { RunCommand } = await import("./run-MJYY4PUT.js");
2683
2891
  const cmd = new RunCommand();
2684
2892
  const input = identifier ? { identifier, args } : { args };
2685
2893
  await cmd.execute(input);
@@ -2688,9 +2896,9 @@ program.command("run").description("Run CLI tool or open workspace in browser").
2688
2896
  process.exit(1);
2689
2897
  }
2690
2898
  });
2691
- program.command("cleanup").description("Remove workspaces").argument("[identifier]", "Branch name or issue number to cleanup (auto-detected)").option("-l, --list", "List all worktrees").option("-a, --all", "Remove all worktrees (interactive confirmation)").option("-i, --issue <number>", "Cleanup by issue number", parseInt).option("-f, --force", "Skip confirmations and force removal").option("--dry-run", "Show what would be done without doing it").action(async (identifier, options) => {
2899
+ program.command("cleanup").alias("remove").alias("clean").description("Remove workspaces").argument("[identifier]", "Branch name or issue number to cleanup (auto-detected)").option("-l, --list", "List all worktrees").option("-a, --all", "Remove all worktrees (interactive confirmation)").option("-i, --issue <number>", "Cleanup by issue number", parseInt).option("-f, --force", "Skip confirmations and force removal").option("--dry-run", "Show what would be done without doing it").action(async (identifier, options) => {
2692
2900
  try {
2693
- const { CleanupCommand } = await import("./cleanup-3MONU4PU.js");
2901
+ const { CleanupCommand } = await import("./cleanup-H4VXU3C3.js");
2694
2902
  const command = new CleanupCommand();
2695
2903
  const input = {
2696
2904
  options: options ?? {}
@@ -2707,9 +2915,16 @@ program.command("cleanup").description("Remove workspaces").argument("[identifie
2707
2915
  program.command("list").description("Show active workspaces").option("--json", "Output as JSON").action(async (options) => {
2708
2916
  try {
2709
2917
  const manager = new GitWorktreeManager();
2918
+ const metadataManager = new MetadataManager();
2710
2919
  const worktrees = await manager.listWorktrees({ porcelain: true });
2920
+ const metadata = /* @__PURE__ */ new Map();
2921
+ for (const worktree of worktrees) {
2922
+ const loomMetadata = await metadataManager.readMetadata(worktree.path);
2923
+ metadata.set(worktree.path, loomMetadata);
2924
+ }
2711
2925
  if (options.json) {
2712
- console.log(JSON.stringify(worktrees, null, 2));
2926
+ const mainWorktreePath = await findMainWorktreePathWithSettings();
2927
+ console.log(JSON.stringify(formatLoomsForJson(worktrees, mainWorktreePath, metadata), null, 2));
2713
2928
  return;
2714
2929
  }
2715
2930
  if (worktrees.length === 0) {
@@ -2719,7 +2934,11 @@ program.command("list").description("Show active workspaces").option("--json", "
2719
2934
  logger.info("Active workspaces:");
2720
2935
  for (const worktree of worktrees) {
2721
2936
  const formatted = manager.formatWorktree(worktree);
2937
+ const loomMetadata = metadata.get(worktree.path);
2722
2938
  logger.info(` ${formatted.title}`);
2939
+ if (loomMetadata == null ? void 0 : loomMetadata.description) {
2940
+ logger.info(` Description: ${loomMetadata.description}`);
2941
+ }
2723
2942
  logger.info(` Path: ${formatted.path}`);
2724
2943
  logger.info(` Commit: ${formatted.commit}`);
2725
2944
  }
@@ -2738,8 +2957,8 @@ program.command("list").description("Show active workspaces").option("--json", "
2738
2957
  });
2739
2958
  program.command("init").alias("config").description("Initialize iloom configuration and setup shell autocomplete").argument("[prompt]", 'Custom initial message to send to Claude (defaults to "Help me configure iloom settings.")').action(async (prompt) => {
2740
2959
  try {
2741
- const { InitCommand } = await import("./init-L55Q73H4.js");
2742
- const command = new InitCommand();
2960
+ const { InitCommand: InitCommand2 } = await import("./init-4FHTAM3F.js");
2961
+ const command = new InitCommand2();
2743
2962
  const trimmedPrompt = prompt == null ? void 0 : prompt.trim();
2744
2963
  const customPrompt = trimmedPrompt && trimmedPrompt.length > 0 ? trimmedPrompt : void 0;
2745
2964
  await command.execute(customPrompt);
@@ -2750,7 +2969,7 @@ program.command("init").alias("config").description("Initialize iloom configurat
2750
2969
  });
2751
2970
  program.command("contribute").description("Set up local development environment for contributing to iloom").action(async () => {
2752
2971
  try {
2753
- const { ContributeCommand } = await import("./contribute-UWJAGIG7.js");
2972
+ const { ContributeCommand } = await import("./contribute-Y7IQV5QY.js");
2754
2973
  const command = new ContributeCommand();
2755
2974
  await command.execute();
2756
2975
  } catch (error) {
@@ -2770,10 +2989,10 @@ program.command("update").description("Update iloom-cli to the latest version").
2770
2989
  });
2771
2990
  program.command("test-github").description("Test GitHub integration (Issue #3)").argument("<identifier>", "Issue number or PR number").option("--no-claude", "Skip Claude for branch name generation").action(async (identifier, options) => {
2772
2991
  try {
2773
- const { GitHubService } = await import("./GitHubService-EBOETDIW.js");
2774
- const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-OMWKUYMM.js");
2992
+ const { GitHubService: GitHubService2 } = await import("./GitHubService-FZHHBOFG.js");
2993
+ const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-A77VI6AI.js");
2775
2994
  logger.info("Testing GitHub Integration\n");
2776
- const service = new GitHubService();
2995
+ const service = new GitHubService2();
2777
2996
  const branchNaming = new DefaultBranchNamingService2({ useClaude: options.claude !== false });
2778
2997
  logger.info("Detecting input type...");
2779
2998
  const detection = await service.detectInputType(identifier);
@@ -2829,10 +3048,10 @@ program.command("test-github").description("Test GitHub integration (Issue #3)")
2829
3048
  });
2830
3049
  program.command("test-claude").description("Test Claude integration (Issue #10)").option("--detect", "Test Claude CLI detection").option("--version", "Get Claude CLI version").option("--branch <title>", "Test branch name generation with given title").option("--issue <number>", "Issue number for branch generation", "123").option("--launch <prompt>", "Launch Claude with a prompt (headless)").option("--interactive", "Launch Claude interactively (requires --launch)").option("--template <name>", "Test template loading").action(async (options) => {
2831
3050
  try {
2832
- const { detectClaudeCli: detectClaudeCli2, getClaudeVersion, generateBranchName, launchClaude: launchClaude2 } = await import("./claude-LUZ35IMK.js");
2833
- const { PromptTemplateManager } = await import("./PromptTemplateManager-A52RUAMS.js");
2834
- const { ClaudeService } = await import("./ClaudeService-6CPK43N4.js");
2835
- const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-3VXA6UPR.js");
3051
+ const { detectClaudeCli: detectClaudeCli2, getClaudeVersion, generateBranchName, launchClaude: launchClaude2 } = await import("./claude-W52VKI6L.js");
3052
+ const { PromptTemplateManager } = await import("./PromptTemplateManager-6HH3PVXV.js");
3053
+ const { ClaudeService } = await import("./ClaudeService-DLYLJUPA.js");
3054
+ const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-BN7RE5ZQ.js");
2836
3055
  logger.info("Testing Claude Integration\n");
2837
3056
  if (options.detect) {
2838
3057
  logger.info("Detecting Claude CLI...");
@@ -2980,7 +3199,7 @@ program.command("test-webserver").description("Test if a web server is running o
2980
3199
  });
2981
3200
  program.command("test-git").description("Test Git integration - findMainWorktreePath() function (reads .iloom/settings.json)").action(async () => {
2982
3201
  try {
2983
- const { TestGitCommand } = await import("./test-git-J7I5MFYH.js");
3202
+ const { TestGitCommand } = await import("./test-git-IT5EWQ5C.js");
2984
3203
  const command = new TestGitCommand();
2985
3204
  await command.execute();
2986
3205
  } catch (error) {
@@ -2993,7 +3212,7 @@ program.command("test-git").description("Test Git integration - findMainWorktree
2993
3212
  });
2994
3213
  program.command("test-tabs").description("Test iTerm2 dual tab functionality - opens two tabs with test commands").action(async () => {
2995
3214
  try {
2996
- const { TestTabsCommand } = await import("./test-tabs-RXDBZ6J7.js");
3215
+ const { TestTabsCommand } = await import("./test-tabs-PRMRSHKI.js");
2997
3216
  const command = new TestTabsCommand();
2998
3217
  await command.execute();
2999
3218
  } catch (error) {
@@ -3006,7 +3225,7 @@ program.command("test-tabs").description("Test iTerm2 dual tab functionality - o
3006
3225
  });
3007
3226
  program.command("test-prefix").description("Test worktree prefix configuration - preview worktree paths (reads .iloom/settings.json)").action(async () => {
3008
3227
  try {
3009
- const { TestPrefixCommand } = await import("./test-prefix-ZCONBCBX.js");
3228
+ const { TestPrefixCommand } = await import("./test-prefix-NPWDPUUH.js");
3010
3229
  const command = new TestPrefixCommand();
3011
3230
  await command.execute();
3012
3231
  } catch (error) {
@@ -3020,8 +3239,8 @@ program.command("test-prefix").description("Test worktree prefix configuration -
3020
3239
  program.command("test-neon").description("Test Neon integration and debug configuration").action(async () => {
3021
3240
  var _a;
3022
3241
  try {
3023
- const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-ZCWJ56WP.js");
3024
- const { createNeonProviderFromSettings: createNeonProviderFromSettings2 } = await import("./neon-helpers-WPUACUVC.js");
3242
+ const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-I2LRCW2A.js");
3243
+ const { createNeonProviderFromSettings: createNeonProviderFromSettings2 } = await import("./neon-helpers-77PBPGJ5.js");
3025
3244
  logger.info("Testing Neon Integration\n");
3026
3245
  logger.info("1. Settings Configuration:");
3027
3246
  const settingsManager = new SettingsManager2();
@@ -3099,12 +3318,26 @@ program.command("help").description("Display help information").argument("[comma
3099
3318
  }
3100
3319
  process.exit(0);
3101
3320
  });
3102
- try {
3103
- await program.parseAsync();
3104
- } catch (error) {
3105
- if (error instanceof Error) {
3106
- logger.error(`Error: ${error.message}`);
3107
- process.exit(1);
3321
+ var isRunDirectly = process.argv[1] && (() => {
3322
+ try {
3323
+ const scriptPath = realpathSync(process.argv[1]);
3324
+ const modulePath = fileURLToPath2(import.meta.url);
3325
+ return scriptPath === modulePath;
3326
+ } catch {
3327
+ return true;
3328
+ }
3329
+ })();
3330
+ if (isRunDirectly) {
3331
+ try {
3332
+ await program.parseAsync();
3333
+ } catch (error) {
3334
+ if (error instanceof Error) {
3335
+ logger.error(`Error: ${error.message}`);
3336
+ process.exit(1);
3337
+ }
3108
3338
  }
3109
3339
  }
3340
+ export {
3341
+ validateGhCliForCommand
3342
+ };
3110
3343
  //# sourceMappingURL=cli.js.map