@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/index.js CHANGED
@@ -226,7 +226,7 @@ var init_SettingsManager = __esm({
226
226
  IloomSettingsSchema = z.object({
227
227
  mainBranch: z.string().min(1, "Settings 'mainBranch' cannot be empty").optional().describe("Name of the main/primary branch for the repository"),
228
228
  sourceEnvOnStart: z.boolean().default(false).describe(
229
- "Source .env file when launching terminal processes (Claude, dev server, terminal). NOTE TO AI AGENTS: Before making changes to settings files, YOU MUST OFFER to check .env compatibility. WARNING: Unquoted values in .env files may break sourcing in bash/zsh shells. Before enabling, verify your .env file does not contain unquoted special characters (e.g., database URLs with ?, &, or other shell metacharacters). Shell compatibility issues may cause processes to fail or behave unexpectedly."
229
+ "Source all dotenv-flow files (.env, .env.local, .env.development, .env.development.local) when launching terminal processes (Claude, dev server, terminal). Files are sourced in precedence order so later files override earlier ones. NOTE TO AI AGENTS: Before making changes to settings files, YOU MUST OFFER to check .env file compatibility. WARNING: Unquoted values in .env files may break sourcing in bash/zsh shells. Before enabling, verify ALL your .env.* files do not contain unquoted special characters (e.g., database URLs with ?, &, or other shell metacharacters). Shell compatibility issues may cause processes to fail or behave unexpectedly."
230
230
  ),
231
231
  worktreePrefix: z.string().optional().refine(
232
232
  (val) => {
@@ -282,7 +282,7 @@ var init_SettingsManager = __esm({
282
282
  IloomSettingsSchemaNoDefaults = z.object({
283
283
  mainBranch: z.string().min(1, "Settings 'mainBranch' cannot be empty").optional().describe("Name of the main/primary branch for the repository"),
284
284
  sourceEnvOnStart: z.boolean().optional().describe(
285
- "Source .env file when launching terminal processes (Claude, dev server, terminal). NOTE TO AI AGENTS: Before making changes to settings files, YOU MUST OFFER to check .env compatibility. WARNING: Unquoted values in .env files may break sourcing in bash/zsh shells. Before enabling, verify your .env file does not contain unquoted special characters (e.g., database URLs with ?, &, or other shell metacharacters). Shell compatibility issues may cause processes to fail or behave unexpectedly."
285
+ "Source all dotenv-flow files (.env, .env.local, .env.development, .env.development.local) when launching terminal processes (Claude, dev server, terminal). Files are sourced in precedence order so later files override earlier ones. NOTE TO AI AGENTS: Before making changes to settings files, YOU MUST OFFER to check .env compatibility. WARNING: Unquoted values in .env files may break sourcing in bash/zsh shells. Before enabling, verify ALL your .env.* files do not contain unquoted special characters (e.g., database URLs with ?, &, or other shell metacharacters). Shell compatibility issues may cause processes to fail or behave unexpectedly."
286
286
  ),
287
287
  worktreePrefix: z.string().optional().refine(
288
288
  (val) => {
@@ -433,8 +433,8 @@ Note: CLI overrides were applied. Check your --set arguments.`);
433
433
  */
434
434
  formatAllZodErrors(error, settingsPath) {
435
435
  const errorMessages = error.issues.map((issue) => {
436
- const path5 = issue.path.length > 0 ? issue.path.join(".") : "root";
437
- return ` - ${path5}: ${issue.message}`;
436
+ const path6 = issue.path.length > 0 ? issue.path.join(".") : "root";
437
+ return ` - ${path6}: ${issue.message}`;
438
438
  });
439
439
  return new Error(
440
440
  `Settings validation failed at ${settingsPath}:
@@ -540,237 +540,6 @@ ${errorMessages.join("\n")}`
540
540
  }
541
541
  });
542
542
 
543
- // src/utils/terminal.ts
544
- var terminal_exports = {};
545
- __export(terminal_exports, {
546
- detectITerm2: () => detectITerm2,
547
- detectPlatform: () => detectPlatform,
548
- openDualTerminalWindow: () => openDualTerminalWindow,
549
- openMultipleTerminalWindows: () => openMultipleTerminalWindows,
550
- openTerminalWindow: () => openTerminalWindow
551
- });
552
- import { execa as execa3 } from "execa";
553
- import { existsSync } from "fs";
554
- function detectPlatform() {
555
- const platform = process.platform;
556
- if (platform === "darwin") return "darwin";
557
- if (platform === "linux") return "linux";
558
- if (platform === "win32") return "win32";
559
- return "unsupported";
560
- }
561
- async function detectITerm2() {
562
- const platform = detectPlatform();
563
- if (platform !== "darwin") return false;
564
- return existsSync("/Applications/iTerm.app");
565
- }
566
- async function openTerminalWindow(options) {
567
- const platform = detectPlatform();
568
- if (platform !== "darwin") {
569
- throw new Error(
570
- `Terminal window launching not yet supported on ${platform}. Currently only macOS is supported.`
571
- );
572
- }
573
- const hasITerm2 = await detectITerm2();
574
- const applescript = hasITerm2 ? buildITerm2SingleTabScript(options) : buildAppleScript(options);
575
- try {
576
- await execa3("osascript", ["-e", applescript]);
577
- if (!hasITerm2) {
578
- await execa3("osascript", ["-e", 'tell application "Terminal" to activate']);
579
- }
580
- } catch (error) {
581
- throw new Error(
582
- `Failed to open terminal window: ${error instanceof Error ? error.message : "Unknown error"}`
583
- );
584
- }
585
- }
586
- function buildAppleScript(options) {
587
- const {
588
- workspacePath,
589
- command,
590
- backgroundColor,
591
- port,
592
- includeEnvSetup,
593
- includePortExport
594
- } = options;
595
- const commands = [];
596
- if (workspacePath) {
597
- commands.push(`cd '${escapePathForAppleScript(workspacePath)}'`);
598
- }
599
- if (includeEnvSetup) {
600
- commands.push("source .env");
601
- }
602
- if (includePortExport && port !== void 0) {
603
- commands.push(`export PORT=${port}`);
604
- }
605
- if (command) {
606
- commands.push(command);
607
- }
608
- const fullCommand = commands.join(" && ");
609
- const historyFreeCommand = ` ${fullCommand}`;
610
- let script = `tell application "Terminal"
611
- `;
612
- script += ` set newTab to do script "${escapeForAppleScript(historyFreeCommand)}"
613
- `;
614
- if (backgroundColor) {
615
- const { r, g, b } = backgroundColor;
616
- script += ` set background color of newTab to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}
617
- `;
618
- }
619
- script += `end tell`;
620
- return script;
621
- }
622
- function escapePathForAppleScript(path5) {
623
- return path5.replace(/'/g, "'\\''");
624
- }
625
- function escapeForAppleScript(command) {
626
- return command.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
627
- }
628
- function buildITerm2SingleTabScript(options) {
629
- const command = buildCommandSequence(options);
630
- let script = 'tell application id "com.googlecode.iterm2"\n';
631
- script += " create window with default profile\n";
632
- script += " set s1 to current session of current window\n\n";
633
- if (options.backgroundColor) {
634
- const { r, g, b } = options.backgroundColor;
635
- script += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}
636
- `;
637
- }
638
- script += ` tell s1 to write text "${escapeForAppleScript(command)}"
639
-
640
- `;
641
- if (options.title) {
642
- script += ` set name of s1 to "${escapeForAppleScript(options.title)}"
643
-
644
- `;
645
- }
646
- script += " activate\n";
647
- script += "end tell";
648
- return script;
649
- }
650
- function buildCommandSequence(options) {
651
- const {
652
- workspacePath,
653
- command,
654
- port,
655
- includeEnvSetup,
656
- includePortExport
657
- } = options;
658
- const commands = [];
659
- if (workspacePath) {
660
- commands.push(`cd '${escapePathForAppleScript(workspacePath)}'`);
661
- }
662
- if (includeEnvSetup) {
663
- commands.push("source .env");
664
- }
665
- if (includePortExport && port !== void 0) {
666
- commands.push(`export PORT=${port}`);
667
- }
668
- if (command) {
669
- commands.push(command);
670
- }
671
- const fullCommand = commands.join(" && ");
672
- return ` ${fullCommand}`;
673
- }
674
- function buildITerm2MultiTabScript(optionsArray) {
675
- if (optionsArray.length < 2) {
676
- throw new Error("buildITerm2MultiTabScript requires at least 2 terminal options");
677
- }
678
- let script = 'tell application id "com.googlecode.iterm2"\n';
679
- script += " create window with default profile\n";
680
- script += " set newWindow to current window\n";
681
- const options1 = optionsArray[0];
682
- if (!options1) {
683
- throw new Error("First terminal option is undefined");
684
- }
685
- const command1 = buildCommandSequence(options1);
686
- script += " set s1 to current session of newWindow\n\n";
687
- if (options1.backgroundColor) {
688
- const { r, g, b } = options1.backgroundColor;
689
- script += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}
690
- `;
691
- }
692
- script += ` tell s1 to write text "${escapeForAppleScript(command1)}"
693
-
694
- `;
695
- if (options1.title) {
696
- script += ` set name of s1 to "${escapeForAppleScript(options1.title)}"
697
-
698
- `;
699
- }
700
- for (let i = 1; i < optionsArray.length; i++) {
701
- const options = optionsArray[i];
702
- if (!options) {
703
- throw new Error(`Terminal option at index ${i} is undefined`);
704
- }
705
- const command = buildCommandSequence(options);
706
- const sessionVar = `s${i + 1}`;
707
- script += " tell newWindow\n";
708
- script += ` set newTab${i} to (create tab with default profile)
709
- `;
710
- script += " end tell\n";
711
- script += ` set ${sessionVar} to current session of newTab${i}
712
-
713
- `;
714
- if (options.backgroundColor) {
715
- const { r, g, b } = options.backgroundColor;
716
- script += ` set background color of ${sessionVar} to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}
717
- `;
718
- }
719
- script += ` tell ${sessionVar} to write text "${escapeForAppleScript(command)}"
720
-
721
- `;
722
- if (options.title) {
723
- script += ` set name of ${sessionVar} to "${escapeForAppleScript(options.title)}"
724
-
725
- `;
726
- }
727
- }
728
- script += " activate\n";
729
- script += "end tell";
730
- return script;
731
- }
732
- async function openMultipleTerminalWindows(optionsArray) {
733
- if (optionsArray.length < 2) {
734
- throw new Error("openMultipleTerminalWindows requires at least 2 terminal options. Use openTerminalWindow for single terminal.");
735
- }
736
- const platform = detectPlatform();
737
- if (platform !== "darwin") {
738
- throw new Error(
739
- `Terminal window launching not yet supported on ${platform}. Currently only macOS is supported.`
740
- );
741
- }
742
- const hasITerm2 = await detectITerm2();
743
- if (hasITerm2) {
744
- const applescript = buildITerm2MultiTabScript(optionsArray);
745
- try {
746
- await execa3("osascript", ["-e", applescript]);
747
- } catch (error) {
748
- throw new Error(
749
- `Failed to open iTerm2 window: ${error instanceof Error ? error.message : "Unknown error"}`
750
- );
751
- }
752
- } else {
753
- for (let i = 0; i < optionsArray.length; i++) {
754
- const options = optionsArray[i];
755
- if (!options) {
756
- throw new Error(`Terminal option at index ${i} is undefined`);
757
- }
758
- await openTerminalWindow(options);
759
- if (i < optionsArray.length - 1) {
760
- await new Promise((resolve) => setTimeout(resolve, 1e3));
761
- }
762
- }
763
- }
764
- }
765
- async function openDualTerminalWindow(options1, options2) {
766
- await openMultipleTerminalWindows([options1, options2]);
767
- }
768
- var init_terminal = __esm({
769
- "src/utils/terminal.ts"() {
770
- "use strict";
771
- }
772
- });
773
-
774
543
  // src/utils/color.ts
775
544
  var color_exports = {};
776
545
  __export(color_exports, {
@@ -951,6 +720,7 @@ import path3 from "path";
951
720
  import fs from "fs-extra";
952
721
 
953
722
  // src/utils/git.ts
723
+ init_SettingsManager();
954
724
  init_logger();
955
725
  import path2 from "path";
956
726
  import { execa } from "execa";
@@ -1097,7 +867,7 @@ function extractIssueNumber(branchName) {
1097
867
  }
1098
868
  return null;
1099
869
  }
1100
- function isWorktreePath(path5) {
870
+ function isWorktreePath(path6) {
1101
871
  const worktreePatterns = [
1102
872
  /\/worktrees?\//i,
1103
873
  // Contains /worktree/ or /worktrees/
@@ -1112,7 +882,7 @@ function isWorktreePath(path5) {
1112
882
  /\.worktree$/i
1113
883
  // ends with .worktree
1114
884
  ];
1115
- return worktreePatterns.some((pattern) => pattern.test(path5));
885
+ return worktreePatterns.some((pattern) => pattern.test(path6));
1116
886
  }
1117
887
  function generateWorktreePath(branchName, rootDir = process.cwd(), options) {
1118
888
  let sanitized = branchName.replace(/\//g, "-");
@@ -1154,31 +924,31 @@ function generateWorktreePath(branchName, rootDir = process.cwd(), options) {
1154
924
  return path2.join(parentDir, `${prefix}${sanitized}`);
1155
925
  }
1156
926
  }
1157
- async function isValidGitRepo(path5) {
927
+ async function isValidGitRepo(path6) {
1158
928
  try {
1159
- await executeGitCommand(["rev-parse", "--git-dir"], { cwd: path5 });
929
+ await executeGitCommand(["rev-parse", "--git-dir"], { cwd: path6 });
1160
930
  return true;
1161
931
  } catch {
1162
932
  return false;
1163
933
  }
1164
934
  }
1165
- async function getCurrentBranch(path5 = process.cwd()) {
935
+ async function getCurrentBranch(path6 = process.cwd()) {
1166
936
  try {
1167
- const result = await executeGitCommand(["branch", "--show-current"], { cwd: path5 });
937
+ const result = await executeGitCommand(["branch", "--show-current"], { cwd: path6 });
1168
938
  return result.trim();
1169
939
  } catch {
1170
940
  return null;
1171
941
  }
1172
942
  }
1173
- async function branchExists(branchName, path5 = process.cwd(), includeRemote = true) {
943
+ async function branchExists(branchName, path6 = process.cwd(), includeRemote = true) {
1174
944
  try {
1175
- const localResult = await executeGitCommand(["branch", "--list", branchName], { cwd: path5 });
945
+ const localResult = await executeGitCommand(["branch", "--list", branchName], { cwd: path6 });
1176
946
  if (localResult.trim()) {
1177
947
  return true;
1178
948
  }
1179
949
  if (includeRemote) {
1180
950
  const remoteResult = await executeGitCommand(["branch", "-r", "--list", `*/${branchName}`], {
1181
- cwd: path5
951
+ cwd: path6
1182
952
  });
1183
953
  if (remoteResult.trim()) {
1184
954
  return true;
@@ -1189,17 +959,17 @@ async function branchExists(branchName, path5 = process.cwd(), includeRemote = t
1189
959
  return false;
1190
960
  }
1191
961
  }
1192
- async function getRepoRoot(path5 = process.cwd()) {
962
+ async function getRepoRoot(path6 = process.cwd()) {
1193
963
  try {
1194
- const result = await executeGitCommand(["rev-parse", "--show-toplevel"], { cwd: path5 });
964
+ const result = await executeGitCommand(["rev-parse", "--show-toplevel"], { cwd: path6 });
1195
965
  return result.trim();
1196
966
  } catch {
1197
967
  return null;
1198
968
  }
1199
969
  }
1200
- async function findMainWorktreePath(path5 = process.cwd(), options) {
970
+ async function findMainWorktreePath(path6 = process.cwd(), options) {
1201
971
  try {
1202
- const output = await executeGitCommand(["worktree", "list", "--porcelain"], { cwd: path5 });
972
+ const output = await executeGitCommand(["worktree", "list", "--porcelain"], { cwd: path6 });
1203
973
  const worktrees = parseWorktreeList(output, options == null ? void 0 : options.mainBranch);
1204
974
  if (worktrees.length === 0) {
1205
975
  throw new Error("No worktrees found in repository");
@@ -1229,33 +999,30 @@ async function findMainWorktreePath(path5 = process.cwd(), options) {
1229
999
  throw new Error(`Failed to find main worktree: ${error instanceof Error ? error.message : String(error)}`);
1230
1000
  }
1231
1001
  }
1232
- async function findMainWorktreePathWithSettings(path5, settingsManager) {
1233
- if (!settingsManager) {
1234
- const { SettingsManager: SM } = await Promise.resolve().then(() => (init_SettingsManager(), SettingsManager_exports));
1235
- settingsManager = new SM();
1236
- }
1237
- const settings = await settingsManager.loadSettings(path5);
1002
+ async function findMainWorktreePathWithSettings(path6, settingsManager) {
1003
+ settingsManager ??= new SettingsManager();
1004
+ const settings = await settingsManager.loadSettings(path6);
1238
1005
  const findOptions = settings.mainBranch ? { mainBranch: settings.mainBranch } : void 0;
1239
- return findMainWorktreePath(path5, findOptions);
1006
+ return findMainWorktreePath(path6, findOptions);
1240
1007
  }
1241
- async function hasUncommittedChanges(path5 = process.cwd()) {
1008
+ async function hasUncommittedChanges(path6 = process.cwd()) {
1242
1009
  try {
1243
- const result = await executeGitCommand(["status", "--porcelain"], { cwd: path5 });
1010
+ const result = await executeGitCommand(["status", "--porcelain"], { cwd: path6 });
1244
1011
  return result.trim().length > 0;
1245
1012
  } catch {
1246
1013
  return false;
1247
1014
  }
1248
1015
  }
1249
- async function getDefaultBranch(path5 = process.cwd()) {
1016
+ async function getDefaultBranch(path6 = process.cwd()) {
1250
1017
  try {
1251
1018
  const remoteResult = await executeGitCommand(["symbolic-ref", "refs/remotes/origin/HEAD"], {
1252
- cwd: path5
1019
+ cwd: path6
1253
1020
  });
1254
1021
  const match = remoteResult.match(/refs\/remotes\/origin\/(.+)/);
1255
1022
  if (match) return match[1] ?? "main";
1256
1023
  const commonDefaults = ["main", "master", "develop"];
1257
1024
  for (const branch of commonDefaults) {
1258
- if (await branchExists(branch, path5)) {
1025
+ if (await branchExists(branch, path6)) {
1259
1026
  return branch;
1260
1027
  }
1261
1028
  }
@@ -1264,13 +1031,13 @@ async function getDefaultBranch(path5 = process.cwd()) {
1264
1031
  return "main";
1265
1032
  }
1266
1033
  }
1267
- async function findAllBranchesForIssue(issueNumber, path5 = process.cwd(), settingsManager) {
1034
+ async function findAllBranchesForIssue(issueNumber, path6 = process.cwd(), settingsManager) {
1268
1035
  if (!settingsManager) {
1269
1036
  const { SettingsManager: SM } = await Promise.resolve().then(() => (init_SettingsManager(), SettingsManager_exports));
1270
1037
  settingsManager = new SM();
1271
1038
  }
1272
- const protectedBranches = await settingsManager.getProtectedBranches(path5);
1273
- const output = await executeGitCommand(["branch", "-a"], { cwd: path5 });
1039
+ const protectedBranches = await settingsManager.getProtectedBranches(path6);
1040
+ const output = await executeGitCommand(["branch", "-a"], { cwd: path6 });
1274
1041
  const branches = [];
1275
1042
  const lines = output.split("\n").filter(Boolean);
1276
1043
  for (const line of lines) {
@@ -1327,18 +1094,18 @@ async function findAllBranchesForIssue(issueNumber, path5 = process.cwd(), setti
1327
1094
  }
1328
1095
  return branches;
1329
1096
  }
1330
- async function isEmptyRepository(path5 = process.cwd()) {
1097
+ async function isEmptyRepository(path6 = process.cwd()) {
1331
1098
  try {
1332
- await executeGitCommand(["rev-parse", "--verify", "HEAD"], { cwd: path5 });
1099
+ await executeGitCommand(["rev-parse", "--verify", "HEAD"], { cwd: path6 });
1333
1100
  return false;
1334
1101
  } catch {
1335
1102
  return true;
1336
1103
  }
1337
1104
  }
1338
- async function ensureRepositoryHasCommits(path5 = process.cwd()) {
1339
- const isEmpty = await isEmptyRepository(path5);
1105
+ async function ensureRepositoryHasCommits(path6 = process.cwd()) {
1106
+ const isEmpty = await isEmptyRepository(path6);
1340
1107
  if (isEmpty) {
1341
- await executeGitCommand(["commit", "--no-verify", "--allow-empty", "-m", "Initial commit"], { cwd: path5 });
1108
+ await executeGitCommand(["commit", "--no-verify", "--allow-empty", "-m", "Initial commit"], { cwd: path6 });
1342
1109
  }
1343
1110
  }
1344
1111
  async function pushBranchToRemote(branchName, worktreePath, options) {
@@ -1383,6 +1150,21 @@ async function pushBranchToRemote(branchName, worktreePath, options) {
1383
1150
  throw new Error(`Failed to push to remote: ${errorMessage}`);
1384
1151
  }
1385
1152
  }
1153
+ async function isFileTrackedByGit(filePath, cwd = process.cwd()) {
1154
+ try {
1155
+ const result = await executeGitCommand(
1156
+ ["ls-files", "--error-unmatch", filePath],
1157
+ { cwd }
1158
+ );
1159
+ return result.trim().length > 0;
1160
+ } catch (error) {
1161
+ const errorMessage = error instanceof Error ? error.message : String(error);
1162
+ if (errorMessage.includes("pathspec") && errorMessage.includes("did not match")) {
1163
+ return false;
1164
+ }
1165
+ throw error;
1166
+ }
1167
+ }
1386
1168
 
1387
1169
  // src/lib/GitWorktreeManager.ts
1388
1170
  var GitWorktreeManager = class {
@@ -1752,6 +1534,9 @@ var GitWorktreeManager = class {
1752
1534
  }
1753
1535
  };
1754
1536
 
1537
+ // src/lib/GitHubService.ts
1538
+ import { execSync } from "child_process";
1539
+
1755
1540
  // src/types/github.ts
1756
1541
  var GitHubError = class extends Error {
1757
1542
  constructor(code, message, details) {
@@ -1991,6 +1776,18 @@ var GitHubService = class {
1991
1776
  this.supportsPullRequests = true;
1992
1777
  this.prompter = (options == null ? void 0 : options.prompter) ?? promptConfirmation;
1993
1778
  }
1779
+ /**
1780
+ * Check if GitHub CLI (gh) is available on the system
1781
+ * @returns true if gh CLI is installed and accessible, false otherwise
1782
+ */
1783
+ static isCliAvailable() {
1784
+ try {
1785
+ execSync("gh --version", { stdio: "ignore" });
1786
+ return true;
1787
+ } catch {
1788
+ return false;
1789
+ }
1790
+ }
1994
1791
  // Input detection - IssueTracker interface implementation
1995
1792
  async detectInputType(input, repo) {
1996
1793
  const numberMatch = input.match(/^#?(\d+)$/);
@@ -2611,6 +2408,7 @@ import fs2 from "fs-extra";
2611
2408
 
2612
2409
  // src/utils/env.ts
2613
2410
  init_logger();
2411
+ import path4 from "path";
2614
2412
  import dotenvFlow from "dotenv-flow";
2615
2413
  function parseEnvFile(content) {
2616
2414
  const envMap = /* @__PURE__ */ new Map();
@@ -2664,6 +2462,45 @@ function isValidEnvKey(key) {
2664
2462
  const validKeyRegex = /^[A-Za-z_][A-Za-z0-9_]*$/;
2665
2463
  return validKeyRegex.test(key);
2666
2464
  }
2465
+ var DOTENV_FLOW_NODE_ENV = process.env.DOTENV_FLOW_NODE_ENV ?? "development";
2466
+ function getDotenvFlowFiles() {
2467
+ return [
2468
+ ".env",
2469
+ ".env.local",
2470
+ `.env.${DOTENV_FLOW_NODE_ENV}`,
2471
+ `.env.${DOTENV_FLOW_NODE_ENV}.local`
2472
+ ];
2473
+ }
2474
+ async function buildEnvSourceCommands(workspacePath, fileExists) {
2475
+ const files = getDotenvFlowFiles();
2476
+ const commands = [];
2477
+ for (const file of files) {
2478
+ const fullPath = path4.join(workspacePath, file);
2479
+ const exists = await fileExists(fullPath);
2480
+ if (exists) {
2481
+ commands.push(`source ${file}`);
2482
+ }
2483
+ }
2484
+ return commands;
2485
+ }
2486
+ async function findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable) {
2487
+ const files = getDotenvFlowFiles().reverse();
2488
+ for (const file of files) {
2489
+ const fullPath = path4.join(workspacePath, file);
2490
+ if (!await fileExists(fullPath)) {
2491
+ continue;
2492
+ }
2493
+ const value = await getEnvVariable(fullPath, variableName);
2494
+ if (value !== null) {
2495
+ return file;
2496
+ }
2497
+ }
2498
+ return null;
2499
+ }
2500
+ async function hasVariableInAnyEnvFile(workspacePath, variableName, fileExists, getEnvVariable) {
2501
+ const file = await findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable);
2502
+ return file !== null;
2503
+ }
2667
2504
 
2668
2505
  // src/utils/port.ts
2669
2506
  import { createHash } from "crypto";
@@ -2882,6 +2719,7 @@ var EnvironmentManager = class {
2882
2719
 
2883
2720
  // src/lib/DatabaseManager.ts
2884
2721
  init_logger();
2722
+ import fs3 from "fs-extra";
2885
2723
  var logger3 = createLogger({ prefix: "\u{1F5C2}\uFE0F" });
2886
2724
  var DatabaseManager = class {
2887
2725
  constructor(provider, environment, databaseUrlEnvVarName = "DATABASE_URL") {
@@ -2904,17 +2742,17 @@ var DatabaseManager = class {
2904
2742
  * Check if database branching should be used
2905
2743
  * Requires BOTH conditions:
2906
2744
  * 1. Database provider is properly configured (checked via provider.isConfigured())
2907
- * 2. .env file contains the configured database URL variable
2745
+ * 2. Any dotenv-flow file contains the configured database URL variable
2908
2746
  */
2909
- async shouldUseDatabaseBranching(envFilePath) {
2747
+ async shouldUseDatabaseBranching(workspacePath) {
2910
2748
  if (!this.provider.isConfigured()) {
2911
2749
  logger3.debug("Skipping database branching: Database provider not configured");
2912
2750
  return false;
2913
2751
  }
2914
- const hasDatabaseUrl = await this.hasDatabaseUrlInEnv(envFilePath);
2752
+ const hasDatabaseUrl = await this.hasDatabaseUrlInEnv(workspacePath);
2915
2753
  if (!hasDatabaseUrl) {
2916
2754
  logger3.debug(
2917
- "Skipping database branching: configured database URL variable not found in .env file"
2755
+ "Skipping database branching: configured database URL variable not found in any env file"
2918
2756
  );
2919
2757
  return false;
2920
2758
  }
@@ -2925,12 +2763,12 @@ var DatabaseManager = class {
2925
2763
  * Returns connection string if branch was created, null if skipped
2926
2764
  *
2927
2765
  * @param branchName - Name of the branch to create
2928
- * @param envFilePath - Path to .env file for configuration checks
2766
+ * @param workspacePath - Path to workspace for configuration checks (checks all dotenv-flow files)
2929
2767
  * @param cwd - Optional working directory to run commands from
2930
2768
  * @param fromBranch - Optional parent branch to create from (for child looms)
2931
2769
  */
2932
- async createBranchIfConfigured(branchName, envFilePath, cwd, fromBranch) {
2933
- if (!await this.shouldUseDatabaseBranching(envFilePath)) {
2770
+ async createBranchIfConfigured(branchName, workspacePath, cwd, fromBranch) {
2771
+ if (!await this.shouldUseDatabaseBranching(workspacePath)) {
2934
2772
  return null;
2935
2773
  }
2936
2774
  if (!await this.provider.isCliAvailable()) {
@@ -3057,19 +2895,24 @@ var DatabaseManager = class {
3057
2895
  return null;
3058
2896
  }
3059
2897
  /**
3060
- * Check if .env has the configured database URL variable
2898
+ * Check if any dotenv-flow file has the configured database URL variable
3061
2899
  * CRITICAL: If user explicitly configured a custom variable name (not default),
3062
- * throw an error if it's missing from .env
2900
+ * throw an error if it's missing from all env files
3063
2901
  */
3064
- async hasDatabaseUrlInEnv(envFilePath) {
2902
+ async hasDatabaseUrlInEnv(workspacePath) {
3065
2903
  try {
3066
- const envMap = await this.environment.readEnvFile(envFilePath);
3067
2904
  if (this.databaseUrlEnvVarName !== "DATABASE_URL") {
3068
2905
  logger3.debug(`Looking for custom database URL variable: ${this.databaseUrlEnvVarName}`);
3069
2906
  } else {
3070
2907
  logger3.debug("Looking for default database URL variable: DATABASE_URL");
3071
2908
  }
3072
- if (envMap.has(this.databaseUrlEnvVarName)) {
2909
+ const hasConfiguredVar = await hasVariableInAnyEnvFile(
2910
+ workspacePath,
2911
+ this.databaseUrlEnvVarName,
2912
+ async (p) => fs3.pathExists(p),
2913
+ async (p, v) => this.environment.getEnvVariable(p, v)
2914
+ );
2915
+ if (hasConfiguredVar) {
3073
2916
  if (this.databaseUrlEnvVarName !== "DATABASE_URL") {
3074
2917
  logger3.debug(`\u2705 Found custom database URL variable: ${this.databaseUrlEnvVarName}`);
3075
2918
  } else {
@@ -3078,20 +2921,25 @@ var DatabaseManager = class {
3078
2921
  return true;
3079
2922
  }
3080
2923
  if (this.databaseUrlEnvVarName !== "DATABASE_URL") {
3081
- logger3.debug(`\u274C Custom database URL variable '${this.databaseUrlEnvVarName}' not found in .env file`);
2924
+ logger3.debug(`\u274C Custom database URL variable '${this.databaseUrlEnvVarName}' not found in any env file`);
3082
2925
  throw new Error(
3083
- `Configured database URL environment variable '${this.databaseUrlEnvVarName}' not found in .env file. Please add it to your .env file or update your iloom configuration.`
2926
+ `Configured database URL environment variable '${this.databaseUrlEnvVarName}' not found in any dotenv-flow file. Please add it to an .env file or update your iloom configuration.`
3084
2927
  );
3085
2928
  }
3086
- const hasDefaultVar = envMap.has("DATABASE_URL");
2929
+ const hasDefaultVar = await hasVariableInAnyEnvFile(
2930
+ workspacePath,
2931
+ "DATABASE_URL",
2932
+ async (p) => fs3.pathExists(p),
2933
+ async (p, v) => this.environment.getEnvVariable(p, v)
2934
+ );
3087
2935
  if (hasDefaultVar) {
3088
2936
  logger3.debug("\u2705 Found fallback DATABASE_URL variable");
3089
2937
  } else {
3090
- logger3.debug("\u274C No DATABASE_URL variable found in .env file");
2938
+ logger3.debug("\u274C No DATABASE_URL variable found in any env file");
3091
2939
  }
3092
2940
  return hasDefaultVar;
3093
2941
  } catch (error) {
3094
- if (error instanceof Error && error.message.includes("not found in .env")) {
2942
+ if (error instanceof Error && error.message.includes("not found in")) {
3095
2943
  throw error;
3096
2944
  }
3097
2945
  return false;
@@ -3104,6 +2952,140 @@ init_logger();
3104
2952
  import { execa as execa4 } from "execa";
3105
2953
  import { existsSync as existsSync2 } from "fs";
3106
2954
  import { join } from "path";
2955
+
2956
+ // src/utils/terminal.ts
2957
+ import { execa as execa3 } from "execa";
2958
+ import { existsSync } from "fs";
2959
+ function detectPlatform() {
2960
+ const platform = process.platform;
2961
+ if (platform === "darwin") return "darwin";
2962
+ if (platform === "linux") return "linux";
2963
+ if (platform === "win32") return "win32";
2964
+ return "unsupported";
2965
+ }
2966
+ async function detectITerm2() {
2967
+ const platform = detectPlatform();
2968
+ if (platform !== "darwin") return false;
2969
+ return existsSync("/Applications/iTerm.app");
2970
+ }
2971
+ async function openTerminalWindow(options) {
2972
+ const platform = detectPlatform();
2973
+ if (platform !== "darwin") {
2974
+ throw new Error(
2975
+ `Terminal window launching not yet supported on ${platform}. Currently only macOS is supported.`
2976
+ );
2977
+ }
2978
+ const hasITerm2 = await detectITerm2();
2979
+ const applescript = hasITerm2 ? await buildITerm2SingleTabScript(options) : await buildAppleScript(options);
2980
+ try {
2981
+ await execa3("osascript", ["-e", applescript]);
2982
+ if (!hasITerm2) {
2983
+ await execa3("osascript", ["-e", 'tell application "Terminal" to activate']);
2984
+ }
2985
+ } catch (error) {
2986
+ throw new Error(
2987
+ `Failed to open terminal window: ${error instanceof Error ? error.message : "Unknown error"}`
2988
+ );
2989
+ }
2990
+ }
2991
+ async function buildAppleScript(options) {
2992
+ const {
2993
+ workspacePath,
2994
+ command,
2995
+ backgroundColor,
2996
+ port,
2997
+ includeEnvSetup,
2998
+ includePortExport
2999
+ } = options;
3000
+ const commands = [];
3001
+ if (workspacePath) {
3002
+ commands.push(`cd '${escapePathForAppleScript(workspacePath)}'`);
3003
+ }
3004
+ if (includeEnvSetup && workspacePath) {
3005
+ const sourceCommands = await buildEnvSourceCommands(
3006
+ workspacePath,
3007
+ async (p) => existsSync(p)
3008
+ );
3009
+ commands.push(...sourceCommands);
3010
+ }
3011
+ if (includePortExport && port !== void 0) {
3012
+ commands.push(`export PORT=${port}`);
3013
+ }
3014
+ if (command) {
3015
+ commands.push(command);
3016
+ }
3017
+ const fullCommand = commands.join(" && ");
3018
+ const historyFreeCommand = ` ${fullCommand}`;
3019
+ let script = `tell application "Terminal"
3020
+ `;
3021
+ script += ` set newTab to do script "${escapeForAppleScript(historyFreeCommand)}"
3022
+ `;
3023
+ if (backgroundColor) {
3024
+ const { r, g, b } = backgroundColor;
3025
+ script += ` set background color of newTab to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}
3026
+ `;
3027
+ }
3028
+ script += `end tell`;
3029
+ return script;
3030
+ }
3031
+ function escapePathForAppleScript(path6) {
3032
+ return path6.replace(/'/g, "'\\''");
3033
+ }
3034
+ function escapeForAppleScript(command) {
3035
+ return command.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
3036
+ }
3037
+ async function buildITerm2SingleTabScript(options) {
3038
+ const command = await buildCommandSequence(options);
3039
+ let script = 'tell application id "com.googlecode.iterm2"\n';
3040
+ script += " create window with default profile\n";
3041
+ script += " set s1 to current session of current window\n\n";
3042
+ if (options.backgroundColor) {
3043
+ const { r, g, b } = options.backgroundColor;
3044
+ script += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}
3045
+ `;
3046
+ }
3047
+ script += ` tell s1 to write text "${escapeForAppleScript(command)}"
3048
+
3049
+ `;
3050
+ if (options.title) {
3051
+ script += ` set name of s1 to "${escapeForAppleScript(options.title)}"
3052
+
3053
+ `;
3054
+ }
3055
+ script += " activate\n";
3056
+ script += "end tell";
3057
+ return script;
3058
+ }
3059
+ async function buildCommandSequence(options) {
3060
+ const {
3061
+ workspacePath,
3062
+ command,
3063
+ port,
3064
+ includeEnvSetup,
3065
+ includePortExport
3066
+ } = options;
3067
+ const commands = [];
3068
+ if (workspacePath) {
3069
+ commands.push(`cd '${escapePathForAppleScript(workspacePath)}'`);
3070
+ }
3071
+ if (includeEnvSetup && workspacePath) {
3072
+ const sourceCommands = await buildEnvSourceCommands(
3073
+ workspacePath,
3074
+ async (p) => existsSync(p)
3075
+ );
3076
+ commands.push(...sourceCommands);
3077
+ }
3078
+ if (includePortExport && port !== void 0) {
3079
+ commands.push(`export PORT=${port}`);
3080
+ }
3081
+ if (command) {
3082
+ commands.push(command);
3083
+ }
3084
+ const fullCommand = commands.join(" && ");
3085
+ return ` ${fullCommand}`;
3086
+ }
3087
+
3088
+ // src/utils/claude.ts
3107
3089
  async function detectClaudeCli() {
3108
3090
  try {
3109
3091
  await execa4("command", ["-v", "claude"], {
@@ -3247,7 +3229,6 @@ async function launchClaudeInNewTerminalWindow(_prompt, options) {
3247
3229
  if (!workspacePath) {
3248
3230
  throw new Error("workspacePath is required for terminal window launch");
3249
3231
  }
3250
- const { openTerminalWindow: openTerminalWindow2 } = await Promise.resolve().then(() => (init_terminal(), terminal_exports));
3251
3232
  const executable = executablePath ?? "iloom";
3252
3233
  let launchCommand = `${executable} spin`;
3253
3234
  if (oneShot !== "default") {
@@ -3271,7 +3252,7 @@ async function launchClaudeInNewTerminalWindow(_prompt, options) {
3271
3252
  }
3272
3253
  }
3273
3254
  const hasEnvFile = existsSync2(join(workspacePath, ".env"));
3274
- await openTerminalWindow2({
3255
+ await openTerminalWindow({
3275
3256
  workspacePath,
3276
3257
  command: launchCommand,
3277
3258
  ...backgroundColor && { backgroundColor },
@@ -3285,7 +3266,7 @@ async function launchClaudeInNewTerminalWindow(_prompt, options) {
3285
3266
  init_logger();
3286
3267
  import { readFile as readFile2 } from "fs/promises";
3287
3268
  import { accessSync } from "fs";
3288
- import path4 from "path";
3269
+ import path5 from "path";
3289
3270
  import { fileURLToPath } from "url";
3290
3271
  var PromptTemplateManager = class {
3291
3272
  constructor(templateDir) {
@@ -3294,17 +3275,17 @@ var PromptTemplateManager = class {
3294
3275
  } else {
3295
3276
  const currentFileUrl = import.meta.url;
3296
3277
  const currentFilePath = fileURLToPath(currentFileUrl);
3297
- const distDir = path4.dirname(currentFilePath);
3298
- let templateDir2 = path4.join(distDir, "prompts");
3278
+ const distDir = path5.dirname(currentFilePath);
3279
+ let templateDir2 = path5.join(distDir, "prompts");
3299
3280
  let currentDir = distDir;
3300
- while (currentDir !== path4.dirname(currentDir)) {
3301
- const candidatePath = path4.join(currentDir, "prompts");
3281
+ while (currentDir !== path5.dirname(currentDir)) {
3282
+ const candidatePath = path5.join(currentDir, "prompts");
3302
3283
  try {
3303
3284
  accessSync(candidatePath);
3304
3285
  templateDir2 = candidatePath;
3305
3286
  break;
3306
3287
  } catch {
3307
- currentDir = path4.dirname(currentDir);
3288
+ currentDir = path5.dirname(currentDir);
3308
3289
  }
3309
3290
  }
3310
3291
  this.templateDir = templateDir2;
@@ -3319,7 +3300,7 @@ var PromptTemplateManager = class {
3319
3300
  * Load a template file by name
3320
3301
  */
3321
3302
  async loadTemplate(templateName) {
3322
- const templatePath = path4.join(this.templateDir, `${templateName}-prompt.txt`);
3303
+ const templatePath = path5.join(this.templateDir, `${templateName}-prompt.txt`);
3323
3304
  logger.debug("Loading template", {
3324
3305
  templateName,
3325
3306
  templateDir: this.templateDir,
@@ -3974,6 +3955,7 @@ export {
3974
3955
  getRepoRoot,
3975
3956
  hasUncommittedChanges,
3976
3957
  isEmptyRepository,
3958
+ isFileTrackedByGit,
3977
3959
  isPRBranch,
3978
3960
  isValidGitRepo,
3979
3961
  isWorktreePath,