@iloom/cli 0.3.1 → 0.3.2

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 (101) hide show
  1. package/README.md +5 -3
  2. package/dist/{BranchNamingService-OMWKUYMM.js → BranchNamingService-JYO746H7.js} +2 -2
  3. package/dist/ClaudeContextManager-5WPRJIIW.js +15 -0
  4. package/dist/ClaudeService-Z4KA7QOW.js +14 -0
  5. package/dist/{GitHubService-EBOETDIW.js → GitHubService-UAMH7DMF.js} +2 -2
  6. package/dist/{LoomLauncher-JF7JZMTZ.js → LoomLauncher-FVZECY3C.js} +24 -13
  7. package/dist/LoomLauncher-FVZECY3C.js.map +1 -0
  8. package/dist/README.md +5 -3
  9. package/dist/{SettingsManager-ZCWJ56WP.js → SettingsManager-MTVX57WR.js} +2 -2
  10. package/dist/{chunk-4BGK7T6X.js → chunk-5NTD4MCZ.js} +23 -7
  11. package/dist/chunk-5NTD4MCZ.js.map +1 -0
  12. package/dist/{chunk-U5QDY7ZD.js → chunk-A2P7NZTB.js} +7 -7
  13. package/dist/{chunk-XPKDPZ5D.js → chunk-C7ASXK6J.js} +2 -2
  14. package/dist/{chunk-G2IEYOLQ.js → chunk-F4ENT6AC.js} +16 -1
  15. package/dist/chunk-F4ENT6AC.js.map +1 -0
  16. package/dist/{chunk-IXKLYTWO.js → chunk-FOV7RRQ2.js} +8 -8
  17. package/dist/{chunk-RO26VS3W.js → chunk-FXMLNKLT.js} +2 -2
  18. package/dist/{chunk-ZBQVSHVT.js → chunk-GOG3ZB7O.js} +14 -8
  19. package/dist/chunk-GOG3ZB7O.js.map +1 -0
  20. package/dist/{chunk-JQFO7QQN.js → chunk-GVICXJHW.js} +2 -2
  21. package/dist/{chunk-JQFO7QQN.js.map → chunk-GVICXJHW.js.map} +1 -1
  22. package/dist/{chunk-HBYZH6GD.js → chunk-KG343GSG.js} +90 -47
  23. package/dist/chunk-KG343GSG.js.map +1 -0
  24. package/dist/{chunk-TSKY3JI7.js → chunk-OAP6SASD.js} +2 -2
  25. package/dist/chunk-OXAM2WVC.js +68 -0
  26. package/dist/chunk-OXAM2WVC.js.map +1 -0
  27. package/dist/{chunk-4E4LD3QR.js → chunk-PRE7KTM4.js} +2 -2
  28. package/dist/{chunk-ZE74H5BR.js → chunk-RW54ZMBM.js} +26 -20
  29. package/dist/chunk-RW54ZMBM.js.map +1 -0
  30. package/dist/{chunk-O5OH5MRX.js → chunk-UCZ24SUE.js} +3 -3
  31. package/dist/chunk-UCZ24SUE.js.map +1 -0
  32. package/dist/{chunk-INW24J2W.js → chunk-UERERX6M.js} +2 -2
  33. package/dist/{chunk-IP7SMKIF.js → chunk-UJL4HI2R.js} +59 -60
  34. package/dist/chunk-UJL4HI2R.js.map +1 -0
  35. package/dist/{chunk-ZWFBBPJI.js → chunk-ZLIHIUDQ.js} +4 -2
  36. package/dist/chunk-ZLIHIUDQ.js.map +1 -0
  37. package/dist/{claude-LUZ35IMK.js → claude-KIZYXTSG.js} +4 -2
  38. package/dist/{cleanup-3MONU4PU.js → cleanup-6WYUD5SN.js} +17 -15
  39. package/dist/{cleanup-3MONU4PU.js.map → cleanup-6WYUD5SN.js.map} +1 -1
  40. package/dist/cli.js +207 -71
  41. package/dist/cli.js.map +1 -1
  42. package/dist/{contribute-UWJAGIG7.js → contribute-7YJHZTO7.js} +3 -2
  43. package/dist/{contribute-UWJAGIG7.js.map → contribute-7YJHZTO7.js.map} +1 -1
  44. package/dist/{feedback-W3BXTGIM.js → feedback-752MGDPG.js} +10 -8
  45. package/dist/{feedback-W3BXTGIM.js.map → feedback-752MGDPG.js.map} +1 -1
  46. package/dist/{git-34Z6QVDS.js → git-TAFVDB3J.js} +5 -2
  47. package/dist/{ignite-KVJEFXNO.js → ignite-OAMDUN27.js} +13 -11
  48. package/dist/{ignite-KVJEFXNO.js.map → ignite-OAMDUN27.js.map} +1 -1
  49. package/dist/index.d.ts +20 -7
  50. package/dist/index.js +276 -294
  51. package/dist/index.js.map +1 -1
  52. package/dist/{init-L55Q73H4.js → init-7IIM35LQ.js} +12 -9
  53. package/dist/{init-L55Q73H4.js.map → init-7IIM35LQ.js.map} +1 -1
  54. package/dist/mcp/issue-management-server.js +8 -1
  55. package/dist/mcp/issue-management-server.js.map +1 -1
  56. package/dist/{neon-helpers-WPUACUVC.js → neon-helpers-5HBYO2VP.js} +2 -2
  57. package/dist/{open-LNRZL3UU.js → open-FCHKQ77R.js} +27 -14
  58. package/dist/open-FCHKQ77R.js.map +1 -0
  59. package/dist/prompts/init-prompt.txt +7 -1
  60. package/dist/{rebase-C4WNCVGM.js → rebase-Q7WXK566.js} +10 -8
  61. package/dist/{rebase-C4WNCVGM.js.map → rebase-Q7WXK566.js.map} +1 -1
  62. package/dist/{run-IOGNIOYN.js → run-SJPM6YRI.js} +27 -14
  63. package/dist/run-SJPM6YRI.js.map +1 -0
  64. package/dist/schema/settings.schema.json +1 -1
  65. package/dist/{test-git-J7I5MFYH.js → test-git-DEUE656D.js} +5 -5
  66. package/dist/{test-prefix-ZCONBCBX.js → test-prefix-Y6Z6ZHSF.js} +5 -5
  67. package/dist/{test-tabs-RXDBZ6J7.js → test-tabs-PRMRSHKI.js} +3 -2
  68. package/dist/{test-tabs-RXDBZ6J7.js.map → test-tabs-PRMRSHKI.js.map} +1 -1
  69. package/package.json +1 -1
  70. package/dist/ClaudeContextManager-3VXA6UPR.js +0 -13
  71. package/dist/ClaudeService-6CPK43N4.js +0 -12
  72. package/dist/LoomLauncher-JF7JZMTZ.js.map +0 -1
  73. package/dist/chunk-4BGK7T6X.js.map +0 -1
  74. package/dist/chunk-G2IEYOLQ.js.map +0 -1
  75. package/dist/chunk-HBYZH6GD.js.map +0 -1
  76. package/dist/chunk-IP7SMKIF.js.map +0 -1
  77. package/dist/chunk-O5OH5MRX.js.map +0 -1
  78. package/dist/chunk-ZBQVSHVT.js.map +0 -1
  79. package/dist/chunk-ZE74H5BR.js.map +0 -1
  80. package/dist/chunk-ZWFBBPJI.js.map +0 -1
  81. package/dist/open-LNRZL3UU.js.map +0 -1
  82. package/dist/run-IOGNIOYN.js.map +0 -1
  83. package/dist/terminal-BIRBZ4AZ.js +0 -16
  84. package/dist/terminal-BIRBZ4AZ.js.map +0 -1
  85. /package/dist/{BranchNamingService-OMWKUYMM.js.map → BranchNamingService-JYO746H7.js.map} +0 -0
  86. /package/dist/{ClaudeContextManager-3VXA6UPR.js.map → ClaudeContextManager-5WPRJIIW.js.map} +0 -0
  87. /package/dist/{ClaudeService-6CPK43N4.js.map → ClaudeService-Z4KA7QOW.js.map} +0 -0
  88. /package/dist/{GitHubService-EBOETDIW.js.map → GitHubService-UAMH7DMF.js.map} +0 -0
  89. /package/dist/{SettingsManager-ZCWJ56WP.js.map → SettingsManager-MTVX57WR.js.map} +0 -0
  90. /package/dist/{chunk-U5QDY7ZD.js.map → chunk-A2P7NZTB.js.map} +0 -0
  91. /package/dist/{chunk-XPKDPZ5D.js.map → chunk-C7ASXK6J.js.map} +0 -0
  92. /package/dist/{chunk-IXKLYTWO.js.map → chunk-FOV7RRQ2.js.map} +0 -0
  93. /package/dist/{chunk-RO26VS3W.js.map → chunk-FXMLNKLT.js.map} +0 -0
  94. /package/dist/{chunk-TSKY3JI7.js.map → chunk-OAP6SASD.js.map} +0 -0
  95. /package/dist/{chunk-4E4LD3QR.js.map → chunk-PRE7KTM4.js.map} +0 -0
  96. /package/dist/{chunk-INW24J2W.js.map → chunk-UERERX6M.js.map} +0 -0
  97. /package/dist/{claude-LUZ35IMK.js.map → claude-KIZYXTSG.js.map} +0 -0
  98. /package/dist/{git-34Z6QVDS.js.map → git-TAFVDB3J.js.map} +0 -0
  99. /package/dist/{neon-helpers-WPUACUVC.js.map → neon-helpers-5HBYO2VP.js.map} +0 -0
  100. /package/dist/{test-git-J7I5MFYH.js.map → test-git-DEUE656D.js.map} +0 -0
  101. /package/dist/{test-prefix-ZCONBCBX.js.map → test-prefix-Y6Z6ZHSF.js.map} +0 -0
