@iloom/cli 0.4.1 → 0.5.1

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 (121) hide show
  1. package/README.md +24 -0
  2. package/dist/{ClaudeContextManager-DK77227F.js → ClaudeContextManager-DQFKIMEP.js} +5 -5
  3. package/dist/{ClaudeService-W3SA7HVG.js → ClaudeService-CJS32WG2.js} +4 -4
  4. package/dist/{LoomLauncher-S3YGJRJQ.js → LoomLauncher-JNWBMHES.js} +22 -88
  5. package/dist/LoomLauncher-JNWBMHES.js.map +1 -0
  6. package/dist/MetadataManager-WXUVXKUS.js +10 -0
  7. package/dist/PRManager-7DSIMCAD.js +16 -0
  8. package/dist/{PromptTemplateManager-2TDZAUC6.js → PromptTemplateManager-72FEOGT6.js} +2 -2
  9. package/dist/README.md +24 -0
  10. package/dist/{SettingsManager-FJFU6JJD.js → SettingsManager-XPR4TEQL.js} +2 -2
  11. package/dist/agents/iloom-issue-analyze-and-plan.md +41 -7
  12. package/dist/agents/iloom-issue-analyzer.md +38 -8
  13. package/dist/agents/iloom-issue-complexity-evaluator.md +45 -15
  14. package/dist/agents/iloom-issue-enhancer.md +60 -18
  15. package/dist/agents/iloom-issue-implementer.md +29 -7
  16. package/dist/agents/iloom-issue-planner.md +36 -7
  17. package/dist/agents/iloom-issue-reviewer.md +30 -7
  18. package/dist/{chunk-JC5HXN75.js → chunk-3CMGCRB5.js} +2 -2
  19. package/dist/{chunk-G6CIIJLT.js → chunk-4YTILIIH.js} +7 -8
  20. package/dist/chunk-4YTILIIH.js.map +1 -0
  21. package/dist/{chunk-IARWMDAX.js → chunk-6KB7R22U.js} +98 -16
  22. package/dist/chunk-6KB7R22U.js.map +1 -0
  23. package/dist/{chunk-55TB3FSG.js → chunk-AS2IRKLU.js} +2 -2
  24. package/dist/{chunk-VTXCGKV5.js → chunk-BVIK2P6P.js} +11 -3
  25. package/dist/chunk-BVIK2P6P.js.map +1 -0
  26. package/dist/chunk-CDF7ZX2B.js +72 -0
  27. package/dist/chunk-CDF7ZX2B.js.map +1 -0
  28. package/dist/{chunk-POI7KLBH.js → chunk-CDQEK2WD.js} +5 -5
  29. package/dist/{chunk-74VMN2KC.js → chunk-DKQ4SUII.js} +16 -1
  30. package/dist/chunk-DKQ4SUII.js.map +1 -0
  31. package/dist/{chunk-BIIQHEXJ.js → chunk-GVRO4PWE.js} +12 -8
  32. package/dist/chunk-GVRO4PWE.js.map +1 -0
  33. package/dist/{chunk-TMZAVPGF.js → chunk-HABINPX2.js} +71 -15
  34. package/dist/{chunk-TMZAVPGF.js.map → chunk-HABINPX2.js.map} +1 -1
  35. package/dist/{chunk-2W2FBL5G.js → chunk-LN4H3A6A.js} +66 -7
  36. package/dist/chunk-LN4H3A6A.js.map +1 -0
  37. package/dist/{chunk-VWNS6DH5.js → chunk-OOU3DKNT.js} +13 -7
  38. package/dist/chunk-OOU3DKNT.js.map +1 -0
  39. package/dist/chunk-P2ZQ5LKB.js +347 -0
  40. package/dist/chunk-P2ZQ5LKB.js.map +1 -0
  41. package/dist/{chunk-OF7BNW4D.js → chunk-RJKMF6BC.js} +30 -4
  42. package/dist/chunk-RJKMF6BC.js.map +1 -0
  43. package/dist/{chunk-O7WHXLCB.js → chunk-RNZMHJK7.js} +18 -4
  44. package/dist/chunk-RNZMHJK7.js.map +1 -0
  45. package/dist/{chunk-UPUAQYAW.js → chunk-S65T4O6I.js} +2 -2
  46. package/dist/{chunk-HD5SUKI2.js → chunk-TSLKDFAF.js} +55 -6
  47. package/dist/chunk-TSLKDFAF.js.map +1 -0
  48. package/dist/{chunk-IJ7IGJT3.js → chunk-YZTDGPFB.js} +18 -1
  49. package/dist/chunk-YZTDGPFB.js.map +1 -0
  50. package/dist/{cleanup-KDLVTT7M.js → cleanup-LU6NU2NZ.js} +14 -14
  51. package/dist/cli.js +283 -363
  52. package/dist/cli.js.map +1 -1
  53. package/dist/{contribute-HY372S6F.js → contribute-RS3DO3WP.js} +4 -4
  54. package/dist/{dev-server-JCJGQ3PV.js → dev-server-ASH7HJVI.js} +30 -16
  55. package/dist/dev-server-ASH7HJVI.js.map +1 -0
  56. package/dist/{feedback-7PVBQNLJ.js → feedback-OFVW22UW.js} +11 -6
  57. package/dist/{feedback-7PVBQNLJ.js.map → feedback-OFVW22UW.js.map} +1 -1
  58. package/dist/{git-4BVOOOOV.js → git-OQAPUPLP.js} +16 -6
  59. package/dist/git-OQAPUPLP.js.map +1 -0
  60. package/dist/{ignite-3B264M7K.js → ignite-NREQ3JRM.js} +57 -22
  61. package/dist/ignite-NREQ3JRM.js.map +1 -0
  62. package/dist/index.d.ts +58 -7
  63. package/dist/index.js +110 -7
  64. package/dist/index.js.map +1 -1
  65. package/dist/{init-LBA6NUK2.js → init-F6PFMSU5.js} +7 -7
  66. package/dist/init-F6PFMSU5.js.map +1 -0
  67. package/dist/mcp/recap-server.js +264 -0
  68. package/dist/mcp/recap-server.js.map +1 -0
  69. package/dist/{open-OGCV32Z4.js → open-KW4NTLXH.js} +16 -17
  70. package/dist/{open-OGCV32Z4.js.map → open-KW4NTLXH.js.map} +1 -1
  71. package/dist/{projects-P55273AB.js → projects-QEAEBAT2.js} +2 -2
  72. package/dist/prompts/init-prompt.txt +31 -72
  73. package/dist/prompts/issue-prompt.txt +115 -15
  74. package/dist/prompts/pr-prompt.txt +49 -1
  75. package/dist/prompts/regular-prompt.txt +80 -20
  76. package/dist/{rebase-4T5FQHNH.js → rebase-WZHHE5LU.js} +6 -6
  77. package/dist/recap-33NPZ3ZO.js +117 -0
  78. package/dist/recap-33NPZ3ZO.js.map +1 -0
  79. package/dist/{run-HNOP6WE2.js → run-HRYQ7TR7.js} +16 -17
  80. package/dist/{run-HNOP6WE2.js.map → run-HRYQ7TR7.js.map} +1 -1
  81. package/dist/schema/settings.schema.json +13 -2
  82. package/dist/{shell-DE3HKJSM.js → shell-JMU5XTHW.js} +6 -6
  83. package/dist/{summary-GDT7DTRI.js → summary-4SSGGH7N.js} +17 -9
  84. package/dist/summary-4SSGGH7N.js.map +1 -0
  85. package/dist/{test-git-YMAE57UP.js → test-git-6SAIRBUD.js} +4 -4
  86. package/dist/{test-prefix-YCKL6CMT.js → test-prefix-RLVRK5ZD.js} +4 -4
  87. package/package.json +1 -1
  88. package/dist/LoomLauncher-S3YGJRJQ.js.map +0 -1
  89. package/dist/chunk-2W2FBL5G.js.map +0 -1
  90. package/dist/chunk-74VMN2KC.js.map +0 -1
  91. package/dist/chunk-BIIQHEXJ.js.map +0 -1
  92. package/dist/chunk-G6CIIJLT.js.map +0 -1
  93. package/dist/chunk-HD5SUKI2.js.map +0 -1
  94. package/dist/chunk-IARWMDAX.js.map +0 -1
  95. package/dist/chunk-IJ7IGJT3.js.map +0 -1
  96. package/dist/chunk-O7WHXLCB.js.map +0 -1
  97. package/dist/chunk-OF7BNW4D.js.map +0 -1
  98. package/dist/chunk-QRBOPFAA.js +0 -48
  99. package/dist/chunk-QRBOPFAA.js.map +0 -1
  100. package/dist/chunk-VTXCGKV5.js.map +0 -1
  101. package/dist/chunk-VWNS6DH5.js.map +0 -1
  102. package/dist/dev-server-JCJGQ3PV.js.map +0 -1
  103. package/dist/ignite-3B264M7K.js.map +0 -1
  104. package/dist/summary-GDT7DTRI.js.map +0 -1
  105. /package/dist/{ClaudeContextManager-DK77227F.js.map → ClaudeContextManager-DQFKIMEP.js.map} +0 -0
  106. /package/dist/{ClaudeService-W3SA7HVG.js.map → ClaudeService-CJS32WG2.js.map} +0 -0
  107. /package/dist/{PromptTemplateManager-2TDZAUC6.js.map → MetadataManager-WXUVXKUS.js.map} +0 -0
  108. /package/dist/{SettingsManager-FJFU6JJD.js.map → PRManager-7DSIMCAD.js.map} +0 -0
  109. /package/dist/{git-4BVOOOOV.js.map → PromptTemplateManager-72FEOGT6.js.map} +0 -0
  110. /package/dist/{init-LBA6NUK2.js.map → SettingsManager-XPR4TEQL.js.map} +0 -0
  111. /package/dist/{chunk-JC5HXN75.js.map → chunk-3CMGCRB5.js.map} +0 -0
  112. /package/dist/{chunk-55TB3FSG.js.map → chunk-AS2IRKLU.js.map} +0 -0
  113. /package/dist/{chunk-POI7KLBH.js.map → chunk-CDQEK2WD.js.map} +0 -0
  114. /package/dist/{chunk-UPUAQYAW.js.map → chunk-S65T4O6I.js.map} +0 -0
  115. /package/dist/{cleanup-KDLVTT7M.js.map → cleanup-LU6NU2NZ.js.map} +0 -0
  116. /package/dist/{contribute-HY372S6F.js.map → contribute-RS3DO3WP.js.map} +0 -0
  117. /package/dist/{projects-P55273AB.js.map → projects-QEAEBAT2.js.map} +0 -0
  118. /package/dist/{rebase-4T5FQHNH.js.map → rebase-WZHHE5LU.js.map} +0 -0
  119. /package/dist/{shell-DE3HKJSM.js.map → shell-JMU5XTHW.js.map} +0 -0
  120. /package/dist/{test-git-YMAE57UP.js.map → test-git-6SAIRBUD.js.map} +0 -0
  121. /package/dist/{test-prefix-YCKL6CMT.js.map → test-prefix-RLVRK5ZD.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
 
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ClaudeContextManager
4
- } from "./chunk-UPUAQYAW.js";
5
- import "./chunk-POI7KLBH.js";
6
- import "./chunk-VWNS6DH5.js";
4
+ } from "./chunk-S65T4O6I.js";
5
+ import "./chunk-CDQEK2WD.js";
6
+ import "./chunk-DKQ4SUII.js";
7
+ import "./chunk-OOU3DKNT.js";
7
8
  import "./chunk-RUC7OULH.js";
