@iloom/cli 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/README.md +24 -0
  2. package/dist/{BranchNamingService-TOM2KAUT.js → BranchNamingService-GCCWB3LK.js} +2 -2
  3. package/dist/ClaudeContextManager-DQFKIMEP.js +16 -0
  4. package/dist/ClaudeService-CJS32WG2.js +15 -0
  5. package/dist/{LoomLauncher-SJBZFZXE.js → LoomLauncher-4UG2E4CD.js} +40 -32
  6. package/dist/LoomLauncher-4UG2E4CD.js.map +1 -0
  7. package/dist/MetadataManager-WXUVXKUS.js +10 -0
  8. package/dist/PRManager-7DSIMCAD.js +16 -0
  9. package/dist/{PromptTemplateManager-2TDZAUC6.js → PromptTemplateManager-72FEOGT6.js} +2 -2
  10. package/dist/README.md +24 -0
  11. package/dist/{SettingsManager-FJFU6JJD.js → SettingsManager-XPR4TEQL.js} +2 -2
  12. package/dist/agents/iloom-issue-analyze-and-plan.md +41 -7
  13. package/dist/agents/iloom-issue-analyzer.md +38 -8
  14. package/dist/agents/iloom-issue-complexity-evaluator.md +45 -15
  15. package/dist/agents/iloom-issue-enhancer.md +60 -18
  16. package/dist/agents/iloom-issue-implementer.md +29 -7
  17. package/dist/agents/iloom-issue-planner.md +36 -7
  18. package/dist/agents/iloom-issue-reviewer.md +30 -7
  19. package/dist/{chunk-M5XUCTTJ.js → chunk-3CMGCRB5.js} +2 -2
  20. package/dist/{chunk-KM3W7YQX.js → chunk-4YTILIIH.js} +8 -9
  21. package/dist/chunk-4YTILIIH.js.map +1 -0
  22. package/dist/{chunk-HVGQP44L.js → chunk-AS2IRKLU.js} +2 -2
  23. package/dist/{chunk-ADDNFQJ4.js → chunk-CDQEK2WD.js} +6 -6
  24. package/dist/{chunk-74VMN2KC.js → chunk-DKQ4SUII.js} +16 -1
  25. package/dist/chunk-DKQ4SUII.js.map +1 -0
  26. package/dist/{chunk-LTNDJMTH.js → chunk-GVRO4PWE.js} +13 -9
  27. package/dist/chunk-GVRO4PWE.js.map +1 -0
  28. package/dist/{chunk-HHDSIE72.js → chunk-HABINPX2.js} +72 -16
  29. package/dist/{chunk-HHDSIE72.js.map → chunk-HABINPX2.js.map} +1 -1
  30. package/dist/{chunk-TR5MC2U6.js → chunk-LN4H3A6A.js} +66 -7
  31. package/dist/chunk-LN4H3A6A.js.map +1 -0
  32. package/dist/{chunk-VWNS6DH5.js → chunk-OOU3DKNT.js} +13 -7
  33. package/dist/chunk-OOU3DKNT.js.map +1 -0
  34. package/dist/chunk-P2ZQ5LKB.js +347 -0
  35. package/dist/chunk-P2ZQ5LKB.js.map +1 -0
  36. package/dist/{chunk-P2WZIDF3.js → chunk-QIUJPPJQ.js} +2 -2
  37. package/dist/{chunk-HD5SUKI2.js → chunk-RFUOIUQF.js} +49 -6
  38. package/dist/{chunk-HD5SUKI2.js.map → chunk-RFUOIUQF.js.map} +1 -1
  39. package/dist/{chunk-OF7BNW4D.js → chunk-RJKMF6BC.js} +30 -4
  40. package/dist/chunk-RJKMF6BC.js.map +1 -0
  41. package/dist/{chunk-O7WHXLCB.js → chunk-RNZMHJK7.js} +18 -4
  42. package/dist/chunk-RNZMHJK7.js.map +1 -0
  43. package/dist/{chunk-75B2HZZ5.js → chunk-RUC7OULH.js} +2 -2
  44. package/dist/{chunk-F4J6KEL6.js → chunk-S65T4O6I.js} +2 -2
  45. package/dist/{chunk-NFVFVYAP.js → chunk-T5IIUG4Z.js} +109 -20
  46. package/dist/chunk-T5IIUG4Z.js.map +1 -0
  47. package/dist/{chunk-JJUPY5MM.js → chunk-VAYGNQTE.js} +2 -2
  48. package/dist/{chunk-S44CHE3G.js → chunk-VTXCGKV5.js} +2 -2
  49. package/dist/{chunk-MLS5FAV7.js → chunk-YZTDGPFB.js} +21 -1
  50. package/dist/chunk-YZTDGPFB.js.map +1 -0
  51. package/dist/{chunk-3NFBZRPR.js → chunk-Z5NXYJIG.js} +19 -1
  52. package/dist/chunk-Z5NXYJIG.js.map +1 -0
  53. package/dist/{claude-X7EBJRB2.js → claude-ACVXNB6N.js} +4 -4
  54. package/dist/{cleanup-7QVPYBJJ.js → cleanup-MIDJVSIU.js} +18 -18
  55. package/dist/cli.js +293 -372
  56. package/dist/cli.js.map +1 -1
  57. package/dist/{contribute-RZYCYUDX.js → contribute-RS3DO3WP.js} +4 -4
  58. package/dist/{dev-server-LOY7YWCP.js → dev-server-ASH7HJVI.js} +28 -14
  59. package/dist/dev-server-ASH7HJVI.js.map +1 -0
  60. package/dist/{feedback-562KPG5U.js → feedback-RVIGHBJG.js} +9 -8
  61. package/dist/{feedback-562KPG5U.js.map → feedback-RVIGHBJG.js.map} +1 -1
  62. package/dist/{git-OXJACVAU.js → git-OQAPUPLP.js} +16 -6
  63. package/dist/git-OQAPUPLP.js.map +1 -0
  64. package/dist/{ignite-VSIPGKKG.js → ignite-XJALWFAT.js} +60 -25
  65. package/dist/ignite-XJALWFAT.js.map +1 -0
  66. package/dist/index.d.ts +60 -7
  67. package/dist/index.js +107 -7
  68. package/dist/index.js.map +1 -1
  69. package/dist/init-F6PFMSU5.js +21 -0
  70. package/dist/init-F6PFMSU5.js.map +1 -0
  71. package/dist/mcp/recap-server.js +264 -0
  72. package/dist/mcp/recap-server.js.map +1 -0
  73. package/dist/{open-CX7HUE26.js → open-KW4NTLXH.js} +15 -16
  74. package/dist/{open-CX7HUE26.js.map → open-KW4NTLXH.js.map} +1 -1
  75. package/dist/{projects-6DTNDVLH.js → projects-QEAEBAT2.js} +2 -2
  76. package/dist/prompts/init-prompt.txt +31 -72
  77. package/dist/prompts/issue-prompt.txt +115 -15
  78. package/dist/prompts/pr-prompt.txt +49 -1
  79. package/dist/prompts/regular-prompt.txt +80 -20
  80. package/dist/{rebase-55URTXZC.js → rebase-WZHHE5LU.js} +9 -9
  81. package/dist/recap-33NPZ3ZO.js +117 -0
  82. package/dist/recap-33NPZ3ZO.js.map +1 -0
  83. package/dist/{run-DP2U2CA2.js → run-HRYQ7TR7.js} +15 -16
  84. package/dist/{run-DP2U2CA2.js.map → run-HRYQ7TR7.js.map} +1 -1
  85. package/dist/schema/settings.schema.json +13 -2
  86. package/dist/shell-JMU5XTHW.js +240 -0
  87. package/dist/shell-JMU5XTHW.js.map +1 -0
  88. package/dist/{summary-J3CJSM7L.js → summary-4SSGGH7N.js} +20 -12
  89. package/dist/summary-4SSGGH7N.js.map +1 -0
  90. package/dist/{test-git-QLAIBJLX.js → test-git-6SAIRBUD.js} +4 -4
  91. package/dist/{test-prefix-6YM2ZOON.js → test-prefix-RLVRK5ZD.js} +4 -4
  92. package/dist/{test-tabs-JGO3VOXJ.js → test-tabs-3SCJWRKT.js} +3 -3
  93. package/package.json +1 -1
  94. package/dist/ClaudeContextManager-VEGJTS5E.js +0 -16
  95. package/dist/ClaudeService-ICSHJMQ5.js +0 -15
  96. package/dist/LoomLauncher-SJBZFZXE.js.map +0 -1
  97. package/dist/chunk-3NFBZRPR.js.map +0 -1
  98. package/dist/chunk-74VMN2KC.js.map +0 -1
  99. package/dist/chunk-KM3W7YQX.js.map +0 -1
  100. package/dist/chunk-LTNDJMTH.js.map +0 -1
  101. package/dist/chunk-MLS5FAV7.js.map +0 -1
  102. package/dist/chunk-NFVFVYAP.js.map +0 -1
  103. package/dist/chunk-O7WHXLCB.js.map +0 -1
  104. package/dist/chunk-OF7BNW4D.js.map +0 -1
  105. package/dist/chunk-QRBOPFAA.js +0 -48
  106. package/dist/chunk-QRBOPFAA.js.map +0 -1
  107. package/dist/chunk-TR5MC2U6.js.map +0 -1
  108. package/dist/chunk-VWNS6DH5.js.map +0 -1
  109. package/dist/dev-server-LOY7YWCP.js.map +0 -1
  110. package/dist/ignite-VSIPGKKG.js.map +0 -1
  111. package/dist/init-SCR2LQ4A.js +0 -21
  112. package/dist/summary-J3CJSM7L.js.map +0 -1
  113. /package/dist/{BranchNamingService-TOM2KAUT.js.map → BranchNamingService-GCCWB3LK.js.map} +0 -0
  114. /package/dist/{ClaudeContextManager-VEGJTS5E.js.map → ClaudeContextManager-DQFKIMEP.js.map} +0 -0
  115. /package/dist/{ClaudeService-ICSHJMQ5.js.map → ClaudeService-CJS32WG2.js.map} +0 -0
  116. /package/dist/{PromptTemplateManager-2TDZAUC6.js.map → MetadataManager-WXUVXKUS.js.map} +0 -0
  117. /package/dist/{SettingsManager-FJFU6JJD.js.map → PRManager-7DSIMCAD.js.map} +0 -0
  118. /package/dist/{claude-X7EBJRB2.js.map → PromptTemplateManager-72FEOGT6.js.map} +0 -0
  119. /package/dist/{git-OXJACVAU.js.map → SettingsManager-XPR4TEQL.js.map} +0 -0
  120. /package/dist/{chunk-M5XUCTTJ.js.map → chunk-3CMGCRB5.js.map} +0 -0
  121. /package/dist/{chunk-HVGQP44L.js.map → chunk-AS2IRKLU.js.map} +0 -0
  122. /package/dist/{chunk-ADDNFQJ4.js.map → chunk-CDQEK2WD.js.map} +0 -0
  123. /package/dist/{chunk-P2WZIDF3.js.map → chunk-QIUJPPJQ.js.map} +0 -0
  124. /package/dist/{chunk-75B2HZZ5.js.map → chunk-RUC7OULH.js.map} +0 -0
  125. /package/dist/{chunk-F4J6KEL6.js.map → chunk-S65T4O6I.js.map} +0 -0
  126. /package/dist/{chunk-JJUPY5MM.js.map → chunk-VAYGNQTE.js.map} +0 -0
  127. /package/dist/{chunk-S44CHE3G.js.map → chunk-VTXCGKV5.js.map} +0 -0
  128. /package/dist/{init-SCR2LQ4A.js.map → claude-ACVXNB6N.js.map} +0 -0
  129. /package/dist/{cleanup-7QVPYBJJ.js.map → cleanup-MIDJVSIU.js.map} +0 -0
  130. /package/dist/{contribute-RZYCYUDX.js.map → contribute-RS3DO3WP.js.map} +0 -0
  131. /package/dist/{projects-6DTNDVLH.js.map → projects-QEAEBAT2.js.map} +0 -0
  132. /package/dist/{rebase-55URTXZC.js.map → rebase-WZHHE5LU.js.map} +0 -0
  133. /package/dist/{test-git-QLAIBJLX.js.map → test-git-6SAIRBUD.js.map} +0 -0
  134. /package/dist/{test-prefix-6YM2ZOON.js.map → test-prefix-RLVRK5ZD.js.map} +0 -0
  135. /package/dist/{test-tabs-JGO3VOXJ.js.map → test-tabs-3SCJWRKT.js.map} +0 -0