package/dist/cli.js CHANGED
@@ -1,28 +1,20 @@
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,
11
7
  ResourceCleanup
12
- } from "./chunk-HBYZH6GD.js";
8
+ } from "./chunk-KG343GSG.js";
13
9
  import {
14
- IdentifierParser,
15
- loadEnvIntoProcess
16
- } from "./chunk-IP7SMKIF.js";
10
+ IdentifierParser
11
+ } from "./chunk-OXAM2WVC.js";
17
12
  import {
18
13
  ProcessManager
19
14
  } from "./chunk-VU3QMIP2.js";
20
- import {
21
- createNeonProviderFromSettings
22
- } from "./chunk-JQFO7QQN.js";
23
15
  import {
24
16
  ShellCompletion
25
- } from "./chunk-4E4LD3QR.js";
17
+ } from "./chunk-PRE7KTM4.js";
26
18
  import {
27
19
  getConfiguredRepoFromSettings,
28
20
  getEffectivePRTargetRemote,
@@ -31,19 +23,23 @@ import {
31
23
  } from "./chunk-PA6Q6AWM.js";
32
24
  import {
33
25
  IssueEnhancementService
34
- } from "./chunk-ZBQVSHVT.js";
35
- import {
36
- AgentManager
37
- } from "./chunk-OC4H6HJD.js";
26
+ } from "./chunk-GOG3ZB7O.js";
38
27
  import {
39
28
  openBrowser
40
29
  } from "./chunk-YETJNRQM.js";