8
9
  import "./chunk-VAYGNQTE.js";
9
10
  import "./chunk-Z5NXYJIG.js";
10
11
  import "./chunk-6UIGZD2N.js";
11
- import "./chunk-74VMN2KC.js";
12
12
  import "./chunk-UYVWLISQ.js";
13
13
  export {
14
14
  ClaudeContextManager
15
15
  };
16
- //# sourceMappingURL=ClaudeContextManager-DK77227F.js.map
16
+ //# sourceMappingURL=ClaudeContextManager-DQFKIMEP.js.map
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ClaudeService
4
- } from "./chunk-POI7KLBH.js";
5
- import "./chunk-VWNS6DH5.js";
4
+ } from "./chunk-CDQEK2WD.js";
5
+ import "./chunk-DKQ4SUII.js";
6
+ import "./chunk-OOU3DKNT.js";
6
7
  import "./chunk-RUC7OULH.js";
7
8
  import "./chunk-VAYGNQTE.js";
8
9
  import "./chunk-Z5NXYJIG.js";
9
10
  import "./chunk-6UIGZD2N.js";
10
- import "./chunk-74VMN2KC.js";
11
11
  import "./chunk-UYVWLISQ.js";
12
12
  export {
13
13
  ClaudeService
14
14
  };
15
- //# sourceMappingURL=ClaudeService-W3SA7HVG.js.map
15
+ //# sourceMappingURL=ClaudeService-CJS32WG2.js.map
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- getDevServerLaunchCommand
4
- } from "./chunk-QRBOPFAA.js";
5
- import "./chunk-VBFDVGAE.js";
3
+ openIdeWindow
4
+ } from "./chunk-CDF7ZX2B.js";
6
5
  import {
7
6
  ClaudeContextManager
8
- } from "./chunk-UPUAQYAW.js";
9
- import "./chunk-POI7KLBH.js";
7
+ } from "./chunk-S65T4O6I.js";
8
+ import "./chunk-CDQEK2WD.js";
9
+ import "./chunk-DKQ4SUII.js";
10
10
  import {
11
11
  getExecutablePath
12
12
  } from "./chunk-GYCR2LOU.js";