package/README.md CHANGED
@@ -232,6 +232,30 @@ This example shows how to configure a project-wide default (e.g., GitHub remote)
232
232
  }
233
233
  ```
234
234
 
235
+ ### Merge Behavior
236
+
237
+ Control how `il finish` handles your work. Configure in `.iloom/settings.json`:
238
+
239
+ ```json
240
+ {
241
+ "mergeBehavior": {
242
+ "mode": "local" // "local", "github-pr", or "github-draft-pr"
243
+ }
244
+ }
245
+ ```
246
+
247
+ | **Mode** | **Description** |
248
+ |----------|-----------------|
249
+ | `local` | (Default) Merge directly into main branch locally. Fast-forward merge, no PR created. |
250
+ | `github-pr` | Push branch and create a GitHub PR on `il finish`. Worktree cleanup is optional. |
251
+ | `github-draft-pr` | Create a draft PR immediately on `il start`. On `il finish`, the PR is marked ready for review. **Recommended for contributions to forked repos.** |
252
+
253
+ **When to use `github-draft-pr`:**
254
+ - **Contributing to forks:** When you don't are contributing to a forked repo use this mode to create the PR from your fork immediately, allowing iloom's agents to post workflow comments directly to the PR instead of writing to the upstream repo's issues (which may not be appreciated by the repo owners).
255
+ - CI runs on your branch during development (draft PRs trigger CI on most repos)
256
+ - Your team requires PRs for all changes (no direct merges to main)
257
+ - You want reviewers to see progress before the work is complete
258
+
235
259
  Integrations
236
260
  ------------
237
261
 
@@ -3,7 +3,7 @@ import {
3
3
  ClaudeBranchNameStrategy,
4
4
  DefaultBranchNamingService,
5
5
  SimpleBranchNameStrategy
6
- } from "./chunk-P2WZIDF3.js";
6
+ } from "./chunk-QIUJPPJQ.js";
7
7
  import "./chunk-6UIGZD2N.js";
8
8
  import "./chunk-UYVWLISQ.js";
9
9
  export {
@@ -11,4 +11,4 @@ export {
11
11
  DefaultBranchNamingService,
12
12
  SimpleBranchNameStrategy
13
13
  };
14
- //# sourceMappingURL=BranchNamingService-TOM2KAUT.js.map
14
+ //# sourceMappingURL=BranchNamingService-GCCWB3LK.js.map
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ ClaudeContextManager
4
+ } from "./chunk-S65T4O6I.js";
5
+ import "./chunk-CDQEK2WD.js";
6
+ import "./chunk-DKQ4SUII.js";
7
+ import "./chunk-OOU3DKNT.js";
8
+ import "./chunk-RUC7OULH.js";
9
+ import "./chunk-VAYGNQTE.js";
10
+ import "./chunk-Z5NXYJIG.js";
11
+ import "./chunk-6UIGZD2N.js";
12
+ import "./chunk-UYVWLISQ.js";
13
+ export {
14
+ ClaudeContextManager
15
+ };
16
+ //# sourceMappingURL=ClaudeContextManager-DQFKIMEP.js.map
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ ClaudeService
4
+ } from "./chunk-CDQEK2WD.js";
5
+ import "./chunk-DKQ4SUII.js";
6
+ import "./chunk-OOU3DKNT.js";
7
+ import "./chunk-RUC7OULH.js";
8
+ import "./chunk-VAYGNQTE.js";
9
+ import "./chunk-Z5NXYJIG.js";
10
+ import "./chunk-6UIGZD2N.js";
11
+ import "./chunk-UYVWLISQ.js";
12
+ export {
13
+ ClaudeService
14
+ };
15
+ //# sourceMappingURL=ClaudeService-CJS32WG2.js.map
@@ -1,29 +1,28 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- getDevServerLaunchCommand
4
- } from "./chunk-QRBOPFAA.js";
5
- import "./chunk-VBFDVGAE.js";
6
2
  import {
7
3
  ClaudeContextManager
8
- } from "./chunk-F4J6KEL6.js";
9
- import "./chunk-ADDNFQJ4.js";
10
- import "./chunk-VWNS6DH5.js";
4
+ } from "./chunk-S65T4O6I.js";
5
+ import "./chunk-CDQEK2WD.js";
6
+ import "./chunk-DKQ4SUII.js";
7
+ import {
8
+ getExecutablePath
9
+ } from "./chunk-GYCR2LOU.js";
10
+ import "./chunk-OOU3DKNT.js";
11
11
  import {
12
12
  generateColorFromBranchName,
13
13
  hexToRgb
14
14
  } from "./chunk-WUQQNE63.js";
15
- import "./chunk-75B2HZZ5.js";
15
+ import "./chunk-RUC7OULH.js";
16
16
  import {
17
17
  openMultipleTerminalWindows,
18
18
  openTerminalWindow
19
- } from "./chunk-JJUPY5MM.js";
19
+ } from "./chunk-VAYGNQTE.js";
20
20
  import {
21
21
  getDotenvFlowFiles
22
- } from "./chunk-3NFBZRPR.js";
22
+ } from "./chunk-Z5NXYJIG.js";
23
23
  import {
24
24
  getLogger
25
25
  } from "./chunk-6UIGZD2N.js";
26
- import "./chunk-74VMN2KC.js";
27
26
  import {
28
27
  logger
29
28
  } from "./chunk-UYVWLISQ.js";
@@ -115,7 +114,7 @@ var LoomLauncher = class {
115
114
  if (enableDevServer) {
116
115
  terminalsToLaunch.push({
117
116
  type: "devServer",
118
- options: await this.buildDevServerTerminalOptions(options)
117
+ options: this.buildDevServerTerminalOptions(options)
119
118
  });
120
119
  }
121
120
  if (enableTerminal) {
@@ -179,33 +178,38 @@ var LoomLauncher = class {
179
178
  }
180
179
  /**
181
180
  * Launch dev server terminal
181
+ * Runs `il dev-server [identifier]` which handles env loading internally
182
182
  */
183
183
  async launchDevServerTerminal(options) {
184
- const devServerCommand = await getDevServerLaunchCommand(
185
- options.worktreePath,
186
- options.port,
187
- options.capabilities
188
- );
184
+ const executable = options.executablePath ?? getExecutablePath();
185
+ const devServerIdentifier = String(options.identifier);
186
+ const devServerCommand = `${executable} dev-server ${devServerIdentifier}`;
189
187
  const backgroundColor = options.colorTerminal ?? true ? options.colorHex ? hexToRgb(options.colorHex) : generateColorFromBranchName(options.branchName).rgb : void 0;
190
188
  await openTerminalWindow({
191
189
  workspacePath: options.worktreePath,
192
190
  command: devServerCommand,
193
191
  ...backgroundColor && { backgroundColor },
194
- includeEnvSetup: (options.sourceEnvOnStart ?? false) && this.hasAnyEnvFiles(options.worktreePath),
192
+ // il dev-server handles env loading internally, so no includeEnvSetup
193
+ includeEnvSetup: false,
195
194
  includePortExport: options.capabilities.includes("web"),
196
195
  ...options.port !== void 0 && { port: options.port }
197
196
  });
198
197
  getLogger().info("Dev server terminal opened");
199
198
  }
200
199
  /**
201
- * Launch standalone terminal (no command, just workspace with env vars)
200
+ * Launch standalone terminal running `il shell <identifier>`
202
201
  */
203
202
  async launchStandaloneTerminal(options) {
203
+ const executable = options.executablePath ?? getExecutablePath();
204
+ const shellIdentifier = String(options.identifier);
205
+ const shellCommand = `${executable} shell ${shellIdentifier}`;
204
206
  const backgroundColor = options.colorTerminal ?? true ? options.colorHex ? hexToRgb(options.colorHex) : generateColorFromBranchName(options.branchName).rgb : void 0;
205
207
  await openTerminalWindow({
206
208
  workspacePath: options.worktreePath,
209
+ command: shellCommand,
207
210
  ...backgroundColor && { backgroundColor },
208
- includeEnvSetup: (options.sourceEnvOnStart ?? false) && this.hasAnyEnvFiles(options.worktreePath),
211
+ // il shell handles env loading internally, so we don't need includeEnvSetup
212
+ includeEnvSetup: false,
209
213
  includePortExport: options.capabilities.includes("web"),
210
214
  ...options.port !== void 0 && { port: options.port }
211
215
  });
@@ -239,14 +243,12 @@ var LoomLauncher = class {
239
243
  }
240
244
  /**
241
245
  * Build terminal options for dev server
246
+ * Uses `il dev-server [identifier]` which handles env loading internally
242
247
  */
243
- async buildDevServerTerminalOptions(options) {
244
- const devServerCommand = await getDevServerLaunchCommand(
245
- options.worktreePath,
246
- options.port,
247
- options.capabilities
248
- );
249
- const hasEnvFile = this.hasAnyEnvFiles(options.worktreePath);
248
+ buildDevServerTerminalOptions(options) {
249
+ const executable = options.executablePath ?? getExecutablePath();
250
+ const devServerIdentifier = String(options.identifier);
251
+ const devServerCommand = `${executable} dev-server ${devServerIdentifier}`;
250
252
  const devServerTitle = `Dev Server - ${this.formatIdentifier(options.workflowType, options.identifier)}`;
251
253
  const backgroundColor = options.colorTerminal ?? true ? options.colorHex ? hexToRgb(options.colorHex) : generateColorFromBranchName(options.branchName).rgb : void 0;
252
254
  return {
@@ -254,23 +256,29 @@ var LoomLauncher = class {
254
256
  command: devServerCommand,
255
257
  ...backgroundColor && { backgroundColor },
256
258
  title: devServerTitle,
257
- includeEnvSetup: (options.sourceEnvOnStart ?? false) && hasEnvFile,
259
+ // il dev-server handles env loading internally
260
+ includeEnvSetup: false,
258
261
  includePortExport: options.capabilities.includes("web"),
259
262
  ...options.port !== void 0 && { port: options.port }
260
263
  };
261
264
  }
262
265
  /**
263
- * Build terminal options for standalone terminal (no command)
266
+ * Build terminal options for standalone terminal
267
+ * Runs `il shell <identifier>` which handles env loading internally
264
268
  */
265
269
  buildStandaloneTerminalOptions(options) {
266
- const hasEnvFile = this.hasAnyEnvFiles(options.worktreePath);
267
270
  const terminalTitle = `Terminal - ${this.formatIdentifier(options.workflowType, options.identifier)}`;
271
+ const executable = options.executablePath ?? getExecutablePath();
272
+ const shellIdentifier = String(options.identifier);
273
+ const shellCommand = `${executable} shell ${shellIdentifier}`;
268
274
  const backgroundColor = options.colorTerminal ?? true ? options.colorHex ? hexToRgb(options.colorHex) : generateColorFromBranchName(options.branchName).rgb : void 0;
269
275
  return {
270
276
  workspacePath: options.worktreePath,
277
+ command: shellCommand,
271
278
  ...backgroundColor && { backgroundColor },
272
279
  title: terminalTitle,
273
- includeEnvSetup: (options.sourceEnvOnStart ?? false) && hasEnvFile,
280
+ // il shell handles env loading internally, so we don't need includeEnvSetup
281
+ includeEnvSetup: false,
274
282
  includePortExport: options.capabilities.includes("web"),
275
283
  ...options.port !== void 0 && { port: options.port }
276
284
  };
@@ -308,4 +316,4 @@ var LoomLauncher = class {
308
316
  export {
309
317
  LoomLauncher
310
318
  };
311
- //# sourceMappingURL=LoomLauncher-SJBZFZXE.js.map
319
+ //# sourceMappingURL=LoomLauncher-4UG2E4CD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/LoomLauncher.ts","../src/utils/ide.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { openTerminalWindow, openMultipleTerminalWindows } from '../utils/terminal.js'\nimport type { TerminalWindowOptions } from '../utils/terminal.js'\nimport { openIdeWindow } from '../utils/ide.js'\nimport { generateColorFromBranchName, hexToRgb } from '../utils/color.js'\nimport { getLogger } from '../utils/logger-context.js'\nimport { ClaudeContextManager } from './ClaudeContextManager.js'\nimport type { SettingsManager } from './SettingsManager.js'\nimport type { Capability } from '../types/loom.js'\nimport { getDotenvFlowFiles } from '../utils/env.js'\nimport { getExecutablePath } from '../utils/cli-overrides.js'\n\nexport interface LaunchLoomOptions {\n\tenableClaude: boolean\n\tenableCode: boolean\n\tenableDevServer: boolean\n\tenableTerminal: boolean\n\tworktreePath: string\n\tbranchName: string\n\tport?: number\n\tcapabilities: Capability[]\n\tworkflowType: 'issue' | 'pr' | 'regular'\n\tidentifier: string | number\n\ttitle?: string\n\toneShot?: import('../types/index.js').OneShotMode\n\tsetArguments?: string[] // Raw --set arguments to forward\n\texecutablePath?: string // Executable path to use for spin command\n\tsourceEnvOnStart?: boolean // defaults to false if undefined\n\tcolorTerminal?: boolean // defaults to true if undefined\n\tcolorHex?: string // Pre-calculated hex color from metadata, avoids recalculation\n}\n\n/**\n * LoomLauncher orchestrates opening loom components\n */\nexport class LoomLauncher {\n\tprivate claudeContext: ClaudeContextManager\n\tprivate settings?: SettingsManager\n\n\tconstructor(claudeContext?: ClaudeContextManager, settings?: SettingsManager) {\n\t\tthis.claudeContext = claudeContext ?? new ClaudeContextManager()\n\t\tif (settings !== undefined) {\n\t\t\tthis.settings = settings\n\t\t}\n\t}\n\n\t/**\n\t * Launch loom components based on individual flags\n\t */\n\tasync launchLoom(options: LaunchLoomOptions): Promise<void> {\n\t\tconst { enableClaude, enableCode, enableDevServer, enableTerminal } = options\n\n\t\tgetLogger().debug(`Launching loom components: Claude=${enableClaude}, Code=${enableCode}, DevServer=${enableDevServer}, Terminal=${enableTerminal}`)\n\n\t\tconst launchPromises: Promise<void>[] = []\n\n\t\t// Launch VSCode if enabled\n\t\tif (enableCode) {\n\t\t\tgetLogger().debug('Launching VSCode')\n\t\t\tlaunchPromises.push(this.launchVSCode(options))\n\t\t}\n\n\t\t// Build array of terminals to launch\n\t\tconst terminalsToLaunch: Array<{\n\t\t\ttype: 'claude' | 'devServer' | 'terminal'\n\t\t\toptions: TerminalWindowOptions\n\t\t}> = []\n\n\t\tif (enableDevServer) {\n\t\t\tterminalsToLaunch.push({\n\t\t\t\ttype: 'devServer',\n\t\t\t\toptions: this.buildDevServerTerminalOptions(options),\n\t\t\t})\n\t\t}\n\n\t\tif (enableTerminal) {\n\t\t\tterminalsToLaunch.push({\n\t\t\t\ttype: 'terminal',\n\t\t\t\toptions: this.buildStandaloneTerminalOptions(options),\n\t\t\t})\n\t\t}\n\n\t\tif (enableClaude) {\n\t\t\tterminalsToLaunch.push({\n\t\t\t\ttype: 'claude',\n\t\t\t\toptions: await this.buildClaudeTerminalOptions(options),\n\t\t\t})\n\t\t}\n\n\t\t// Launch terminals based on count\n\t\tif (terminalsToLaunch.length > 1) {\n\t\t\t// Multiple terminals - launch as tabs in single window\n\t\t\tgetLogger().debug(`Launching ${terminalsToLaunch.length} terminals in single window`)\n\t\t\tlaunchPromises.push(this.launchMultipleTerminals(terminalsToLaunch, options))\n\t\t} else if (terminalsToLaunch.length === 1) {\n\t\t\t// Single terminal - launch standalone\n\t\t\tconst terminal = terminalsToLaunch[0]\n\t\t\tif (!terminal) {\n\t\t\t\tthrow new Error('Terminal configuration is undefined')\n\t\t\t}\n\t\t\tconst terminalType = terminal.type\n\t\t\tgetLogger().debug(`Launching single ${terminalType} terminal`)\n\n\t\t\tif (terminalType === 'claude') {\n\t\t\t\tlaunchPromises.push(this.launchClaudeTerminal(options))\n\t\t\t} else if (terminalType === 'devServer') {\n\t\t\t\tlaunchPromises.push(this.launchDevServerTerminal(options))\n\t\t\t} else {\n\t\t\t\tlaunchPromises.push(this.launchStandaloneTerminal(options))\n\t\t\t}\n\t\t}\n\n\t\t// Wait for all components to launch\n\t\tawait Promise.all(launchPromises)\n\n\t\tgetLogger().success('loom launched successfully')\n\t}\n\n\t/**\n\t * Launch IDE (VSCode or configured alternative)\n\t */\n\tprivate async launchVSCode(options: LaunchLoomOptions): Promise<void> {\n\t\tconst ideConfig = await this.settings?.loadSettings().then((s) => s.ide)\n\t\tawait openIdeWindow(options.worktreePath, ideConfig)\n\t\tgetLogger().info('IDE opened')\n\t}\n\n\t/**\n\t * Launch Claude terminal\n\t */\n\tprivate async launchClaudeTerminal(options: LaunchLoomOptions): Promise<void> {\n\t\tawait this.claudeContext.launchWithContext({\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\ttype: options.workflowType,\n\t\t\tidentifier: options.identifier,\n\t\t\tbranchName: options.branchName,\n\t\t\t...(options.title && { title: options.title }),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t\toneShot: options.oneShot ?? 'default',\n\t\t\t...(options.setArguments && { setArguments: options.setArguments }),\n\t\t\t...(options.executablePath && { executablePath: options.executablePath }),\n\t\t})\n\t\tgetLogger().info('Claude terminal opened')\n\t}\n\n\t/**\n\t * Launch dev server terminal\n\t * Runs `il dev-server [identifier]` which handles env loading internally\n\t */\n\tprivate async launchDevServerTerminal(options: LaunchLoomOptions): Promise<void> {\n\t\t// Build dev-server command with identifier\n\t\tconst executable = options.executablePath ?? getExecutablePath()\n\t\tconst devServerIdentifier = String(options.identifier)\n\t\tconst devServerCommand = `${executable} dev-server ${devServerIdentifier}`\n\n\t\t// Only generate color if terminal coloring is enabled (default: true)\n\t\tconst backgroundColor = (options.colorTerminal ?? true)\n\t\t\t? options.colorHex\n\t\t\t\t? hexToRgb(options.colorHex)\n\t\t\t\t: generateColorFromBranchName(options.branchName).rgb\n\t\t\t: undefined\n\n\t\tawait openTerminalWindow({\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tcommand: devServerCommand,\n\t\t\t...(backgroundColor && { backgroundColor }),\n\t\t\t// il dev-server handles env loading internally, so no includeEnvSetup\n\t\t\tincludeEnvSetup: false,\n\t\t\tincludePortExport: options.capabilities.includes('web'),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t})\n\t\tgetLogger().info('Dev server terminal opened')\n\t}\n\n\t/**\n\t * Launch standalone terminal running `il shell <identifier>`\n\t */\n\tprivate async launchStandaloneTerminal(options: LaunchLoomOptions): Promise<void> {\n\t\t// Build shell command with identifier\n\t\tconst executable = options.executablePath ?? getExecutablePath()\n\t\tconst shellIdentifier = String(options.identifier)\n\t\tconst shellCommand = `${executable} shell ${shellIdentifier}`\n\n\t\t// Only generate color if terminal coloring is enabled (default: true)\n\t\tconst backgroundColor = (options.colorTerminal ?? true)\n\t\t\t? options.colorHex\n\t\t\t\t? hexToRgb(options.colorHex)\n\t\t\t\t: generateColorFromBranchName(options.branchName).rgb\n\t\t\t: undefined\n\n\t\tawait openTerminalWindow({\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tcommand: shellCommand,\n\t\t\t...(backgroundColor && { backgroundColor }),\n\t\t\t// il shell handles env loading internally, so we don't need includeEnvSetup\n\t\t\tincludeEnvSetup: false,\n\t\t\tincludePortExport: options.capabilities.includes('web'),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t})\n\t\tgetLogger().info('Standalone terminal opened')\n\t}\n\n\t/**\n\t * Build terminal options for Claude\n\t */\n\tprivate async buildClaudeTerminalOptions(\n\t\toptions: LaunchLoomOptions\n\t): Promise<TerminalWindowOptions> {\n\t\tconst hasEnvFile = this.hasAnyEnvFiles(options.worktreePath)\n\t\tconst claudeTitle = `Claude - ${this.formatIdentifier(options.workflowType, options.identifier)}`\n\n\t\tconst executable = options.executablePath ?? 'iloom'\n\t\tlet claudeCommand = `${executable} spin`\n\t\tif (options.oneShot !== undefined && options.oneShot !== 'default') {\n\t\t\tclaudeCommand += ` --one-shot=${options.oneShot}`\n\t\t}\n\t\tif (options.setArguments && options.setArguments.length > 0) {\n\t\t\tfor (const setArg of options.setArguments) {\n\t\t\t\tclaudeCommand += ` --set ${setArg}`\n\t\t\t}\n\t\t}\n\n\t\t// Only generate color if terminal coloring is enabled (default: true)\n\t\tconst backgroundColor = (options.colorTerminal ?? true)\n\t\t\t? options.colorHex\n\t\t\t\t? hexToRgb(options.colorHex)\n\t\t\t\t: generateColorFromBranchName(options.branchName).rgb\n\t\t\t: undefined\n\n\t\treturn {\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tcommand: claudeCommand,\n\t\t\t...(backgroundColor && { backgroundColor }),\n\t\t\ttitle: claudeTitle,\n\t\t\tincludeEnvSetup: (options.sourceEnvOnStart ?? false) && hasEnvFile,\n\t\t\t...(options.port !== undefined && { port: options.port, includePortExport: true }),\n\t\t}\n\t}\n\n\t/**\n\t * Build terminal options for dev server\n\t * Uses `il dev-server [identifier]` which handles env loading internally\n\t */\n\tprivate buildDevServerTerminalOptions(\n\t\toptions: LaunchLoomOptions\n\t): TerminalWindowOptions {\n\t\t// Build dev-server command with identifier\n\t\tconst executable = options.executablePath ?? getExecutablePath()\n\t\tconst devServerIdentifier = String(options.identifier)\n\t\tconst devServerCommand = `${executable} dev-server ${devServerIdentifier}`\n\n\t\tconst devServerTitle = `Dev Server - ${this.formatIdentifier(options.workflowType, options.identifier)}`\n\n\t\t// Only generate color if terminal coloring is enabled (default: true)\n\t\tconst backgroundColor = (options.colorTerminal ?? true)\n\t\t\t? options.colorHex\n\t\t\t\t? hexToRgb(options.colorHex)\n\t\t\t\t: generateColorFromBranchName(options.branchName).rgb\n\t\t\t: undefined\n\n\t\treturn {\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tcommand: devServerCommand,\n\t\t\t...(backgroundColor && { backgroundColor }),\n\t\t\ttitle: devServerTitle,\n\t\t\t// il dev-server handles env loading internally\n\t\t\tincludeEnvSetup: false,\n\t\t\tincludePortExport: options.capabilities.includes('web'),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t}\n\t}\n\n\t/**\n\t * Build terminal options for standalone terminal\n\t * Runs `il shell <identifier>` which handles env loading internally\n\t */\n\tprivate buildStandaloneTerminalOptions(\n\t\toptions: LaunchLoomOptions\n\t): TerminalWindowOptions {\n\t\tconst terminalTitle = `Terminal - ${this.formatIdentifier(options.workflowType, options.identifier)}`\n\n\t\t// Build shell command with identifier\n\t\t// Use the same executable path pattern as buildClaudeTerminalOptions\n\t\tconst executable = options.executablePath ?? getExecutablePath()\n\t\tconst shellIdentifier = String(options.identifier)\n\t\tconst shellCommand = `${executable} shell ${shellIdentifier}`\n\n\t\t// Only generate color if terminal coloring is enabled (default: true)\n\t\tconst backgroundColor = (options.colorTerminal ?? true)\n\t\t\t? options.colorHex\n\t\t\t\t? hexToRgb(options.colorHex)\n\t\t\t\t: generateColorFromBranchName(options.branchName).rgb\n\t\t\t: undefined\n\n\t\treturn {\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tcommand: shellCommand,\n\t\t\t...(backgroundColor && { backgroundColor }),\n\t\t\ttitle: terminalTitle,\n\t\t\t// il shell handles env loading internally, so we don't need includeEnvSetup\n\t\t\tincludeEnvSetup: false,\n\t\t\tincludePortExport: options.capabilities.includes('web'),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t}\n\t}\n\n\t/**\n\t * Launch multiple terminals (2+) as tabs in single window\n\t */\n\tprivate async launchMultipleTerminals(\n\t\tterminals: Array<{ type: string; options: TerminalWindowOptions }>,\n\t\t_options: LaunchLoomOptions\n\t): Promise<void> {\n\t\tconst terminalOptions = terminals.map((t) => t.options)\n\n\t\tawait openMultipleTerminalWindows(terminalOptions)\n\n\t\tconst terminalTypes = terminals.map((t) => t.type).join(' + ')\n\t\tgetLogger().info(`Multiple terminals opened: ${terminalTypes}`)\n\t}\n\n\t/**\n\t * Check if any dotenv-flow files exist in the workspace\n\t * Checks all files: .env, .env.local, .env.{NODE_ENV}, .env.{NODE_ENV}.local\n\t */\n\tprivate hasAnyEnvFiles(workspacePath: string): boolean {\n\t\tconst envFiles = getDotenvFlowFiles()\n\t\treturn envFiles.some(file => existsSync(join(workspacePath, file)))\n\t}\n\n\t/**\n\t * Format identifier for terminal tab titles\n\t */\n\tprivate formatIdentifier(workflowType: 'issue' | 'pr' | 'regular', identifier: string | number): string {\n\t\tif (workflowType === 'issue') {\n\t\t\treturn `Issue #${identifier}`\n\t\t} else if (workflowType === 'pr') {\n\t\t\treturn `PR #${identifier}`\n\t\t} else {\n\t\t\treturn `Branch: ${identifier}`\n\t\t}\n\t}\n}\n","import { execa } from 'execa'\nimport { logger } from './logger.js'\nimport type { IdeSettings } from '../lib/SettingsManager.js'\n\n// IDE preset configuration\nconst IDE_PRESETS = {\n\tvscode: { command: 'code', name: 'Visual Studio Code', args: [] },\n\tcursor: { command: 'cursor', name: 'Cursor', args: [] },\n\twebstorm: { command: 'webstorm', name: 'WebStorm', args: ['--nosplash'] },\n\tsublime: { command: 'subl', name: 'Sublime Text', args: [] },\n\tintellij: { command: 'idea', name: 'IntelliJ IDEA', args: ['--nosplash'] },\n\twindsurf: { command: 'surf', name: 'Windsurf', args: [] },\n\tantigravity: { command: 'agy', name: 'Antigravity', args: [] },\n} as const\n\ntype IdePreset = keyof typeof IDE_PRESETS\n\n// Resolve IDE configuration to command and args\nexport function getIdeConfig(ideSettings?: IdeSettings): {\n\tcommand: string\n\targs: string[]\n\tname: string\n} {\n\t// Default to vscode if not configured\n\tconst type = ideSettings?.type ?? 'vscode'\n\n\tconst preset = IDE_PRESETS[type as IdePreset]\n\treturn {\n\t\tcommand: preset.command,\n\t\targs: [...preset.args],\n\t\tname: preset.name,\n\t}\n}\n\n// Check if IDE is available\nexport async function isIdeAvailable(command: string): Promise<boolean> {\n\ttry {\n\t\tawait execa('command', ['-v', command], { shell: true, timeout: 5000 })\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\n// Get installation hint for IDE\nfunction getInstallHint(type: string): string {\n\tconst hints: Record<string, string> = {\n\t\tvscode:\n\t\t\t'Install command-line tools: Open VSCode > Command Palette > \"Shell Command: Install \\'code\\' command in PATH\"',\n\t\tcursor:\n\t\t\t'Install command-line tools: Open Cursor > Command Palette > \"Install \\'cursor\\' command in PATH\"',\n\t\twebstorm: 'Install via JetBrains Toolbox > Settings > Shell Scripts > Enable',\n\t\tsublime:\n\t\t\t'Create symlink: ln -s \"/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl\" /usr/local/bin/subl',\n\t\tintellij: 'Install via JetBrains Toolbox > Settings > Shell Scripts > Enable',\n\t\twindsurf:\n\t\t\t'Install command-line tools during Windsurf installation or create symlink manually',\n\t\tantigravity:\n\t\t\t'Install command-line tools during Antigravity installation or create symlink manually',\n\t}\n\treturn hints[type] ?? `Ensure the IDE command is available in your PATH`\n}\n\n// Open IDE window for workspace\nexport async function openIdeWindow(\n\tworkspacePath: string,\n\tideSettings?: IdeSettings\n): Promise<void> {\n\tconst config = getIdeConfig(ideSettings)\n\tconst available = await isIdeAvailable(config.command)\n\n\tif (!available) {\n\t\tconst type = ideSettings?.type ?? 'vscode'\n\t\tthrow new Error(\n\t\t\t`${config.name} is not available. The \"${config.command}\" command was not found in PATH.\\n` +\n\t\t\t\tgetInstallHint(type)\n\t\t)\n\t}\n\n\ttry {\n\t\tawait execa(config.command, [...config.args, workspacePath])\n\t\tlogger.debug(`Opened ${config.name} for workspace: ${workspacePath}`)\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to open ${config.name}: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t)\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ MetadataManager
4
+ } from "./chunk-YZTDGPFB.js";
5
+ import "./chunk-6UIGZD2N.js";
6
+ import "./chunk-UYVWLISQ.js";
7
+ export {
8
+ MetadataManager
9
+ };
10
+ //# sourceMappingURL=MetadataManager-WXUVXKUS.js.map
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ PRManager
4
+ } from "./chunk-P2ZQ5LKB.js";
5
+ import "./chunk-YETJNRQM.js";
6
+ import "./chunk-PSFVTBM7.js";
7
+ import "./chunk-KO2FOMHL.js";
8
+ import "./chunk-RUC7OULH.js";
9
+ import "./chunk-VAYGNQTE.js";
10
+ import "./chunk-Z5NXYJIG.js";
11
+ import "./chunk-6UIGZD2N.js";
12
+ import "./chunk-UYVWLISQ.js";
13
+ export {
14
+ PRManager
15
+ };
16
+ //# sourceMappingURL=PRManager-7DSIMCAD.js.map
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  PromptTemplateManager
4
- } from "./chunk-74VMN2KC.js";
4
+ } from "./chunk-DKQ4SUII.js";
5
5
  import "./chunk-UYVWLISQ.js";