41
30
  import {
42
31
  MergeManager
43
- } from "./chunk-IXKLYTWO.js";
32
+ } from "./chunk-FOV7RRQ2.js";
33
+ import {
34
+ IssueTrackerFactory,
35
+ generateIssueManagementMcpConfig
36
+ } from "./chunk-FXMLNKLT.js";
37
+ import {
38
+ AgentManager
39
+ } from "./chunk-OC4H6HJD.js";
44
40
  import {
45
41
  GitWorktreeManager
46
- } from "./chunk-TSKY3JI7.js";
42
+ } from "./chunk-OAP6SASD.js";
47
43
  import {
48
44
  detectPackageManager,
49
45
  installDependencies,
@@ -51,16 +47,12 @@ import {
51
47
  } from "./chunk-ZT3YZB4K.js";
52
48
  import {
53
49
  ClaudeContextManager
54
- } from "./chunk-XPKDPZ5D.js";
55
- import "./chunk-U5QDY7ZD.js";
56
- import {
57
- detectClaudeCli,
58
- launchClaude
59
- } from "./chunk-ZWFBBPJI.js";
50
+ } from "./chunk-C7ASXK6J.js";
51
+ import "./chunk-A2P7NZTB.js";
60
52
  import "./chunk-WEN5C5DM.js";
61
53
  import {
62
54
  DefaultBranchNamingService
63
- } from "./chunk-INW24J2W.js";
55
+ } from "./chunk-UERERX6M.js";
64
56
  import {
65
57
  ProjectCapabilityDetector
66
58
  } from "./chunk-EBISESAP.js";
@@ -72,15 +64,20 @@ import {
72
64
  extractSettingsOverrides
73
65
  } from "./chunk-GYCR2LOU.js";
74
66
  import {
75
- SettingsManager
76
- } from "./chunk-O5OH5MRX.js";
67
+ createNeonProviderFromSettings
68
+ } from "./chunk-GVICXJHW.js";
77
69
  import {
78
70
  executeGitCommand,
79
71
  extractIssueNumber,
80
72
  findMainWorktreePathWithSettings,
81
73
  pushBranchToRemote
82
- } from "./chunk-4BGK7T6X.js";
83
- import "./chunk-G2IEYOLQ.js";
74
+ } from "./chunk-5NTD4MCZ.js";
75
+ import {
76
+ SettingsManager
77
+ } from "./chunk-UCZ24SUE.js";
78
+ import {
79
+ GitHubService
80
+ } from "./chunk-F4ENT6AC.js";
84
81
  import {
85
82
  executeGhCommand
86
83
  } from "./chunk-3RUPPQRG.js";
@@ -89,6 +86,14 @@ import {
89
86
  waitForKeypress
90
87
  } from "./chunk-JKXJ7BGL.js";
91
88
  import "./chunk-ZZZWQGTS.js";