13
- import "./chunk-VWNS6DH5.js";
13
+ import "./chunk-OOU3DKNT.js";
14
14
  import {
15
15
  generateColorFromBranchName,
16
16
  hexToRgb
@@ -26,76 +26,11 @@ import {
26
26
  import {
27
27
  getLogger
28
28
  } from "./chunk-6UIGZD2N.js";
29
- import "./chunk-74VMN2KC.js";
30
- import {
31
- logger
32
- } from "./chunk-UYVWLISQ.js";
29
+ import "./chunk-UYVWLISQ.js";
33
30
 
34
31
  // src/lib/LoomLauncher.ts
35
32
  import { existsSync } from "fs";
36
33
  import { join } from "path";
37
-
38
- // src/utils/ide.ts
39
- import { execa } from "execa";
40
- var IDE_PRESETS = {
41
- vscode: { command: "code", name: "Visual Studio Code", args: [] },
42
- cursor: { command: "cursor", name: "Cursor", args: [] },
43
- webstorm: { command: "webstorm", name: "WebStorm", args: ["--nosplash"] },
44
- sublime: { command: "subl", name: "Sublime Text", args: [] },
45
- intellij: { command: "idea", name: "IntelliJ IDEA", args: ["--nosplash"] },
46
- windsurf: { command: "surf", name: "Windsurf", args: [] },
47
- antigravity: { command: "agy", name: "Antigravity", args: [] }
48
- };
49
- function getIdeConfig(ideSettings) {
50
- const type = (ideSettings == null ? void 0 : ideSettings.type) ?? "vscode";
51
- const preset = IDE_PRESETS[type];
52
- return {
53
- command: preset.command,
54
- args: [...preset.args],
55
- name: preset.name
56
- };
57
- }
58
- async function isIdeAvailable(command) {
59
- try {
60
- await execa("command", ["-v", command], { shell: true, timeout: 5e3 });
61
- return true;
62
- } catch {
63
- return false;
64
- }
65
- }
66
- function getInstallHint(type) {
67
- const hints = {
68
- vscode: `Install command-line tools: Open VSCode > Command Palette > "Shell Command: Install 'code' command in PATH"`,
69
- cursor: `Install command-line tools: Open Cursor > Command Palette > "Install 'cursor' command in PATH"`,
70
- webstorm: "Install via JetBrains Toolbox > Settings > Shell Scripts > Enable",
71
- sublime: 'Create symlink: ln -s "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl" /usr/local/bin/subl',
72
- intellij: "Install via JetBrains Toolbox > Settings > Shell Scripts > Enable",
73
- windsurf: "Install command-line tools during Windsurf installation or create symlink manually",
74
- antigravity: "Install command-line tools during Antigravity installation or create symlink manually"
75
- };
76
- return hints[type] ?? `Ensure the IDE command is available in your PATH`;
77
- }
78
- async function openIdeWindow(workspacePath, ideSettings) {
79
- const config = getIdeConfig(ideSettings);
80
- const available = await isIdeAvailable(config.command);
81
- if (!available) {
82
- const type = (ideSettings == null ? void 0 : ideSettings.type) ?? "vscode";
83
- throw new Error(
84
- `${config.name} is not available. The "${config.command}" command was not found in PATH.
85
- ` + getInstallHint(type)
86
- );
87
- }
88
- try {
89
- await execa(config.command, [...config.args, workspacePath]);
90
- logger.debug(`Opened ${config.name} for workspace: ${workspacePath}`);
91
- } catch (error) {
92
- throw new Error(
93
- `Failed to open ${config.name}: ${error instanceof Error ? error.message : "Unknown error"}`
94
- );
95
- }
96
- }
97
-
98
- // src/lib/LoomLauncher.ts
99
34
  var LoomLauncher = class {
100
35
  constructor(claudeContext, settings) {
101
36
  this.claudeContext = claudeContext ?? new ClaudeContextManager();
@@ -118,7 +53,7 @@ var LoomLauncher = class {
118
53
  if (enableDevServer) {
119
54
  terminalsToLaunch.push({
120
55
  type: "devServer",
121
- options: await this.buildDevServerTerminalOptions(options)
56
+ options: this.buildDevServerTerminalOptions(options)
122
57
  });
123
58
  }
124
59
  if (enableTerminal) {
@@ -182,19 +117,19 @@ var LoomLauncher = class {
182
117
  }
183
118
  /**
184
119
  * Launch dev server terminal
120
+ * Runs `il dev-server [identifier]` which handles env loading internally
185
121
  */
186
122
  async launchDevServerTerminal(options) {
187
- const devServerCommand = await getDevServerLaunchCommand(
188
- options.worktreePath,
189
- options.port,
190
- options.capabilities
191
- );
123
+ const executable = options.executablePath ?? getExecutablePath();
124
+ const devServerIdentifier = String(options.identifier);
125
+ const devServerCommand = `${executable} dev-server ${devServerIdentifier}`;
192
126
  const backgroundColor = options.colorTerminal ?? true ? options.colorHex ? hexToRgb(options.colorHex) : generateColorFromBranchName(options.branchName).rgb : void 0;
193
127
  await openTerminalWindow({
194
128
  workspacePath: options.worktreePath,
195
129
  command: devServerCommand,
196
130
  ...backgroundColor && { backgroundColor },
197
- includeEnvSetup: (options.sourceEnvOnStart ?? false) && this.hasAnyEnvFiles(options.worktreePath),
131
+ // il dev-server handles env loading internally, so no includeEnvSetup
132
+ includeEnvSetup: false,
198
133
  includePortExport: options.capabilities.includes("web"),
199
134
  ...options.port !== void 0 && { port: options.port }
200
135
  });
@@ -247,14 +182,12 @@ var LoomLauncher = class {
247
182
  }
248
183
  /**
249
184
  * Build terminal options for dev server
185
+ * Uses `il dev-server [identifier]` which handles env loading internally
250
186
  */
251
- async buildDevServerTerminalOptions(options) {
252
- const devServerCommand = await getDevServerLaunchCommand(
253
- options.worktreePath,
254
- options.port,
255
- options.capabilities
256
- );
257
- const hasEnvFile = this.hasAnyEnvFiles(options.worktreePath);
187
+ buildDevServerTerminalOptions(options) {
188
+ const executable = options.executablePath ?? getExecutablePath();
189
+ const devServerIdentifier = String(options.identifier);
190
+ const devServerCommand = `${executable} dev-server ${devServerIdentifier}`;
258
191
  const devServerTitle = `Dev Server - ${this.formatIdentifier(options.workflowType, options.identifier)}`;
259
192
  const backgroundColor = options.colorTerminal ?? true ? options.colorHex ? hexToRgb(options.colorHex) : generateColorFromBranchName(options.branchName).rgb : void 0;
260
193
  return {
@@ -262,7 +195,8 @@ var LoomLauncher = class {
262
195
  command: devServerCommand,
263
196
  ...backgroundColor && { backgroundColor },
264
197
  title: devServerTitle,
265
- includeEnvSetup: (options.sourceEnvOnStart ?? false) && hasEnvFile,
198
+ // il dev-server handles env loading internally
199
+ includeEnvSetup: false,
266
200
  includePortExport: options.capabilities.includes("web"),
267
201
  ...options.port !== void 0 && { port: options.port }
268
202
  };
@@ -321,4 +255,4 @@ var LoomLauncher = class {
321
255
  export {
322
256
  LoomLauncher
323
257
  };
324
- //# sourceMappingURL=LoomLauncher-S3YGJRJQ.js.map
258
+ //# sourceMappingURL=LoomLauncher-JNWBMHES.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/LoomLauncher.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"],"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