6
6
  export {
7
7
  PromptTemplateManager
8
8
  };
9
- //# sourceMappingURL=PromptTemplateManager-2TDZAUC6.js.map
9
+ //# sourceMappingURL=PromptTemplateManager-72FEOGT6.js.map
package/dist/README.md CHANGED
@@ -232,6 +232,30 @@ This example shows how to configure a project-wide default (e.g., GitHub remote)
232
232
  }
233
233
  ```
234
234
 
235
+ ### Merge Behavior
236
+
237
+ Control how `il finish` handles your work. Configure in `.iloom/settings.json`:
238
+
239
+ ```json
240
+ {
241
+ "mergeBehavior": {
242
+ "mode": "local" // "local", "github-pr", or "github-draft-pr"
243
+ }
244
+ }
245
+ ```
246
+
247
+ | **Mode** | **Description** |
248
+ |----------|-----------------|
249
+ | `local` | (Default) Merge directly into main branch locally. Fast-forward merge, no PR created. |
250
+ | `github-pr` | Push branch and create a GitHub PR on `il finish`. Worktree cleanup is optional. |
251
+ | `github-draft-pr` | Create a draft PR immediately on `il start`. On `il finish`, the PR is marked ready for review. **Recommended for contributions to forked repos.** |
252
+
253
+ **When to use `github-draft-pr`:**
254
+ - **Contributing to forks:** When you don't are contributing to a forked repo use this mode to create the PR from your fork immediately, allowing iloom's agents to post workflow comments directly to the PR instead of writing to the upstream repo's issues (which may not be appreciated by the repo owners).
255
+ - CI runs on your branch during development (draft PRs trigger CI on most repos)
256
+ - Your team requires PRs for all changes (no direct merges to main)
257
+ - You want reviewers to see progress before the work is complete
258
+
235
259
  Integrations
236
260
  ------------
237
261
 
@@ -14,7 +14,7 @@ import {
14
14
  WorkflowPermissionSchemaNoDefaults,
15
15
  WorkflowsSettingsSchema,
16
16
  WorkflowsSettingsSchemaNoDefaults
17
- } from "./chunk-VWNS6DH5.js";
17
+ } from "./chunk-OOU3DKNT.js";
18
18
  import "./chunk-UYVWLISQ.js";
19
19
  export {
20
20
  AgentSettingsSchema,
@@ -32,4 +32,4 @@ export {
32
32
  WorkflowsSettingsSchema,
33
33
  WorkflowsSettingsSchemaNoDefaults
34
34
  };
35
- //# sourceMappingURL=SettingsManager-FJFU6JJD.js.map
35
+ //# sourceMappingURL=SettingsManager-XPR4TEQL.js.map
@@ -1,13 +1,30 @@
1
1
  ---
2
2
  name: iloom-issue-analyze-and-plan
3
3
  description: Combined analysis and planning agent for SIMPLE tasks. This agent performs lightweight analysis and creates an implementation plan in one streamlined phase. Only invoked for tasks pre-classified as SIMPLE (< 5 files, <200 LOC, no breaking changes, no DB migrations). Use this agent when you have a simple issue that needs quick analysis followed by immediate planning.
4
- tools: Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__figma-dev-mode-mcp-server__get_code, mcp__figma-dev-mode-mcp-server__get_variable_defs, mcp__figma-dev-mode-mcp-server__get_code_connect_map, mcp__figma-dev-mode-mcp-server__get_screenshot, mcp__figma-dev-mode-mcp-server__get_metadata, mcp__figma-dev-mode-mcp-server__add_code_connect_map, mcp__figma-dev-mode-mcp-server__create_design_system_rules, Bash(git show:*),mcp__issue_management__update_comment, mcp__issue_management__get_issue, mcp__issue_management__get_comment, mcp__issue_management__create_comment
4
+ tools: Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__figma-dev-mode-mcp-server__get_code, mcp__figma-dev-mode-mcp-server__get_variable_defs, mcp__figma-dev-mode-mcp-server__get_code_connect_map, mcp__figma-dev-mode-mcp-server__get_screenshot, mcp__figma-dev-mode-mcp-server__get_metadata, mcp__figma-dev-mode-mcp-server__add_code_connect_map, mcp__figma-dev-mode-mcp-server__create_design_system_rules, Bash(git show:*), mcp__issue_management__update_comment, mcp__issue_management__get_issue, mcp__issue_management__get_comment, mcp__issue_management__create_comment, mcp__recap__get_recap, mcp__recap__add_entry, mcp__recap__add_artifact
5
5
  color: teal
6
6
  model: sonnet
7
7
  ---
8
8
 
9
9
  You are Claude, an AI assistant specialized in combined analysis and planning for simple issues. You excel at efficiently handling straightforward tasks that have been pre-classified as SIMPLE by the complexity evaluator.
10
10
 
11
+ ## Loom Recap
12
+
13
+ The recap panel helps users stay oriented without reading all your output. Capture key findings using the Recap MCP tools:
14
+ - `recap.get_recap` - Check existing entries to avoid duplicates
15
+ - `recap.add_entry` - Log with appropriate type
16
+ - `recap.add_artifact` - After creating any comment, log it with type='comment', primaryUrl, and description. Re-calling with the same primaryUrl will update the existing entry.
17
+
18
+ **During analysis, log:**
19
+ - **insight**: Technical discoveries - "Config parsing happens before env vars are loaded"
20
+ - **risk**: Things that could go wrong - "Removing this validation will allow malformed input to reach the database"
21
+
22
+ **During planning, log:**
23
+ - **decision**: Significant choices - "Using WebSocket instead of polling for real-time updates"
24
+ - **assumption**: Bets you're making - "Assuming no backwards compat needed"
25
+
26
+ **Never log** workflow status, complexity classifications, or phase information.
27
+
11
28
  **Your Core Mission**: For SIMPLE tasks only, you will perform lightweight technical analysis AND create a focused implementation plan in one streamlined phase. **Target: <5 minutes to read Section 1. If your visible output exceeds this, you are being too detailed.**
12
29
 
13
30
  **IMPORTANT**: You are only invoked for pre-classified SIMPLE tasks. Do NOT second-guess the complexity assessment - trust that the evaluator has correctly classified this as a simple task.
@@ -208,8 +225,9 @@ Available Tools:
208
225
  Parameters: { commentId: string, number: string }
209
226
  Returns: { id, body, author, created_at, ... }
210
227
 
211
- - mcp__issue_management__create_comment: Create a new comment on issue ISSUE_NUMBER
212
- Parameters: { number: string, body: "markdown content", type: "issue" }
228
+ {{#IF DRAFT_PR_MODE}}- mcp__issue_management__create_comment: Create a new comment on PR DRAFT_PR_NUMBER
229
+ Parameters: { number: string, body: "markdown content", type: "pr" }{{/IF DRAFT_PR_MODE}}{{#IF STANDARD_ISSUE_MODE}}- mcp__issue_management__create_comment: Create a new comment on issue ISSUE_NUMBER
230
+ Parameters: { number: string, body: "markdown content", type: "issue" }{{/IF STANDARD_ISSUE_MODE}}
213
231
  Returns: { id: string, url: string, created_at: string }
214
232
 
215
233
  - mcp__issue_management__update_comment: Update an existing comment
@@ -218,7 +236,7 @@ Available Tools:
218
236
 
219
237
  Workflow Comment Strategy:
220
238
  1. When beginning work, create a NEW comment informing the user you are working on Analysis and Planning.
221
- 2. Store the returned comment ID
239
+ 2. Store the returned comment ID and URL. After creating the comment, call `mcp__recap__add_artifact` to log it with type='comment', primaryUrl=[comment URL], and a brief description (e.g., "Analysis and planning comment").
222
240
  3. Once you have formulated your tasks in a todo format, update the comment using mcp__issue_management__update_comment with your tasks formatted as checklists using markdown:
223
241
  - [ ] for incomplete tasks (which should be all of them at this point)
224
242
  4. After you complete every todo item, update the comment using mcp__issue_management__update_comment with your progress - you may add todo items if you need:
@@ -232,17 +250,33 @@ Workflow Comment Strategy:
232
250
  Example Usage:
233
251
  ```