89
+ import {
90
+ detectClaudeCli,
91
+ launchClaude
92
+ } from "./chunk-ZLIHIUDQ.js";
93
+ import "./chunk-RW54ZMBM.js";
94
+ import {
95
+ loadEnvIntoProcess
96
+ } from "./chunk-UJL4HI2R.js";
92
97
  import {
93
98
  logger
94
99
  } from "./chunk-GEHQXLEI.js";
@@ -131,7 +136,7 @@ async function launchFirstRunSetup() {
131
136
  );
132
137
  const { waitForKeypress: waitForKeypress2 } = await import("./prompt-7INJ7YRU.js");
133
138
  await waitForKeypress2("Press any key to start configuration...");
134
- const { InitCommand } = await import("./init-L55Q73H4.js");
139
+ const { InitCommand } = await import("./init-7IIM35LQ.js");
135
140
  const initCommand = new InitCommand();
136
141
  await initCommand.execute(
137
142
  "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."
@@ -208,8 +213,7 @@ var StartCommand = class {
208
213
  }
209
214
  }
210
215
  let repo;
211
- const multipleRemotes = await hasMultipleRemotes();
212
- if (multipleRemotes) {
216
+ if (this.issueTracker.providerName === "github" && await hasMultipleRemotes()) {
213
217
  repo = await getConfiguredRepoFromSettings(initialSettings);
214
218
  logger.info(`Using GitHub repository: ${repo}`);
215
219
  }
@@ -529,8 +533,7 @@ var AddIssueCommand = class {
529
533
  const { description } = input;
530
534
  const settings = await this.settingsManager.loadSettings();
531
535
  let repo;
532
- const multipleRemotes = await hasMultipleRemotes();
533
- if (multipleRemotes) {
536
+ if (this.enhancementService.issueTracker.providerName === "github" && await hasMultipleRemotes()) {
534
537
  repo = await getConfiguredRepoFromSettings(settings);
535
538
  logger.info(`Using GitHub repository: ${repo}`);
536
539
  }
@@ -569,8 +572,7 @@ var EnhanceCommand = class {
569
572
  const { author } = options;
570
573
  const settings = await this.settingsManager.loadSettings();
571
574
  let repo;
572
- const multipleRemotes = await hasMultipleRemotes();
573
- if (multipleRemotes) {
575
+ if (this.issueTracker.providerName === "github" && await hasMultipleRemotes()) {
574
576
  repo = await getConfiguredRepoFromSettings(settings);
575
577
  logger.info(`Using GitHub repository: ${repo}`);
576
578
  }
@@ -1719,7 +1721,7 @@ var FinishCommand = class {
1719
1721
  const neonProvider = createNeonProviderFromSettings(settings);
1720
1722
  const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName);
1721
1723
  const cliIsolationManager = new CLIIsolationManager();
1722
- const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-OMWKUYMM.js");
1724
+ const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-JYO746H7.js");
1723
1725
  this.loomManager ??= new LoomManager(
1724
1726
  this.gitWorktreeManager,
1725
1727
  this.issueTracker,
@@ -1777,11 +1779,12 @@ var FinishCommand = class {
1777
1779
  * Main entry point for finish command
1778
1780
  */
1779
1781
  async execute(input) {
1782
+ var _a;
1780
1783
  try {
1781
1784
  const settings = await this.settingsManager.loadSettings();
1782
1785
  let repo;
1783
- const multipleRemotes = await hasMultipleRemotes();
1784
- if (multipleRemotes) {
1786
+ const needsRepo = ((_a = settings.mergeBehavior) == null ? void 0 : _a.mode) === "github-pr" || this.issueTracker.providerName === "github";
1787
+ if (needsRepo && await hasMultipleRemotes()) {
1785
1788
  repo = await getConfiguredRepoFromSettings(settings);
1786
1789
  logger.info(`Using GitHub repository: ${repo}`);
1787
1790
  }
@@ -2081,6 +2084,11 @@ var FinishCommand = class {
2081
2084
  const settings = await this.settingsManager.loadSettings(worktree.path);
2082
2085
  const mergeBehavior = settings.mergeBehavior ?? { mode: "local" };
2083
2086
  if (mergeBehavior.mode === "github-pr") {
2087
+ if (!this.issueTracker.supportsPullRequests) {
2088
+ throw new Error(
2089
+ `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.`
2090
+ );
2091
+ }
2084
2092
  await this.executeGitHubPRWorkflow(parsed, options, worktree, settings);
2085
2093
  return;
2086
2094
  }
@@ -2459,6 +2467,66 @@ function getPackageInfo(scriptPath) {
2459
2467
 
2460
2468
  // src/cli.ts
2461
2469
  import { fileURLToPath as fileURLToPath2 } from "url";
2470
+ import { realpathSync } from "fs";
2471
+
2472
+ // src/utils/loom-formatter.ts
2473
+ function determineLoomType(worktree) {
2474
+ const prPathPattern = /_pr_\d+$/;
2475
+ if (prPathPattern.test(worktree.path)) {
2476
+ return "pr";
2477
+ }
2478
+ const issueNumber = extractIssueNumber(worktree.branch);
2479
+ if (issueNumber !== null) {
2480
+ return "issue";
2481
+ }
2482
+ return "branch";
2483
+ }
2484
+ function extractPRNumbers(path4) {
2485
+ if (!path4) {
2486
+ return [];
2487
+ }
2488
+ const prPathPattern = /_pr_(\d+)$/;
2489
+ const match = path4.match(prPathPattern);
2490
+ if (match == null ? void 0 : match[1]) {
2491
+ return [match[1]];
2492
+ }
2493
+ return [];
2494
+ }
2495
+ function extractIssueNumbers(branch) {
2496
+ if (!branch) {
2497
+ return [];
2498
+ }
2499
+ const issueNumber = extractIssueNumber(branch);
2500
+ if (issueNumber === null) {
2501
+ return [];
2502
+ }
2503
+ return [issueNumber];
2504
+ }
2505
+ function formatLoomForJson(worktree, mainWorktreePath) {
2506
+ const loomType = determineLoomType(worktree);
2507
+ let issueNumbers = [];
2508
+ let prNumbers = [];
2509
+ if (loomType === "pr") {
2510
+ prNumbers = extractPRNumbers(worktree.path);
2511
+ } else if (loomType === "issue") {
2512
+ issueNumbers = extractIssueNumbers(worktree.branch);
2513
+ }
2514
+ const isMainWorktree = mainWorktreePath ? worktree.path === mainWorktreePath : false;
2515
+ return {
2516
+ name: worktree.branch || worktree.path,
2517
+ worktreePath: worktree.bare ? null : worktree.path,
2518
+ branch: worktree.branch || null,
2519
+ type: loomType,
2520
+ issue_numbers: issueNumbers,
2521
+ pr_numbers: prNumbers,
2522
+ isMainWorktree
2523
+ };
2524
+ }
2525
+ function formatLoomsForJson(worktrees, mainWorktreePath) {
2526
+ return worktrees.map((wt) => formatLoomForJson(wt, mainWorktreePath));
2527
+ }
2528
+
2529
+ // src/cli.ts
2462
2530
  var __filename = fileURLToPath2(import.meta.url);
2463
2531
  var packageJson = getPackageInfo(__filename);
2464
2532
  function parseIssueIdentifier(value) {
@@ -2490,6 +2558,7 @@ program.name("iloom").description(packageJson.description).version(packageJson.v
2490
2558
  logger.debug(`Settings migration failed: ${error instanceof Error ? error.message : "Unknown"}`);
2491
2559
  }
2492
2560
  await validateSettingsForCommand(thisCommand);
2561
+ await validateGhCliForCommand(thisCommand);
2493
2562
  });
2494
2563
  async function validateSettingsForCommand(command) {
2495
2564
  var _a, _b;
@@ -2501,8 +2570,7 @@ async function validateSettingsForCommand(command) {
2501
2570
  try {
2502
2571
  const settingsManager = new SettingsManager();
2503
2572
  const settings = await settingsManager.loadSettings();
2504
- const { hasMultipleRemotes: hasMultipleRemotes2 } = await import("./remote-VUNCQZ6J.js");
2505
- const multipleRemotes = await hasMultipleRemotes2();
2573
+ const multipleRemotes = await hasMultipleRemotes();
2506
2574
  if (multipleRemotes && !((_b = (_a = settings.issueManagement) == null ? void 0 : _a.github) == null ? void 0 : _b.remote)) {
2507
2575
  await autoLaunchInitForMultipleRemotes();
2508
2576
  return;
@@ -2513,6 +2581,59 @@ async function validateSettingsForCommand(command) {
2513
2581
  process.exit(1);
2514
2582
  }
2515
2583
  }
2584
+ async function validateGhCliForCommand(command) {
2585
+ var _a, _b;
2586
+ const commandName = command.args[0] ?? "";
2587
+ const alwaysRequireGh = ["feedback", "contribute"];
2588
+ const conditionallyRequireGh = ["start", "finish", "enhance", "add-issue", "ignite", "spin"];
2589
+ const warnOnly = ["init", "list", "rebase", "cleanup", "run", "update", "open"];
2590
+ if (commandName.startsWith("test-") || commandName === "help") {
2591
+ return;
2592
+ }
2593
+ const ghAvailable = GitHubService.isCliAvailable();
2594
+ let needsGhCli = alwaysRequireGh.includes(commandName);
2595
+ if (!needsGhCli && conditionallyRequireGh.includes(commandName)) {
2596
+ try {
2597
+ const settingsManager = new SettingsManager();
2598
+ const settings = await settingsManager.loadSettings();
2599
+ const provider = IssueTrackerFactory.getProviderName(settings);
2600
+ const mergeBehaviorMode = (_a = settings.mergeBehavior) == null ? void 0 : _a.mode;
2601
+ needsGhCli = provider === "github" || mergeBehaviorMode === "github-pr";
2602
+ } catch {
2603
+ needsGhCli = true;
2604
+ }
2605
+ }
2606
+ if (!ghAvailable) {
2607
+ if (needsGhCli) {
2608
+ 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.`;
2609
+ logger.error(errorMessage);
2610
+ logger.info("");
2611
+ logger.info("To install GitHub CLI:");
2612
+ logger.info(" \u2022 macOS: brew install gh");
2613
+ logger.info(" \u2022 Windows: winget install GitHub.cli");
2614
+ logger.info(" \u2022 Linux: https://github.com/cli/cli#installation");
2615
+ logger.info("");
2616
+ logger.info("After installation, authenticate with: gh auth login");
2617
+ process.exit(1);
2618
+ } else if (warnOnly.includes(commandName)) {
2619
+ try {
2620
+ const settingsManager = new SettingsManager();
2621
+ const settings = await settingsManager.loadSettings();
2622
+ const provider = IssueTrackerFactory.getProviderName(settings);
2623
+ const mergeBehaviorMode = (_b = settings.mergeBehavior) == null ? void 0 : _b.mode;
2624
+ if (provider === "github" || mergeBehaviorMode === "github-pr") {
2625
+ logger.warn("GitHub CLI (gh) is not installed.");
2626
+ logger.warn(
2627
+ "Some features may not work correctly with your current configuration (GitHub provider or github-pr merge mode)."
2628
+ );
2629
+ logger.info("To install: brew install gh (macOS) or see https://github.com/cli/cli#installation");
2630
+ logger.info("");
2631
+ }
2632
+ } catch {
2633
+ }
2634
+ }
2635
+ }
2636
+ }
2516
2637
  async function autoLaunchInitForMultipleRemotes() {
2517
2638
  var _a, _b;
2518
2639
  logger.info("Multiple git remotes detected, but no GitHub remote is configured.");
@@ -2524,14 +2645,14 @@ async function autoLaunchInitForMultipleRemotes() {
2524
2645
  await waitForKeypress2("Press any key to start configuration...");
2525
2646
  logger.info("");
2526
2647
  try {
2527
- const { InitCommand } = await import("./init-L55Q73H4.js");
2648
+ const { InitCommand } = await import("./init-7IIM35LQ.js");
2528
2649
  const initCommand = new InitCommand();
2529
2650
  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
2651
  await initCommand.execute(customInitialMessage);
2531
2652
  logger.info("");
2532
2653
  logger.info("Configuration complete! Continuing with your original command...");
2533
2654
  logger.info("");
2534
- const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-ZCWJ56WP.js");
2655
+ const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-MTVX57WR.js");
2535
2656
  const settingsManager = new SettingsManager2();
2536
2657
  const settings = await settingsManager.loadSettings();
2537
2658
  const { hasMultipleRemotes: hasMultipleRemotes2 } = await import("./remote-VUNCQZ6J.js");
@@ -2550,7 +2671,7 @@ async function autoLaunchInitForMultipleRemotes() {
2550
2671
  }
2551
2672
  var shellCompletion = new ShellCompletion();
2552
2673
  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(
2674
+ 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
2675
  new Option("--one-shot <mode>", "One-shot automation mode").choices(["default", "noReview", "bypassPermissions"]).default("default")
2555
2676
  ).action(async (identifier, options) => {
2556
2677
  try {
@@ -2593,7 +2714,7 @@ program.command("add-issue").alias("a").description("Create and enhance GitHub i
2593
2714
  });
2594
2715
  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
2716
  try {
2596
- const { FeedbackCommand } = await import("./feedback-W3BXTGIM.js");
2717
+ const { FeedbackCommand } = await import("./feedback-752MGDPG.js");
2597
2718
  const command = new FeedbackCommand();
2598
2719
  const feedbackOptions = {};
2599
2720
  if (options.body !== void 0) {
@@ -2644,7 +2765,7 @@ program.command("finish").alias("dn").description("Merge work and cleanup worksp
2644
2765
  });
2645
2766
  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
2767
  try {
2647
- const { RebaseCommand } = await import("./rebase-C4WNCVGM.js");
2768
+ const { RebaseCommand } = await import("./rebase-Q7WXK566.js");
2648
2769
  const command = new RebaseCommand();
2649
2770
  await command.execute(options);
2650
2771
  } catch (error) {
@@ -2656,7 +2777,7 @@ program.command("spin").alias("ignite").description("Launch Claude with auto-det
2656
2777
  new Option("--one-shot <mode>", "One-shot automation mode").choices(["default", "noReview", "bypassPermissions"]).default("default")
2657
2778
  ).action(async (options) => {
2658
2779
  try {
2659
- const { IgniteCommand } = await import("./ignite-KVJEFXNO.js");
2780
+ const { IgniteCommand } = await import("./ignite-OAMDUN27.js");
2660
2781
  const command = new IgniteCommand();
2661
2782
  await command.execute(options.oneShot ?? "default");
2662
2783
  } catch (error) {
@@ -2667,7 +2788,7 @@ program.command("spin").alias("ignite").description("Launch Claude with auto-det
2667
2788
  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
2789
  try {
2669
2790
  const args = (command == null ? void 0 : command.args) ? command.args.slice(identifier ? 1 : 0) : [];
2670
- const { OpenCommand } = await import("./open-LNRZL3UU.js");
2791
+ const { OpenCommand } = await import("./open-FCHKQ77R.js");
2671
2792
  const cmd = new OpenCommand();
2672
2793
  const input = identifier ? { identifier, args } : { args };
2673
2794
  await cmd.execute(input);
@@ -2679,7 +2800,7 @@ program.command("open").description("Open workspace in browser or run CLI tool")
2679
2800
  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
2801
  try {
2681
2802
  const args = (command == null ? void 0 : command.args) ? command.args.slice(identifier ? 1 : 0) : [];
2682
- const { RunCommand } = await import("./run-IOGNIOYN.js");
2803
+ const { RunCommand } = await import("./run-SJPM6YRI.js");
2683
2804
  const cmd = new RunCommand();
2684
2805
  const input = identifier ? { identifier, args } : { args };
2685
2806
  await cmd.execute(input);
@@ -2688,9 +2809,9 @@ program.command("run").description("Run CLI tool or open workspace in browser").
2688
2809
  process.exit(1);
2689
2810
  }
2690
2811
  });
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) => {
2812
+ 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
2813
  try {
2693
- const { CleanupCommand } = await import("./cleanup-3MONU4PU.js");
2814
+ const { CleanupCommand } = await import("./cleanup-6WYUD5SN.js");
2694
2815
  const command = new CleanupCommand();
2695
2816
  const input = {
2696
2817
  options: options ?? {}
@@ -2709,7 +2830,8 @@ program.command("list").description("Show active workspaces").option("--json", "
2709
2830
  const manager = new GitWorktreeManager();
2710
2831
  const worktrees = await manager.listWorktrees({ porcelain: true });
2711
2832
  if (options.json) {
2712
- console.log(JSON.stringify(worktrees, null, 2));
2833
+ const mainWorktreePath = await findMainWorktreePathWithSettings();
2834
+ console.log(JSON.stringify(formatLoomsForJson(worktrees, mainWorktreePath), null, 2));
2713
2835
  return;
2714
2836
  }
2715
2837
  if (worktrees.length === 0) {
@@ -2738,7 +2860,7 @@ program.command("list").description("Show active workspaces").option("--json", "
2738
2860
  });
2739
2861
  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
2862
  try {
2741
- const { InitCommand } = await import("./init-L55Q73H4.js");
2863
+ const { InitCommand } = await import("./init-7IIM35LQ.js");
2742
2864
  const command = new InitCommand();
2743
2865
  const trimmedPrompt = prompt == null ? void 0 : prompt.trim();
2744
2866
  const customPrompt = trimmedPrompt && trimmedPrompt.length > 0 ? trimmedPrompt : void 0;
@@ -2750,7 +2872,7 @@ program.command("init").alias("config").description("Initialize iloom configurat
2750
2872
  });
2751
2873
  program.command("contribute").description("Set up local development environment for contributing to iloom").action(async () => {
2752
2874
  try {
2753
- const { ContributeCommand } = await import("./contribute-UWJAGIG7.js");
2875
+ const { ContributeCommand } = await import("./contribute-7YJHZTO7.js");
2754
2876
  const command = new ContributeCommand();
2755
2877
  await command.execute();
2756
2878
  } catch (error) {
@@ -2770,10 +2892,10 @@ program.command("update").description("Update iloom-cli to the latest version").
2770
2892
  });
2771
2893
  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
2894
  try {
2773
- const { GitHubService } = await import("./GitHubService-EBOETDIW.js");
2774
- const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-OMWKUYMM.js");
2895
+ const { GitHubService: GitHubService2 } = await import("./GitHubService-UAMH7DMF.js");
2896
+ const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-JYO746H7.js");
2775
2897
  logger.info("Testing GitHub Integration\n");
2776
- const service = new GitHubService();
2898
+ const service = new GitHubService2();
2777
2899
  const branchNaming = new DefaultBranchNamingService2({ useClaude: options.claude !== false });
2778
2900
  logger.info("Detecting input type...");
2779
2901
  const detection = await service.detectInputType(identifier);
@@ -2829,10 +2951,10 @@ program.command("test-github").description("Test GitHub integration (Issue #3)")
2829
2951
  });
2830
2952
  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
2953
  try {
2832
- const { detectClaudeCli: detectClaudeCli2, getClaudeVersion, generateBranchName, launchClaude: launchClaude2 } = await import("./claude-LUZ35IMK.js");
2954
+ const { detectClaudeCli: detectClaudeCli2, getClaudeVersion, generateBranchName, launchClaude: launchClaude2 } = await import("./claude-KIZYXTSG.js");
2833
2955
  const { PromptTemplateManager } = await import("./PromptTemplateManager-A52RUAMS.js");
2834
- const { ClaudeService } = await import("./ClaudeService-6CPK43N4.js");
2835
- const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-3VXA6UPR.js");
2956
+ const { ClaudeService } = await import("./ClaudeService-Z4KA7QOW.js");
2957
+ const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-5WPRJIIW.js");
2836
2958
  logger.info("Testing Claude Integration\n");
2837
2959
  if (options.detect) {
2838
2960
  logger.info("Detecting Claude CLI...");
@@ -2980,7 +3102,7 @@ program.command("test-webserver").description("Test if a web server is running o
2980
3102
  });
2981
3103
  program.command("test-git").description("Test Git integration - findMainWorktreePath() function (reads .iloom/settings.json)").action(async () => {
2982
3104
  try {
2983
- const { TestGitCommand } = await import("./test-git-J7I5MFYH.js");
3105
+ const { TestGitCommand } = await import("./test-git-DEUE656D.js");
2984
3106
  const command = new TestGitCommand();
2985
3107
  await command.execute();
2986
3108
  } catch (error) {
@@ -2993,7 +3115,7 @@ program.command("test-git").description("Test Git integration - findMainWorktree
2993
3115
  });
2994
3116
  program.command("test-tabs").description("Test iTerm2 dual tab functionality - opens two tabs with test commands").action(async () => {
2995
3117
  try {
2996
- const { TestTabsCommand } = await import("./test-tabs-RXDBZ6J7.js");
3118
+ const { TestTabsCommand } = await import("./test-tabs-PRMRSHKI.js");
2997
3119
  const command = new TestTabsCommand();
2998
3120
  await command.execute();
2999
3121
  } catch (error) {
@@ -3006,7 +3128,7 @@ program.command("test-tabs").description("Test iTerm2 dual tab functionality - o
3006
3128
  });
3007
3129
  program.command("test-prefix").description("Test worktree prefix configuration - preview worktree paths (reads .iloom/settings.json)").action(async () => {
3008
3130
  try {
3009
- const { TestPrefixCommand } = await import("./test-prefix-ZCONBCBX.js");
3131
+ const { TestPrefixCommand } = await import("./test-prefix-Y6Z6ZHSF.js");
3010
3132
  const command = new TestPrefixCommand();
3011
3133
  await command.execute();
3012
3134
  } catch (error) {
@@ -3020,8 +3142,8 @@ program.command("test-prefix").description("Test worktree prefix configuration -
3020
3142
  program.command("test-neon").description("Test Neon integration and debug configuration").action(async () => {
3021
3143
  var _a;
3022
3144
  try {
3023
- const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-ZCWJ56WP.js");
3024
- const { createNeonProviderFromSettings: createNeonProviderFromSettings2 } = await import("./neon-helpers-WPUACUVC.js");
3145
+ const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-MTVX57WR.js");
3146
+ const { createNeonProviderFromSettings: createNeonProviderFromSettings2 } = await import("./neon-helpers-5HBYO2VP.js");
3025
3147
  logger.info("Testing Neon Integration\n");
3026
3148
  logger.info("1. Settings Configuration:");
3027
3149
  const settingsManager = new SettingsManager2();
@@ -3099,12 +3221,26 @@ program.command("help").description("Display help information").argument("[comma
3099
3221
  }
3100
3222
  process.exit(0);
3101
3223
  });
3102
- try {
3103
- await program.parseAsync();
3104
- } catch (error) {
3105
- if (error instanceof Error) {
3106
- logger.error(`Error: ${error.message}`);
3107
- process.exit(1);
3224
+ var isRunDirectly = process.argv[1] && (() => {
3225
+ try {
3226
+ const scriptPath = realpathSync(process.argv[1]);
3227
+ const modulePath = fileURLToPath2(import.meta.url);
3228
+ return scriptPath === modulePath;
3229
+ } catch {
3230
+ return true;
3231
+ }
3232
+ })();
3233
+ if (isRunDirectly) {
3234
+ try {
3235
+ await program.parseAsync();
3236
+ } catch (error) {
3237
+ if (error instanceof Error) {
3238
+ logger.error(`Error: ${error.message}`);
3239
+ process.exit(1);
3240
+ }
3108
3241
  }
3109
3242
  }
3243
+ export {
3244
+ validateGhCliForCommand
3245
+ };
3110
3246
  //# sourceMappingURL=cli.js.map