234
252
  // Start
235
- const comment = await mcp__issue_management__create_comment({
253
+ {{#IF DRAFT_PR_MODE}}const comment = await mcp__issue_management__create_comment({
254
+ number: DRAFT_PR_NUMBER,
255
+ body: "# Combined Analysis and Planning\n\n- [ ] Perform lightweight analysis\n- [ ] Create implementation plan",
256
+ type: "pr"
257
+ }){{/IF DRAFT_PR_MODE}}{{#IF STANDARD_ISSUE_MODE}}const comment = await mcp__issue_management__create_comment({
236
258
  number: ISSUE_NUMBER,
237
259
  body: "# Combined Analysis and Planning\n\n- [ ] Perform lightweight analysis\n- [ ] Create implementation plan",
238
260
  type: "issue"
261
+ }){{/IF STANDARD_ISSUE_MODE}}
262
+
263
+ // Log the comment as an artifact
264
+ await mcp__recap__add_artifact({
265
+ type: "comment",
266
+ primaryUrl: comment.url,
267
+ description: "Analysis and planning comment"
239
268
  })
240
269
 
241
270
  // Update as you progress
242
- await mcp__issue_management__update_comment({
271
+ {{#IF DRAFT_PR_MODE}}await mcp__issue_management__update_comment({
243
272
  commentId: comment.id,
273
+ number: DRAFT_PR_NUMBER,
244
274
  body: "# Combined Analysis and Planning\n\n- [x] Perform lightweight analysis\n- [ ] Create implementation plan"
245
- })
275
+ }){{/IF DRAFT_PR_MODE}}{{#IF STANDARD_ISSUE_MODE}}await mcp__issue_management__update_comment({
276
+ commentId: comment.id,
277
+ number: ISSUE_NUMBER,
278
+ body: "# Combined Analysis and Planning\n\n- [x] Perform lightweight analysis\n- [ ] Create implementation plan"
279
+ }){{/IF STANDARD_ISSUE_MODE}}
246
280
  ```
247
281
  </comment_tool_info>
248
282
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: iloom-issue-analyzer
3
3
  description: Use this agent when you need to analyze and research issues, bugs, or enhancement requests. The agent will investigate the codebase, recent commits, and third-party dependencies to identify root causes WITHOUT proposing solutions. Ideal for initial issue triage, regression analysis, and documenting technical findings for team discussion.\n\nExamples:\n<example>\nContext: User wants to analyze a newly reported bug in issue #42\nuser: "Please analyze issue #42 - users are reporting that the login button doesn't work on mobile"\nassistant: "I'll use the issue-analyzer agent to investigate this issue and document my findings."\n<commentary>\nSince this is a request to analyze an issue, use the Task tool to launch the issue-analyzer agent to research the problem.\n</commentary>\n</example>\n<example>\nContext: User needs to understand a regression that appeared after recent changes\nuser: "Can you look into issue #78? It seems like something broke after yesterday's deployment"\nassistant: "Let me launch the issue-analyzer agent to research this regression and identify what changed."\n<commentary>\nThe user is asking for issue analysis and potential regression investigation, so use the issue-analyzer agent.\n</commentary>\n</example>
4
- tools: Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__figma-dev-mode-mcp-server__get_code, mcp__figma-dev-mode-mcp-server__get_variable_defs, mcp__figma-dev-mode-mcp-server__get_code_connect_map, mcp__figma-dev-mode-mcp-server__get_screenshot, mcp__figma-dev-mode-mcp-server__get_metadata, mcp__figma-dev-mode-mcp-server__add_code_connect_map, mcp__figma-dev-mode-mcp-server__create_design_system_rules ,Bash(git show:*),mcp__issue_management__update_comment, mcp__issue_management__get_issue, mcp__issue_management__get_comment, mcp__issue_management__create_comment
4
+ tools: Bash, Glob, Grep, Read, Edit, Write, NotebookEdit, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, SlashCommand, ListMcpResourcesTool, ReadMcpResourceTool, mcp__context7__resolve-library-id, mcp__context7__get-library-docs, mcp__figma-dev-mode-mcp-server__get_code, mcp__figma-dev-mode-mcp-server__get_variable_defs, mcp__figma-dev-mode-mcp-server__get_code_connect_map, mcp__figma-dev-mode-mcp-server__get_screenshot, mcp__figma-dev-mode-mcp-server__get_metadata, mcp__figma-dev-mode-mcp-server__add_code_connect_map, mcp__figma-dev-mode-mcp-server__create_design_system_rules, Bash(git show:*), mcp__issue_management__update_comment, mcp__issue_management__get_issue, mcp__issue_management__get_comment, mcp__issue_management__create_comment, mcp__recap__get_recap, mcp__recap__add_entry, mcp__recap__add_artifact
5
5
  color: pink
6
6
  model: sonnet
7
7
  ---
@@ -10,6 +10,19 @@ You are Claude, an elite issue analyst specializing in deep technical investigat
10
10
 
11
11
  **Your Core Mission**: Analyze issues to identify root causes and document key findings concisely. You research but you do not solve or propose solutions - your role is to provide the technical intelligence needed for informed decision-making.
12
12
 
13
+ ## Loom Recap
14
+
15
+ The recap panel helps users stay oriented without reading all your output. Capture key discoveries using the Recap MCP tools:
16
+ - `recap.get_recap` - Check existing entries to avoid duplicates
17
+ - `recap.add_entry` - Log with type: `insight` or `risk`
18
+ - `recap.add_artifact` - After creating any comment, log it with type='comment', primaryUrl, and description. Re-calling with the same primaryUrl will update the existing entry.
19
+
20
+ **Log these:**
21
+ - **insight**: Technical discoveries - "Auth module depends on session middleware being initialized first"
22
+ - **risk**: Things that could go wrong - "Removing this function breaks the CLI's --verbose flag"
23
+
24
+ **Never log** workflow status, complexity classifications, or what phases you skipped.
25
+
13
26
  ## Core Workflow
14
27
 
15
28
  ### Step 1: Fetch the Issue
@@ -285,8 +298,9 @@ Available Tools:
285
298
  Parameters: { commentId: string, number: string }
286
299
  Returns: { id, body, author, created_at, ... }
287
300
 
288
- - mcp__issue_management__create_comment: Create a new comment on issue ISSUE_NUMBER
289
- Parameters: { number: string, body: "markdown content", type: "issue" }
301
+ {{#IF DRAFT_PR_MODE}}- mcp__issue_management__create_comment: Create a new comment on PR DRAFT_PR_NUMBER
302
+ Parameters: { number: string, body: "markdown content", type: "pr" }{{/IF DRAFT_PR_MODE}}{{#IF STANDARD_ISSUE_MODE}}- mcp__issue_management__create_comment: Create a new comment on issue ISSUE_NUMBER
303
+ Parameters: { number: string, body: "markdown content", type: "issue" }{{/IF STANDARD_ISSUE_MODE}}
290
304
  Returns: { id: string, url: string, created_at: string }
291
305
 
292
306
  - mcp__issue_management__update_comment: Update an existing comment
@@ -295,13 +309,13 @@ Available Tools:
295
309
 
296
310
  Workflow Comment Strategy:
297
311
  1. When beginning analysis/research, create a NEW comment informing the user you are working on analyzing the issue.
298
- 2. Store the returned comment ID
312
+ 2. Store the returned comment ID and URL. After creating the comment, call `mcp__recap__add_artifact` to log it with type='comment', primaryUrl=[comment URL], and a brief description (e.g., "Analysis progress comment").
299
313
  3. Once you have formulated your tasks in a todo format, update the comment using mcp__issue_management__update_comment with your tasks formatted as checklists using markdown:
300
314
  - [ ] for incomplete tasks (which should be all of them at this point)
301
315
  4. After you complete every todo item, update the comment using mcp__issue_management__update_comment with your progress - you may add todo items if you need:
302
316
  - [ ] for incomplete tasks
303
317
  - [x] for completed tasks
304
-
318
+
305
319
  * Include relevant context (current step, progress, blockers) and a **very aggressive** estimated time to completion of this step and the whole task in each update after the comment's todo list
306
320
  5. When you have finished your task, update the same comment as before - MAKE SURE YOU DO NOT ERASE THE "details" section, then let the calling process know the full web URL of the issue comment, including the comment ID. NEVER ATTEMPT CONCURRENT UPDATES OF THE COMMENT. DATA WILL BE LOST.
307
321
  6. CONSTRAINT: After you create the initial comment, you may not create another comment. You must always update the initial comment instead.
@@ -309,17 +323,33 @@ Workflow Comment Strategy:
309
323
  Example Usage:
310
324
  ```
311
325
  // Start
312
- const comment = await mcp__issue_management__create_comment({
326
+ {{#IF DRAFT_PR_MODE}}const comment = await mcp__issue_management__create_comment({
327
+ number: DRAFT_PR_NUMBER,
328
+ body: "# Analysis Phase\n\n- [ ] Fetch issue details\n- [ ] Analyze requirements",
329
+ type: "pr"
330
+ }){{/IF DRAFT_PR_MODE}}{{#IF STANDARD_ISSUE_MODE}}const comment = await mcp__issue_management__create_comment({
313
331
  number: ISSUE_NUMBER,
314
332
  body: "# Analysis Phase\n\n- [ ] Fetch issue details\n- [ ] Analyze requirements",
315
333
  type: "issue"
334
+ }){{/IF STANDARD_ISSUE_MODE}}
335
+
336
+ // Log the comment as an artifact
337
+ await mcp__recap__add_artifact({
338
+ type: "comment",
339
+ primaryUrl: comment.url,
340
+ description: "Analysis progress comment"
316
341
  })
317
342
 
318
343
  // Update as you progress
319
- await mcp__issue_management__update_comment({
344
+ {{#IF DRAFT_PR_MODE}}await mcp__issue_management__update_comment({
320
345
  commentId: comment.id,
346
+ number: DRAFT_PR_NUMBER,
321
347
  body: "# Analysis Phase\n\n- [x] Fetch issue details\n- [ ] Analyze requirements"
322
- })
348
+ }){{/IF DRAFT_PR_MODE}}{{#IF STANDARD_ISSUE_MODE}}await mcp__issue_management__update_comment({
349
+ commentId: comment.id,
350
+ number: ISSUE_NUMBER,
351
+ body: "# Analysis Phase\n\n- [x] Fetch issue details\n- [ ] Analyze requirements"
352
+ }){{/IF STANDARD_ISSUE_MODE}}
323
353
  ```
324
354
  </comment_tool_info>
325
355