@cleocode/adapters 2.0.0 → 2026.3.39

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 (234) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +503 -0
  3. package/dist/index.js +621 -496
  4. package/dist/index.js.map +4 -4
  5. package/package.json +12 -7
  6. package/src/__tests__/claude-code-adapter.test.d.ts +10 -0
  7. package/src/__tests__/claude-code-adapter.test.d.ts.map +1 -0
  8. package/src/__tests__/claude-code-adapter.test.js +192 -0
  9. package/src/__tests__/claude-code-adapter.test.js.map +1 -0
  10. package/src/__tests__/claude-code-adapter.test.ts +235 -0
  11. package/src/__tests__/cursor-adapter.test.d.ts +10 -0
  12. package/src/__tests__/cursor-adapter.test.d.ts.map +1 -0
  13. package/src/__tests__/cursor-adapter.test.js +196 -0
  14. package/src/__tests__/cursor-adapter.test.js.map +1 -0
  15. package/src/__tests__/cursor-adapter.test.ts +246 -0
  16. package/src/__tests__/opencode-adapter.test.d.ts +10 -0
  17. package/src/__tests__/opencode-adapter.test.d.ts.map +1 -0
  18. package/src/__tests__/opencode-adapter.test.js +204 -0
  19. package/src/__tests__/opencode-adapter.test.js.map +1 -0
  20. package/src/__tests__/opencode-adapter.test.ts +250 -0
  21. package/src/index.d.ts +28 -20
  22. package/src/index.d.ts.map +1 -1
  23. package/src/index.js +4 -19
  24. package/src/index.js.map +1 -1
  25. package/src/index.ts +25 -25
  26. package/src/providers/claude-code/__tests__/adapter.test.d.ts +1 -1
  27. package/src/providers/claude-code/__tests__/adapter.test.d.ts.map +0 -0
  28. package/src/providers/claude-code/__tests__/adapter.test.js +2 -2
  29. package/src/providers/claude-code/__tests__/adapter.test.js.map +1 -1
  30. package/src/providers/claude-code/__tests__/adapter.test.ts +2 -2
  31. package/src/providers/claude-code/adapter.d.ts +54 -50
  32. package/src/providers/claude-code/adapter.d.ts.map +0 -0
  33. package/src/providers/claude-code/adapter.js +1 -1
  34. package/src/providers/claude-code/adapter.js.map +1 -1
  35. package/src/providers/claude-code/adapter.ts +1 -1
  36. package/src/providers/claude-code/context-monitor.d.ts +6 -6
  37. package/src/providers/claude-code/context-monitor.d.ts.map +0 -0
  38. package/src/providers/claude-code/context-monitor.js +0 -0
  39. package/src/providers/claude-code/context-monitor.js.map +0 -0
  40. package/src/providers/claude-code/context-monitor.ts +0 -0
  41. package/src/providers/claude-code/hooks.d.ts +36 -36
  42. package/src/providers/claude-code/hooks.d.ts.map +0 -0
  43. package/src/providers/claude-code/hooks.js +0 -0
  44. package/src/providers/claude-code/hooks.js.map +0 -0
  45. package/src/providers/claude-code/hooks.ts +0 -0
  46. package/src/providers/claude-code/index.d.ts +6 -2
  47. package/src/providers/claude-code/index.d.ts.map +1 -1
  48. package/src/providers/claude-code/index.js +1 -1
  49. package/src/providers/claude-code/index.js.map +1 -1
  50. package/src/providers/claude-code/index.ts +2 -2
  51. package/src/providers/claude-code/install.d.ts +52 -52
  52. package/src/providers/claude-code/install.d.ts.map +1 -1
  53. package/src/providers/claude-code/install.js +1 -4
  54. package/src/providers/claude-code/install.js.map +1 -1
  55. package/src/providers/claude-code/install.ts +1 -4
  56. package/src/providers/claude-code/manifest.json +0 -0
  57. package/src/providers/claude-code/paths.d.ts +5 -5
  58. package/src/providers/claude-code/paths.d.ts.map +0 -0
  59. package/src/providers/claude-code/paths.js +0 -0
  60. package/src/providers/claude-code/paths.js.map +0 -0
  61. package/src/providers/claude-code/paths.ts +0 -0
  62. package/src/providers/claude-code/spawn.d.ts +37 -37
  63. package/src/providers/claude-code/spawn.d.ts.map +1 -1
  64. package/src/providers/claude-code/spawn.js +4 -0
  65. package/src/providers/claude-code/spawn.js.map +1 -1
  66. package/src/providers/claude-code/spawn.ts +5 -0
  67. package/src/providers/claude-code/statusline.d.ts +1 -2
  68. package/src/providers/claude-code/statusline.d.ts.map +0 -0
  69. package/src/providers/claude-code/statusline.js +2 -1
  70. package/src/providers/claude-code/statusline.js.map +1 -1
  71. package/src/providers/claude-code/statusline.ts +3 -3
  72. package/src/providers/claude-code/task-sync.d.ts +7 -7
  73. package/src/providers/claude-code/task-sync.d.ts.map +1 -1
  74. package/src/providers/claude-code/task-sync.js +1 -3
  75. package/src/providers/claude-code/task-sync.js.map +1 -1
  76. package/src/providers/claude-code/task-sync.ts +1 -3
  77. package/src/providers/claude-code/transport.d.ts +3 -3
  78. package/src/providers/claude-code/transport.d.ts.map +0 -0
  79. package/src/providers/claude-code/transport.js +0 -0
  80. package/src/providers/claude-code/transport.js.map +0 -0
  81. package/src/providers/claude-code/transport.ts +0 -0
  82. package/src/providers/cursor/__tests__/adapter.test.d.ts +1 -1
  83. package/src/providers/cursor/__tests__/adapter.test.d.ts.map +0 -0
  84. package/src/providers/cursor/__tests__/adapter.test.js +2 -2
  85. package/src/providers/cursor/__tests__/adapter.test.js.map +1 -1
  86. package/src/providers/cursor/__tests__/adapter.test.ts +2 -2
  87. package/src/providers/cursor/adapter.d.ts +44 -40
  88. package/src/providers/cursor/adapter.d.ts.map +0 -0
  89. package/src/providers/cursor/adapter.js +0 -0
  90. package/src/providers/cursor/adapter.js.map +0 -0
  91. package/src/providers/cursor/adapter.ts +0 -0
  92. package/src/providers/cursor/hooks.d.ts +29 -29
  93. package/src/providers/cursor/hooks.d.ts.map +0 -0
  94. package/src/providers/cursor/hooks.js +0 -0
  95. package/src/providers/cursor/hooks.js.map +0 -0
  96. package/src/providers/cursor/hooks.ts +0 -0
  97. package/src/providers/cursor/index.d.ts +1 -1
  98. package/src/providers/cursor/index.d.ts.map +0 -0
  99. package/src/providers/cursor/index.js +0 -0
  100. package/src/providers/cursor/index.js.map +0 -0
  101. package/src/providers/cursor/index.ts +0 -0
  102. package/src/providers/cursor/install.d.ts +67 -67
  103. package/src/providers/cursor/install.d.ts.map +1 -1
  104. package/src/providers/cursor/install.js +1 -4
  105. package/src/providers/cursor/install.js.map +1 -1
  106. package/src/providers/cursor/install.ts +1 -4
  107. package/src/providers/cursor/manifest.json +0 -0
  108. package/src/providers/cursor/spawn.d.ts +31 -31
  109. package/src/providers/cursor/spawn.d.ts.map +0 -0
  110. package/src/providers/cursor/spawn.js +0 -0
  111. package/src/providers/cursor/spawn.js.map +1 -1
  112. package/src/providers/cursor/spawn.ts +2 -2
  113. package/src/providers/opencode/__tests__/adapter.test.d.ts +1 -1
  114. package/src/providers/opencode/__tests__/adapter.test.d.ts.map +0 -0
  115. package/src/providers/opencode/__tests__/adapter.test.js +2 -2
  116. package/src/providers/opencode/__tests__/adapter.test.js.map +1 -1
  117. package/src/providers/opencode/__tests__/adapter.test.ts +2 -2
  118. package/src/providers/opencode/adapter.d.ts +50 -46
  119. package/src/providers/opencode/adapter.d.ts.map +0 -0
  120. package/src/providers/opencode/adapter.js +0 -0
  121. package/src/providers/opencode/adapter.js.map +0 -0
  122. package/src/providers/opencode/adapter.ts +0 -0
  123. package/src/providers/opencode/hooks.d.ts +36 -36
  124. package/src/providers/opencode/hooks.d.ts.map +0 -0
  125. package/src/providers/opencode/hooks.js +1 -1
  126. package/src/providers/opencode/hooks.js.map +1 -1
  127. package/src/providers/opencode/hooks.ts +1 -1
  128. package/src/providers/opencode/index.d.ts +2 -2
  129. package/src/providers/opencode/index.d.ts.map +1 -1
  130. package/src/providers/opencode/index.js +1 -1
  131. package/src/providers/opencode/index.js.map +1 -1
  132. package/src/providers/opencode/index.ts +1 -1
  133. package/src/providers/opencode/install.d.ts +46 -46
  134. package/src/providers/opencode/install.d.ts.map +1 -1
  135. package/src/providers/opencode/install.js +1 -4
  136. package/src/providers/opencode/install.js.map +1 -1
  137. package/src/providers/opencode/install.ts +1 -4
  138. package/src/providers/opencode/manifest.json +0 -0
  139. package/src/providers/opencode/spawn.d.ts +42 -39
  140. package/src/providers/opencode/spawn.d.ts.map +1 -1
  141. package/src/providers/opencode/spawn.js +0 -0
  142. package/src/providers/opencode/spawn.js.map +1 -1
  143. package/src/providers/opencode/spawn.ts +2 -7
  144. package/src/registry.d.ts +12 -12
  145. package/src/registry.d.ts.map +1 -1
  146. package/src/registry.js +0 -0
  147. package/src/registry.js.map +1 -1
  148. package/src/registry.ts +1 -3
  149. package/dist/index.d.ts +0 -27
  150. package/dist/index.d.ts.map +0 -1
  151. package/dist/providers/claude-code/adapter.d.ts +0 -75
  152. package/dist/providers/claude-code/adapter.d.ts.map +0 -1
  153. package/dist/providers/claude-code/adapter.js +0 -154
  154. package/dist/providers/claude-code/adapter.js.map +0 -1
  155. package/dist/providers/claude-code/context-monitor.d.ts +0 -24
  156. package/dist/providers/claude-code/context-monitor.d.ts.map +0 -1
  157. package/dist/providers/claude-code/context-monitor.js +0 -148
  158. package/dist/providers/claude-code/context-monitor.js.map +0 -1
  159. package/dist/providers/claude-code/hooks.d.ts +0 -59
  160. package/dist/providers/claude-code/hooks.d.ts.map +0 -1
  161. package/dist/providers/claude-code/hooks.js +0 -77
  162. package/dist/providers/claude-code/hooks.js.map +0 -1
  163. package/dist/providers/claude-code/index.d.ts +0 -24
  164. package/dist/providers/claude-code/index.d.ts.map +0 -1
  165. package/dist/providers/claude-code/index.js +0 -26
  166. package/dist/providers/claude-code/index.js.map +0 -1
  167. package/dist/providers/claude-code/install.d.ts +0 -75
  168. package/dist/providers/claude-code/install.d.ts.map +0 -1
  169. package/dist/providers/claude-code/install.js +0 -237
  170. package/dist/providers/claude-code/install.js.map +0 -1
  171. package/dist/providers/claude-code/paths.d.ts +0 -24
  172. package/dist/providers/claude-code/paths.d.ts.map +0 -1
  173. package/dist/providers/claude-code/paths.js +0 -33
  174. package/dist/providers/claude-code/paths.js.map +0 -1
  175. package/dist/providers/claude-code/spawn.d.ts +0 -60
  176. package/dist/providers/claude-code/spawn.d.ts.map +0 -1
  177. package/dist/providers/claude-code/spawn.js +0 -160
  178. package/dist/providers/claude-code/spawn.js.map +0 -1
  179. package/dist/providers/claude-code/statusline.d.ts +0 -24
  180. package/dist/providers/claude-code/statusline.d.ts.map +0 -1
  181. package/dist/providers/claude-code/statusline.js +0 -85
  182. package/dist/providers/claude-code/statusline.js.map +0 -1
  183. package/dist/providers/claude-code/task-sync.d.ts +0 -27
  184. package/dist/providers/claude-code/task-sync.d.ts.map +0 -1
  185. package/dist/providers/claude-code/task-sync.js +0 -124
  186. package/dist/providers/claude-code/task-sync.js.map +0 -1
  187. package/dist/providers/claude-code/transport.d.ts +0 -14
  188. package/dist/providers/claude-code/transport.d.ts.map +0 -1
  189. package/dist/providers/claude-code/transport.js +0 -18
  190. package/dist/providers/claude-code/transport.js.map +0 -1
  191. package/dist/providers/cursor/adapter.d.ts +0 -62
  192. package/dist/providers/cursor/adapter.d.ts.map +0 -1
  193. package/dist/providers/cursor/adapter.js +0 -124
  194. package/dist/providers/cursor/adapter.js.map +0 -1
  195. package/dist/providers/cursor/hooks.d.ts +0 -48
  196. package/dist/providers/cursor/hooks.d.ts.map +0 -1
  197. package/dist/providers/cursor/hooks.js +0 -55
  198. package/dist/providers/cursor/hooks.js.map +0 -1
  199. package/dist/providers/cursor/index.d.ts +0 -19
  200. package/dist/providers/cursor/index.d.ts.map +0 -1
  201. package/dist/providers/cursor/index.js +0 -21
  202. package/dist/providers/cursor/index.js.map +0 -1
  203. package/dist/providers/cursor/install.d.ts +0 -94
  204. package/dist/providers/cursor/install.d.ts.map +0 -1
  205. package/dist/providers/cursor/install.js +0 -241
  206. package/dist/providers/cursor/install.js.map +0 -1
  207. package/dist/providers/cursor/spawn.d.ts +0 -50
  208. package/dist/providers/cursor/spawn.d.ts.map +0 -1
  209. package/dist/providers/cursor/spawn.js +0 -59
  210. package/dist/providers/cursor/spawn.js.map +0 -1
  211. package/dist/providers/opencode/adapter.d.ts +0 -67
  212. package/dist/providers/opencode/adapter.d.ts.map +0 -1
  213. package/dist/providers/opencode/adapter.js +0 -144
  214. package/dist/providers/opencode/adapter.js.map +0 -1
  215. package/dist/providers/opencode/hooks.d.ts +0 -66
  216. package/dist/providers/opencode/hooks.d.ts.map +0 -1
  217. package/dist/providers/opencode/hooks.js +0 -89
  218. package/dist/providers/opencode/hooks.js.map +0 -1
  219. package/dist/providers/opencode/index.d.ts +0 -20
  220. package/dist/providers/opencode/index.d.ts.map +0 -1
  221. package/dist/providers/opencode/index.js +0 -22
  222. package/dist/providers/opencode/index.js.map +0 -1
  223. package/dist/providers/opencode/install.d.ts +0 -65
  224. package/dist/providers/opencode/install.d.ts.map +0 -1
  225. package/dist/providers/opencode/install.js +0 -183
  226. package/dist/providers/opencode/install.js.map +0 -1
  227. package/dist/providers/opencode/spawn.d.ts +0 -72
  228. package/dist/providers/opencode/spawn.d.ts.map +0 -1
  229. package/dist/providers/opencode/spawn.js +0 -219
  230. package/dist/providers/opencode/spawn.js.map +0 -1
  231. package/dist/registry.d.ts +0 -36
  232. package/dist/registry.d.ts.map +0 -1
  233. package/dist/registry.js +0 -55
  234. package/dist/registry.js.map +0 -1
package/dist/index.js CHANGED
@@ -231,10 +231,7 @@ var INSTRUCTION_REFERENCES, MCP_SERVER_KEY, ClaudeCodeInstallProvider;
231
231
  var init_install = __esm({
232
232
  "packages/adapters/src/providers/claude-code/install.js"() {
233
233
  "use strict";
234
- INSTRUCTION_REFERENCES = [
235
- "@~/.cleo/templates/CLEO-INJECTION.md",
236
- "@.cleo/memory-bridge.md"
237
- ];
234
+ INSTRUCTION_REFERENCES = ["@~/.cleo/templates/CLEO-INJECTION.md", "@.cleo/memory-bridge.md"];
238
235
  MCP_SERVER_KEY = "cleo";
239
236
  ClaudeCodeInstallProvider = class {
240
237
  installedProjectDir = null;
@@ -426,6 +423,152 @@ var init_install = __esm({
426
423
  }
427
424
  });
428
425
 
426
+ // packages/contracts/src/errors.ts
427
+ function getErrorMessage(error, fallback = "Unknown error") {
428
+ if (error instanceof Error) {
429
+ return error.message;
430
+ }
431
+ if (typeof error === "string") {
432
+ return error;
433
+ }
434
+ if (error !== null && typeof error === "object" && "message" in error && typeof error.message === "string") {
435
+ return error.message;
436
+ }
437
+ return fallback;
438
+ }
439
+ var init_errors = __esm({
440
+ "packages/contracts/src/errors.ts"() {
441
+ "use strict";
442
+ }
443
+ });
444
+
445
+ // packages/contracts/src/exit-codes.ts
446
+ var init_exit_codes = __esm({
447
+ "packages/contracts/src/exit-codes.ts"() {
448
+ "use strict";
449
+ }
450
+ });
451
+
452
+ // packages/contracts/src/lafs.ts
453
+ var init_lafs = __esm({
454
+ "packages/contracts/src/lafs.ts"() {
455
+ "use strict";
456
+ }
457
+ });
458
+
459
+ // packages/contracts/src/operations/issues.ts
460
+ var init_issues = __esm({
461
+ "packages/contracts/src/operations/issues.ts"() {
462
+ "use strict";
463
+ }
464
+ });
465
+
466
+ // packages/contracts/src/operations/lifecycle.ts
467
+ var init_lifecycle = __esm({
468
+ "packages/contracts/src/operations/lifecycle.ts"() {
469
+ "use strict";
470
+ }
471
+ });
472
+
473
+ // packages/contracts/src/operations/orchestrate.ts
474
+ var init_orchestrate = __esm({
475
+ "packages/contracts/src/operations/orchestrate.ts"() {
476
+ "use strict";
477
+ }
478
+ });
479
+
480
+ // packages/contracts/src/operations/release.ts
481
+ var init_release = __esm({
482
+ "packages/contracts/src/operations/release.ts"() {
483
+ "use strict";
484
+ }
485
+ });
486
+
487
+ // packages/contracts/src/operations/research.ts
488
+ var init_research = __esm({
489
+ "packages/contracts/src/operations/research.ts"() {
490
+ "use strict";
491
+ }
492
+ });
493
+
494
+ // packages/contracts/src/operations/session.ts
495
+ var init_session = __esm({
496
+ "packages/contracts/src/operations/session.ts"() {
497
+ "use strict";
498
+ }
499
+ });
500
+
501
+ // packages/contracts/src/operations/skills.ts
502
+ var init_skills = __esm({
503
+ "packages/contracts/src/operations/skills.ts"() {
504
+ "use strict";
505
+ }
506
+ });
507
+
508
+ // packages/contracts/src/operations/system.ts
509
+ var init_system = __esm({
510
+ "packages/contracts/src/operations/system.ts"() {
511
+ "use strict";
512
+ }
513
+ });
514
+
515
+ // packages/contracts/src/operations/tasks.ts
516
+ var init_tasks = __esm({
517
+ "packages/contracts/src/operations/tasks.ts"() {
518
+ "use strict";
519
+ }
520
+ });
521
+
522
+ // packages/contracts/src/operations/validate.ts
523
+ var init_validate = __esm({
524
+ "packages/contracts/src/operations/validate.ts"() {
525
+ "use strict";
526
+ }
527
+ });
528
+
529
+ // packages/contracts/src/operations/index.ts
530
+ var init_operations = __esm({
531
+ "packages/contracts/src/operations/index.ts"() {
532
+ "use strict";
533
+ init_issues();
534
+ init_lifecycle();
535
+ init_orchestrate();
536
+ init_release();
537
+ init_research();
538
+ init_session();
539
+ init_skills();
540
+ init_system();
541
+ init_tasks();
542
+ init_validate();
543
+ }
544
+ });
545
+
546
+ // packages/contracts/src/session.ts
547
+ var init_session2 = __esm({
548
+ "packages/contracts/src/session.ts"() {
549
+ "use strict";
550
+ }
551
+ });
552
+
553
+ // packages/contracts/src/status-registry.ts
554
+ var init_status_registry = __esm({
555
+ "packages/contracts/src/status-registry.ts"() {
556
+ "use strict";
557
+ }
558
+ });
559
+
560
+ // packages/contracts/src/index.ts
561
+ var init_src = __esm({
562
+ "packages/contracts/src/index.ts"() {
563
+ init_errors();
564
+ init_exit_codes();
565
+ init_lafs();
566
+ init_operations();
567
+ init_session2();
568
+ init_status_registry();
569
+ }
570
+ });
571
+
429
572
  // packages/adapters/src/providers/claude-code/spawn.js
430
573
  import { exec, spawn as nodeSpawn } from "node:child_process";
431
574
  import { unlink, writeFile } from "node:fs/promises";
@@ -434,6 +577,7 @@ var execAsync, ClaudeCodeSpawnProvider;
434
577
  var init_spawn = __esm({
435
578
  "packages/adapters/src/providers/claude-code/spawn.js"() {
436
579
  "use strict";
580
+ init_src();
437
581
  execAsync = promisify(exec);
438
582
  ClaudeCodeSpawnProvider = class {
439
583
  /** Map of instance IDs to tracked process info. */
@@ -500,6 +644,7 @@ var init_spawn = __esm({
500
644
  startTime
501
645
  };
502
646
  } catch (error) {
647
+ console.error(`[ClaudeCodeSpawnProvider] Failed to spawn: ${getErrorMessage(error)}`);
503
648
  if (tmpFile) {
504
649
  try {
505
650
  await unlink(tmpFile);
@@ -512,7 +657,8 @@ var init_spawn = __esm({
512
657
  providerId: "claude-code",
513
658
  status: "failed",
514
659
  startTime,
515
- endTime: (/* @__PURE__ */ new Date()).toISOString()
660
+ endTime: (/* @__PURE__ */ new Date()).toISOString(),
661
+ error: getErrorMessage(error)
516
662
  };
517
663
  }
518
664
  }
@@ -664,8 +810,8 @@ var init_transport = __esm({
664
810
  // packages/adapters/src/providers/claude-code/adapter.js
665
811
  import { exec as exec2 } from "node:child_process";
666
812
  import { existsSync as existsSync3 } from "node:fs";
667
- import { join as join5 } from "node:path";
668
813
  import { homedir as homedir4 } from "node:os";
814
+ import { join as join5 } from "node:path";
669
815
  import { promisify as promisify2 } from "node:util";
670
816
  var execAsync2, ClaudeCodeAdapter;
671
817
  var init_adapter = __esm({
@@ -892,45 +1038,36 @@ var init_claude_code = __esm({
892
1038
  init_install();
893
1039
  init_paths();
894
1040
  init_spawn();
895
- init_transport();
896
1041
  init_statusline();
1042
+ init_transport();
897
1043
  claude_code_default = ClaudeCodeAdapter;
898
1044
  }
899
1045
  });
900
1046
 
901
- // packages/adapters/src/providers/opencode/hooks.js
902
- var OPENCODE_EVENT_MAP, OpenCodeHookProvider;
1047
+ // packages/adapters/src/providers/cursor/hooks.js
1048
+ var CursorHookProvider;
903
1049
  var init_hooks2 = __esm({
904
- "packages/adapters/src/providers/opencode/hooks.js"() {
1050
+ "packages/adapters/src/providers/cursor/hooks.js"() {
905
1051
  "use strict";
906
- OPENCODE_EVENT_MAP = {
907
- "session.start": "onSessionStart",
908
- "session.end": "onSessionEnd",
909
- "tool.start": "onToolStart",
910
- "tool.complete": "onToolComplete",
911
- "error": "onError",
912
- "prompt.submit": "onPromptSubmit"
913
- };
914
- OpenCodeHookProvider = class {
1052
+ CursorHookProvider = class {
915
1053
  registered = false;
916
1054
  /**
917
- * Map an OpenCode native event name to a CAAMP hook event name.
1055
+ * Map a provider event name to a CAAMP hook event name.
918
1056
  *
919
- * @param providerEvent - OpenCode event name (e.g. "session.start", "tool.complete")
920
- * @returns CAAMP event name or null if unmapped
1057
+ * Always returns null since Cursor does not emit hook events.
1058
+ *
1059
+ * @param _providerEvent - Ignored; Cursor has no hook events
1060
+ * @returns null (no mapping available)
921
1061
  */
922
- mapProviderEvent(providerEvent) {
923
- return OPENCODE_EVENT_MAP[providerEvent] ?? null;
1062
+ mapProviderEvent(_providerEvent) {
1063
+ return null;
924
1064
  }
925
1065
  /**
926
1066
  * Register native hooks for a project.
927
1067
  *
928
- * For OpenCode, hooks are registered via the config system
929
- * (.opencode/config.json), which is handled by the install provider.
930
- * This method marks hooks as registered without performing
931
- * filesystem operations.
1068
+ * No-op for Cursor since it has no hook system.
932
1069
  *
933
- * @param _projectDir - Project directory (unused; config manages registration)
1070
+ * @param _projectDir - Ignored
934
1071
  */
935
1072
  async registerNativeHooks(_projectDir) {
936
1073
  this.registered = true;
@@ -938,45 +1075,34 @@ var init_hooks2 = __esm({
938
1075
  /**
939
1076
  * Unregister native hooks.
940
1077
  *
941
- * For OpenCode, this is a no-op since hooks are managed through
942
- * the config system. Unregistration happens via the install
943
- * provider's uninstall method.
1078
+ * No-op for Cursor since it has no hook system.
944
1079
  */
945
1080
  async unregisterNativeHooks() {
946
1081
  this.registered = false;
947
1082
  }
948
1083
  /**
949
- * Check whether hooks have been registered via registerNativeHooks.
1084
+ * Check whether hooks have been registered.
950
1085
  */
951
1086
  isRegistered() {
952
1087
  return this.registered;
953
1088
  }
954
- /**
955
- * Get the full event mapping for introspection/debugging.
956
- */
957
- getEventMap() {
958
- return { ...OPENCODE_EVENT_MAP };
959
- }
960
1089
  };
961
1090
  }
962
1091
  });
963
1092
 
964
- // packages/adapters/src/providers/opencode/install.js
1093
+ // packages/adapters/src/providers/cursor/install.js
965
1094
  import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
966
1095
  import { join as join7 } from "node:path";
967
- var INSTRUCTION_REFERENCES2, MCP_SERVER_KEY2, OpenCodeInstallProvider;
1096
+ var INSTRUCTION_REFERENCES2, MCP_SERVER_KEY2, CursorInstallProvider;
968
1097
  var init_install2 = __esm({
969
- "packages/adapters/src/providers/opencode/install.js"() {
1098
+ "packages/adapters/src/providers/cursor/install.js"() {
970
1099
  "use strict";
971
- INSTRUCTION_REFERENCES2 = [
972
- "@~/.cleo/templates/CLEO-INJECTION.md",
973
- "@.cleo/memory-bridge.md"
974
- ];
1100
+ INSTRUCTION_REFERENCES2 = ["@~/.cleo/templates/CLEO-INJECTION.md", "@.cleo/memory-bridge.md"];
975
1101
  MCP_SERVER_KEY2 = "cleo";
976
- OpenCodeInstallProvider = class {
1102
+ CursorInstallProvider = class {
977
1103
  installedProjectDir = null;
978
1104
  /**
979
- * Install CLEO into an OpenCode project.
1105
+ * Install CLEO into a Cursor project.
980
1106
  *
981
1107
  * @param options - Installation options including project directory and MCP server path
982
1108
  * @returns Result describing what was installed
@@ -990,12 +1116,12 @@ var init_install2 = __esm({
990
1116
  if (mcpServerPath) {
991
1117
  mcpRegistered = this.registerMcpServer(projectDir, mcpServerPath);
992
1118
  if (mcpRegistered) {
993
- details.mcpConfigPath = join7(projectDir, ".opencode", "config.json");
1119
+ details.mcpConfigPath = join7(projectDir, ".cursor", "mcp.json");
994
1120
  }
995
1121
  }
996
- instructionFileUpdated = this.updateInstructionFile(projectDir);
1122
+ instructionFileUpdated = this.updateInstructionFiles(projectDir);
997
1123
  if (instructionFileUpdated) {
998
- details.instructionFile = join7(projectDir, "AGENTS.md");
1124
+ details.instructionFiles = this.getUpdatedFileList(projectDir);
999
1125
  }
1000
1126
  this.installedProjectDir = projectDir;
1001
1127
  return {
@@ -1007,23 +1133,23 @@ var init_install2 = __esm({
1007
1133
  };
1008
1134
  }
1009
1135
  /**
1010
- * Uninstall CLEO from the current OpenCode project.
1136
+ * Uninstall CLEO from the current Cursor project.
1011
1137
  *
1012
- * Removes the MCP server registration from .opencode/config.json.
1013
- * Does not remove AGENTS.md references (they are harmless if CLEO is not present).
1138
+ * Removes the MCP server registration from .cursor/mcp.json.
1139
+ * Does not remove instruction file references (they are harmless if CLEO is not present).
1014
1140
  */
1015
1141
  async uninstall() {
1016
1142
  if (!this.installedProjectDir)
1017
1143
  return;
1018
- const configPath = join7(this.installedProjectDir, ".opencode", "config.json");
1019
- if (existsSync5(configPath)) {
1144
+ const mcpPath = join7(this.installedProjectDir, ".cursor", "mcp.json");
1145
+ if (existsSync5(mcpPath)) {
1020
1146
  try {
1021
- const raw = readFileSync4(configPath, "utf-8");
1147
+ const raw = readFileSync4(mcpPath, "utf-8");
1022
1148
  const config = JSON.parse(raw);
1023
1149
  const mcpServers = config.mcpServers;
1024
1150
  if (mcpServers && MCP_SERVER_KEY2 in mcpServers) {
1025
1151
  delete mcpServers[MCP_SERVER_KEY2];
1026
- writeFileSync3(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
1152
+ writeFileSync3(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
1027
1153
  }
1028
1154
  } catch {
1029
1155
  }
@@ -1033,14 +1159,13 @@ var init_install2 = __esm({
1033
1159
  /**
1034
1160
  * Check whether CLEO is installed in the current environment.
1035
1161
  *
1036
- * Checks for MCP server registered in .opencode/config.json.
1037
- * Returns true if the CLEO MCP server entry is found.
1162
+ * Checks for MCP server registered in .cursor/mcp.json.
1038
1163
  */
1039
1164
  async isInstalled() {
1040
- const configPath = join7(process.cwd(), ".opencode", "config.json");
1041
- if (existsSync5(configPath)) {
1165
+ const mcpPath = join7(process.cwd(), ".cursor", "mcp.json");
1166
+ if (existsSync5(mcpPath)) {
1042
1167
  try {
1043
- const config = JSON.parse(readFileSync4(configPath, "utf-8"));
1168
+ const config = JSON.parse(readFileSync4(mcpPath, "utf-8"));
1044
1169
  const mcpServers = config.mcpServers;
1045
1170
  if (mcpServers && MCP_SERVER_KEY2 in mcpServers) {
1046
1171
  return true;
@@ -1051,31 +1176,31 @@ var init_install2 = __esm({
1051
1176
  return false;
1052
1177
  }
1053
1178
  /**
1054
- * Ensure AGENTS.md contains @-references to CLEO instruction files.
1179
+ * Ensure instruction files contain @-references to CLEO.
1055
1180
  *
1056
- * Creates AGENTS.md if it does not exist. Appends any missing references.
1181
+ * Updates .cursorrules (legacy) and creates .cursor/rules/cleo.mdc (modern).
1057
1182
  *
1058
1183
  * @param projectDir - Project root directory
1059
1184
  */
1060
1185
  async ensureInstructionReferences(projectDir) {
1061
- this.updateInstructionFile(projectDir);
1186
+ this.updateInstructionFiles(projectDir);
1062
1187
  }
1063
1188
  /**
1064
- * Register the CLEO MCP server in .opencode/config.json.
1189
+ * Register the CLEO MCP server in .cursor/mcp.json.
1065
1190
  *
1066
- * OpenCode stores its MCP server configuration in .opencode/config.json
1191
+ * Cursor stores MCP server configuration in .cursor/mcp.json
1067
1192
  * under the mcpServers key.
1068
1193
  *
1069
1194
  * @returns true if registration was performed or updated
1070
1195
  */
1071
1196
  registerMcpServer(projectDir, mcpServerPath) {
1072
- const openCodeDir = join7(projectDir, ".opencode");
1073
- const configPath = join7(openCodeDir, "config.json");
1197
+ const cursorDir = join7(projectDir, ".cursor");
1198
+ const mcpPath = join7(cursorDir, "mcp.json");
1074
1199
  let config = {};
1075
- mkdirSync2(openCodeDir, { recursive: true });
1076
- if (existsSync5(configPath)) {
1200
+ mkdirSync2(cursorDir, { recursive: true });
1201
+ if (existsSync5(mcpPath)) {
1077
1202
  try {
1078
- config = JSON.parse(readFileSync4(configPath, "utf-8"));
1203
+ config = JSON.parse(readFileSync4(mcpPath, "utf-8"));
1079
1204
  } catch {
1080
1205
  }
1081
1206
  }
@@ -1087,250 +1212,114 @@ var init_install2 = __esm({
1087
1212
  command: "node",
1088
1213
  args: [mcpServerPath]
1089
1214
  };
1090
- writeFileSync3(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
1215
+ writeFileSync3(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
1091
1216
  return true;
1092
1217
  }
1093
1218
  /**
1094
- * Update AGENTS.md with CLEO @-references.
1219
+ * Update instruction files with CLEO @-references.
1095
1220
  *
1096
- * @returns true if the file was created or modified
1221
+ * Handles both legacy (.cursorrules) and modern (.cursor/rules/cleo.mdc) formats.
1222
+ *
1223
+ * @returns true if any file was created or modified
1097
1224
  */
1098
- updateInstructionFile(projectDir) {
1099
- const agentsMdPath = join7(projectDir, "AGENTS.md");
1100
- let content = "";
1101
- let existed = false;
1102
- if (existsSync5(agentsMdPath)) {
1103
- content = readFileSync4(agentsMdPath, "utf-8");
1104
- existed = true;
1225
+ updateInstructionFiles(projectDir) {
1226
+ let updated = false;
1227
+ if (this.updateLegacyRules(projectDir)) {
1228
+ updated = true;
1229
+ }
1230
+ if (this.updateModernRules(projectDir)) {
1231
+ updated = true;
1232
+ }
1233
+ return updated;
1234
+ }
1235
+ /**
1236
+ * Update legacy .cursorrules file with @-references.
1237
+ * Only modifies the file if it already exists (does not create it).
1238
+ *
1239
+ * @returns true if the file was modified
1240
+ */
1241
+ updateLegacyRules(projectDir) {
1242
+ const rulesPath = join7(projectDir, ".cursorrules");
1243
+ if (!existsSync5(rulesPath)) {
1244
+ return false;
1105
1245
  }
1246
+ let content = readFileSync4(rulesPath, "utf-8");
1106
1247
  const missingRefs = INSTRUCTION_REFERENCES2.filter((ref) => !content.includes(ref));
1107
1248
  if (missingRefs.length === 0) {
1108
1249
  return false;
1109
1250
  }
1110
- const refsBlock = missingRefs.join("\n");
1111
- if (existed) {
1112
- const separator = content.endsWith("\n") ? "" : "\n";
1113
- content = content + separator + refsBlock + "\n";
1114
- } else {
1115
- content = refsBlock + "\n";
1251
+ const separator = content.endsWith("\n") ? "" : "\n";
1252
+ content = content + separator + missingRefs.join("\n") + "\n";
1253
+ writeFileSync3(rulesPath, content, "utf-8");
1254
+ return true;
1255
+ }
1256
+ /**
1257
+ * Create or update .cursor/rules/cleo.mdc with CLEO references.
1258
+ *
1259
+ * MDC (Markdown Component) format is Cursor's modern rule file format.
1260
+ * Each .mdc file in .cursor/rules/ is loaded as a rule set.
1261
+ *
1262
+ * @returns true if the file was created or modified
1263
+ */
1264
+ updateModernRules(projectDir) {
1265
+ const rulesDir = join7(projectDir, ".cursor", "rules");
1266
+ const mdcPath = join7(rulesDir, "cleo.mdc");
1267
+ const expectedContent = [
1268
+ "---",
1269
+ "description: CLEO task management protocol references",
1270
+ 'globs: "**/*"',
1271
+ "alwaysApply: true",
1272
+ "---",
1273
+ "",
1274
+ ...INSTRUCTION_REFERENCES2,
1275
+ ""
1276
+ ].join("\n");
1277
+ if (existsSync5(mdcPath)) {
1278
+ const existing = readFileSync4(mdcPath, "utf-8");
1279
+ if (existing === expectedContent) {
1280
+ return false;
1281
+ }
1116
1282
  }
1117
- writeFileSync3(agentsMdPath, content, "utf-8");
1283
+ mkdirSync2(rulesDir, { recursive: true });
1284
+ writeFileSync3(mdcPath, expectedContent, "utf-8");
1118
1285
  return true;
1119
1286
  }
1287
+ /**
1288
+ * Get list of instruction files that were updated.
1289
+ */
1290
+ getUpdatedFileList(projectDir) {
1291
+ const files = [];
1292
+ if (existsSync5(join7(projectDir, ".cursorrules"))) {
1293
+ files.push(join7(projectDir, ".cursorrules"));
1294
+ }
1295
+ files.push(join7(projectDir, ".cursor", "rules", "cleo.mdc"));
1296
+ return files;
1297
+ }
1120
1298
  };
1121
1299
  }
1122
1300
  });
1123
1301
 
1124
- // packages/adapters/src/providers/opencode/spawn.js
1125
- import { exec as exec3, spawn as nodeSpawn2 } from "node:child_process";
1126
- import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
1302
+ // packages/adapters/src/providers/cursor/adapter.js
1303
+ import { existsSync as existsSync6 } from "node:fs";
1127
1304
  import { join as join8 } from "node:path";
1128
- import { promisify as promisify3 } from "node:util";
1129
- function buildOpenCodeAgentMarkdown(description, instructions) {
1130
- const normalizedDesc = description.replace(/\s+/g, " ").trim();
1131
- return [
1132
- "---",
1133
- `description: ${JSON.stringify(normalizedDesc)}`,
1134
- "mode: subagent",
1135
- "hidden: true",
1136
- "---",
1137
- "",
1138
- instructions.trim(),
1139
- ""
1140
- ].join("\n");
1141
- }
1142
- async function ensureSubagentDefinition(workingDirectory) {
1143
- const agentDir = join8(workingDirectory, ".opencode", "agent");
1144
- const agentPath = join8(agentDir, `${OPENCODE_SUBAGENT_NAME}.md`);
1145
- const description = "CLEO task executor with protocol compliance.";
1146
- const instructions = [
1147
- "# CLEO Subagent",
1148
- "",
1149
- "You are a CLEO subagent executing a delegated task.",
1150
- "Follow the CLEO protocol and complete the assigned work.",
1151
- "",
1152
- "@~/.cleo/templates/CLEO-INJECTION.md"
1153
- ].join("\n");
1154
- const content = buildOpenCodeAgentMarkdown(description, instructions);
1155
- await mkdir2(agentDir, { recursive: true });
1156
- let existing = null;
1157
- try {
1158
- existing = await readFile2(agentPath, "utf-8");
1159
- } catch {
1160
- existing = null;
1161
- }
1162
- if (existing !== content) {
1163
- await writeFile2(agentPath, content, "utf-8");
1164
- }
1165
- return OPENCODE_SUBAGENT_NAME;
1166
- }
1167
- var execAsync3, OPENCODE_SUBAGENT_NAME, OPENCODE_FALLBACK_AGENT, OpenCodeSpawnProvider;
1168
- var init_spawn2 = __esm({
1169
- "packages/adapters/src/providers/opencode/spawn.js"() {
1170
- "use strict";
1171
- execAsync3 = promisify3(exec3);
1172
- OPENCODE_SUBAGENT_NAME = "cleo-subagent";
1173
- OPENCODE_FALLBACK_AGENT = "general";
1174
- OpenCodeSpawnProvider = class {
1175
- /** Map of instance IDs to tracked process info. */
1176
- processMap = /* @__PURE__ */ new Map();
1177
- /**
1178
- * Check if the OpenCode CLI is available in PATH.
1179
- *
1180
- * @returns true if `opencode` is found via `which`
1181
- */
1182
- async canSpawn() {
1183
- try {
1184
- await execAsync3("which opencode");
1185
- return true;
1186
- } catch {
1187
- return false;
1188
- }
1189
- }
1190
- /**
1191
- * Spawn a subagent via OpenCode CLI.
1192
- *
1193
- * Ensures the CLEO subagent definition exists in the project's
1194
- * .opencode/agent/ directory, then spawns a detached OpenCode
1195
- * process. The process runs independently of the parent.
1196
- *
1197
- * @param context - Spawn context with taskId, prompt, and options
1198
- * @returns Spawn result with instance ID and status
1199
- */
1200
- async spawn(context) {
1201
- const instanceId = `opencode-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
1202
- const startTime = (/* @__PURE__ */ new Date()).toISOString();
1203
- const workingDirectory = context.workingDirectory ?? process.cwd();
1204
- try {
1205
- let agentName;
1206
- try {
1207
- agentName = await ensureSubagentDefinition(workingDirectory);
1208
- } catch {
1209
- agentName = OPENCODE_FALLBACK_AGENT;
1210
- }
1211
- const child = nodeSpawn2("opencode", [
1212
- "run",
1213
- "--format",
1214
- "json",
1215
- "--agent",
1216
- agentName,
1217
- "--title",
1218
- `CLEO ${context.taskId}`,
1219
- context.prompt
1220
- ], {
1221
- cwd: workingDirectory,
1222
- detached: true,
1223
- stdio: "ignore"
1224
- });
1225
- child.unref();
1226
- if (child.pid) {
1227
- this.processMap.set(instanceId, {
1228
- pid: child.pid,
1229
- taskId: context.taskId,
1230
- startTime
1231
- });
1232
- }
1233
- child.on("exit", () => {
1234
- this.processMap.delete(instanceId);
1235
- });
1236
- return {
1237
- instanceId,
1238
- taskId: context.taskId,
1239
- providerId: "opencode",
1240
- status: "running",
1241
- startTime
1242
- };
1243
- } catch {
1244
- return {
1245
- instanceId,
1246
- taskId: context.taskId,
1247
- providerId: "opencode",
1248
- status: "failed",
1249
- startTime,
1250
- endTime: (/* @__PURE__ */ new Date()).toISOString()
1251
- };
1252
- }
1253
- }
1254
- /**
1255
- * List currently running OpenCode subagent processes.
1256
- *
1257
- * Checks each tracked process via kill(pid, 0) to verify it is still alive.
1258
- * Dead processes are automatically cleaned from the tracking map.
1259
- *
1260
- * @returns Array of spawn results for running processes
1261
- */
1262
- async listRunning() {
1263
- const running = [];
1264
- for (const [instanceId, tracked] of this.processMap.entries()) {
1265
- try {
1266
- process.kill(tracked.pid, 0);
1267
- running.push({
1268
- instanceId,
1269
- taskId: tracked.taskId,
1270
- providerId: "opencode",
1271
- status: "running",
1272
- startTime: tracked.startTime
1273
- });
1274
- } catch {
1275
- this.processMap.delete(instanceId);
1276
- }
1277
- }
1278
- return running;
1279
- }
1280
- /**
1281
- * Terminate a running spawn by instance ID.
1282
- *
1283
- * Sends SIGTERM to the tracked process. If the process is not found
1284
- * or has already exited, this is a no-op.
1285
- *
1286
- * @param instanceId - ID of the spawn instance to terminate
1287
- */
1288
- async terminate(instanceId) {
1289
- const tracked = this.processMap.get(instanceId);
1290
- if (!tracked)
1291
- return;
1292
- try {
1293
- process.kill(tracked.pid, "SIGTERM");
1294
- } catch {
1295
- }
1296
- this.processMap.delete(instanceId);
1297
- }
1298
- };
1299
- }
1300
- });
1301
-
1302
- // packages/adapters/src/providers/opencode/adapter.js
1303
- import { exec as exec4 } from "node:child_process";
1304
- import { existsSync as existsSync6 } from "node:fs";
1305
- import { join as join9 } from "node:path";
1306
- import { promisify as promisify4 } from "node:util";
1307
- var execAsync4, OpenCodeAdapter;
1305
+ var CursorAdapter;
1308
1306
  var init_adapter2 = __esm({
1309
- "packages/adapters/src/providers/opencode/adapter.js"() {
1307
+ "packages/adapters/src/providers/cursor/adapter.js"() {
1310
1308
  "use strict";
1311
1309
  init_hooks2();
1312
1310
  init_install2();
1313
- init_spawn2();
1314
- execAsync4 = promisify4(exec4);
1315
- OpenCodeAdapter = class {
1316
- id = "opencode";
1317
- name = "OpenCode";
1311
+ CursorAdapter = class {
1312
+ id = "cursor";
1313
+ name = "Cursor";
1318
1314
  version = "1.0.0";
1319
1315
  capabilities = {
1320
- supportsHooks: true,
1321
- supportedHookEvents: [
1322
- "onSessionStart",
1323
- "onSessionEnd",
1324
- "onToolStart",
1325
- "onToolComplete",
1326
- "onError",
1327
- "onPromptSubmit"
1328
- ],
1329
- supportsSpawn: true,
1316
+ supportsHooks: false,
1317
+ supportedHookEvents: [],
1318
+ supportsSpawn: false,
1330
1319
  supportsInstall: true,
1331
1320
  supportsMcp: true,
1332
1321
  supportsInstructionFiles: true,
1333
- instructionFilePattern: "AGENTS.md",
1322
+ instructionFilePattern: ".cursor/rules/*.mdc",
1334
1323
  supportsContextMonitor: false,
1335
1324
  supportsStatusline: false,
1336
1325
  supportsProviderPaths: true,
@@ -1338,21 +1327,16 @@ var init_adapter2 = __esm({
1338
1327
  supportsTaskSync: false
1339
1328
  };
1340
1329
  hooks;
1341
- spawn;
1342
1330
  install;
1343
1331
  projectDir = null;
1344
1332
  initialized = false;
1345
1333
  constructor() {
1346
- this.hooks = new OpenCodeHookProvider();
1347
- this.spawn = new OpenCodeSpawnProvider();
1348
- this.install = new OpenCodeInstallProvider();
1334
+ this.hooks = new CursorHookProvider();
1335
+ this.install = new CursorInstallProvider();
1349
1336
  }
1350
1337
  /**
1351
1338
  * Initialize the adapter for a given project directory.
1352
1339
  *
1353
- * Validates the environment by checking for the OpenCode CLI
1354
- * and OpenCode configuration directory.
1355
- *
1356
1340
  * @param projectDir - Root directory of the project
1357
1341
  */
1358
1342
  async initialize(projectDir) {
@@ -1361,8 +1345,6 @@ var init_adapter2 = __esm({
1361
1345
  }
1362
1346
  /**
1363
1347
  * Dispose the adapter and clean up resources.
1364
- *
1365
- * Unregisters hooks and releases any tracked state.
1366
1348
  */
1367
1349
  async dispose() {
1368
1350
  if (this.hooks.isRegistered()) {
@@ -1372,12 +1354,12 @@ var init_adapter2 = __esm({
1372
1354
  this.projectDir = null;
1373
1355
  }
1374
1356
  /**
1375
- * Run a health check to verify OpenCode is accessible.
1357
+ * Run a health check to verify Cursor is accessible.
1376
1358
  *
1377
1359
  * Checks:
1378
1360
  * 1. Adapter has been initialized
1379
- * 2. OpenCode CLI is available in PATH
1380
- * 3. .opencode/ configuration directory exists in the project
1361
+ * 2. .cursor/ configuration directory exists in the project
1362
+ * 3. CURSOR_EDITOR env var is set
1381
1363
  *
1382
1364
  * @returns Health status with details about each check
1383
1365
  */
@@ -1390,23 +1372,20 @@ var init_adapter2 = __esm({
1390
1372
  details: { error: "Adapter not initialized" }
1391
1373
  };
1392
1374
  }
1393
- let cliAvailable = false;
1394
- try {
1395
- const { stdout } = await execAsync4("which opencode");
1396
- cliAvailable = stdout.trim().length > 0;
1397
- details.cliPath = stdout.trim();
1398
- } catch {
1399
- details.cliAvailable = false;
1400
- }
1375
+ let configExists = false;
1401
1376
  if (this.projectDir) {
1402
- const openCodeConfigDir = join9(this.projectDir, ".opencode");
1403
- const configExists = existsSync6(openCodeConfigDir);
1377
+ const cursorConfigDir = join8(this.projectDir, ".cursor");
1378
+ configExists = existsSync6(cursorConfigDir);
1404
1379
  details.configDirExists = configExists;
1405
1380
  }
1406
- const versionEnvSet = process.env.OPENCODE_VERSION !== void 0;
1407
- details.versionEnvSet = versionEnvSet;
1408
- const healthy = cliAvailable;
1409
- details.cliAvailable = cliAvailable;
1381
+ const editorEnvSet = process.env.CURSOR_EDITOR !== void 0;
1382
+ details.editorEnvSet = editorEnvSet;
1383
+ if (this.projectDir) {
1384
+ const legacyRulesExist = existsSync6(join8(this.projectDir, ".cursorrules"));
1385
+ details.legacyRulesExist = legacyRulesExist;
1386
+ }
1387
+ const healthy = configExists || editorEnvSet;
1388
+ details.detected = healthy;
1410
1389
  return {
1411
1390
  healthy,
1412
1391
  provider: this.id,
@@ -1429,56 +1408,63 @@ var init_adapter2 = __esm({
1429
1408
  }
1430
1409
  });
1431
1410
 
1432
- // packages/adapters/src/providers/opencode/index.js
1433
- var opencode_exports = {};
1434
- __export(opencode_exports, {
1435
- OpenCodeAdapter: () => OpenCodeAdapter,
1436
- OpenCodeHookProvider: () => OpenCodeHookProvider,
1437
- OpenCodeInstallProvider: () => OpenCodeInstallProvider,
1438
- OpenCodeSpawnProvider: () => OpenCodeSpawnProvider,
1411
+ // packages/adapters/src/providers/cursor/index.js
1412
+ var cursor_exports = {};
1413
+ __export(cursor_exports, {
1414
+ CursorAdapter: () => CursorAdapter,
1415
+ CursorHookProvider: () => CursorHookProvider,
1416
+ CursorInstallProvider: () => CursorInstallProvider,
1439
1417
  createAdapter: () => createAdapter2,
1440
- default: () => opencode_default
1418
+ default: () => cursor_default
1441
1419
  });
1442
1420
  function createAdapter2() {
1443
- return new OpenCodeAdapter();
1421
+ return new CursorAdapter();
1444
1422
  }
1445
- var opencode_default;
1446
- var init_opencode = __esm({
1447
- "packages/adapters/src/providers/opencode/index.js"() {
1423
+ var cursor_default;
1424
+ var init_cursor = __esm({
1425
+ "packages/adapters/src/providers/cursor/index.js"() {
1448
1426
  "use strict";
1449
1427
  init_adapter2();
1450
1428
  init_adapter2();
1451
1429
  init_hooks2();
1452
- init_spawn2();
1453
1430
  init_install2();
1454
- opencode_default = OpenCodeAdapter;
1431
+ cursor_default = CursorAdapter;
1455
1432
  }
1456
1433
  });
1457
1434
 
1458
- // packages/adapters/src/providers/cursor/hooks.js
1459
- var CursorHookProvider;
1435
+ // packages/adapters/src/providers/opencode/hooks.js
1436
+ var OPENCODE_EVENT_MAP, OpenCodeHookProvider;
1460
1437
  var init_hooks3 = __esm({
1461
- "packages/adapters/src/providers/cursor/hooks.js"() {
1438
+ "packages/adapters/src/providers/opencode/hooks.js"() {
1462
1439
  "use strict";
1463
- CursorHookProvider = class {
1440
+ OPENCODE_EVENT_MAP = {
1441
+ "session.start": "onSessionStart",
1442
+ "session.end": "onSessionEnd",
1443
+ "tool.start": "onToolStart",
1444
+ "tool.complete": "onToolComplete",
1445
+ error: "onError",
1446
+ "prompt.submit": "onPromptSubmit"
1447
+ };
1448
+ OpenCodeHookProvider = class {
1464
1449
  registered = false;
1465
1450
  /**
1466
- * Map a provider event name to a CAAMP hook event name.
1467
- *
1468
- * Always returns null since Cursor does not emit hook events.
1451
+ * Map an OpenCode native event name to a CAAMP hook event name.
1469
1452
  *
1470
- * @param _providerEvent - Ignored; Cursor has no hook events
1471
- * @returns null (no mapping available)
1453
+ * @param providerEvent - OpenCode event name (e.g. "session.start", "tool.complete")
1454
+ * @returns CAAMP event name or null if unmapped
1472
1455
  */
1473
- mapProviderEvent(_providerEvent) {
1474
- return null;
1456
+ mapProviderEvent(providerEvent) {
1457
+ return OPENCODE_EVENT_MAP[providerEvent] ?? null;
1475
1458
  }
1476
1459
  /**
1477
1460
  * Register native hooks for a project.
1478
1461
  *
1479
- * No-op for Cursor since it has no hook system.
1462
+ * For OpenCode, hooks are registered via the config system
1463
+ * (.opencode/config.json), which is handled by the install provider.
1464
+ * This method marks hooks as registered without performing
1465
+ * filesystem operations.
1480
1466
  *
1481
- * @param _projectDir - Ignored
1467
+ * @param _projectDir - Project directory (unused; config manages registration)
1482
1468
  */
1483
1469
  async registerNativeHooks(_projectDir) {
1484
1470
  this.registered = true;
@@ -1486,37 +1472,42 @@ var init_hooks3 = __esm({
1486
1472
  /**
1487
1473
  * Unregister native hooks.
1488
1474
  *
1489
- * No-op for Cursor since it has no hook system.
1475
+ * For OpenCode, this is a no-op since hooks are managed through
1476
+ * the config system. Unregistration happens via the install
1477
+ * provider's uninstall method.
1490
1478
  */
1491
1479
  async unregisterNativeHooks() {
1492
1480
  this.registered = false;
1493
1481
  }
1494
1482
  /**
1495
- * Check whether hooks have been registered.
1483
+ * Check whether hooks have been registered via registerNativeHooks.
1496
1484
  */
1497
1485
  isRegistered() {
1498
1486
  return this.registered;
1499
1487
  }
1488
+ /**
1489
+ * Get the full event mapping for introspection/debugging.
1490
+ */
1491
+ getEventMap() {
1492
+ return { ...OPENCODE_EVENT_MAP };
1493
+ }
1500
1494
  };
1501
1495
  }
1502
1496
  });
1503
1497
 
1504
- // packages/adapters/src/providers/cursor/install.js
1498
+ // packages/adapters/src/providers/opencode/install.js
1505
1499
  import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
1506
- import { join as join10 } from "node:path";
1507
- var INSTRUCTION_REFERENCES3, MCP_SERVER_KEY3, CursorInstallProvider;
1500
+ import { join as join9 } from "node:path";
1501
+ var INSTRUCTION_REFERENCES3, MCP_SERVER_KEY3, OpenCodeInstallProvider;
1508
1502
  var init_install3 = __esm({
1509
- "packages/adapters/src/providers/cursor/install.js"() {
1503
+ "packages/adapters/src/providers/opencode/install.js"() {
1510
1504
  "use strict";
1511
- INSTRUCTION_REFERENCES3 = [
1512
- "@~/.cleo/templates/CLEO-INJECTION.md",
1513
- "@.cleo/memory-bridge.md"
1514
- ];
1505
+ INSTRUCTION_REFERENCES3 = ["@~/.cleo/templates/CLEO-INJECTION.md", "@.cleo/memory-bridge.md"];
1515
1506
  MCP_SERVER_KEY3 = "cleo";
1516
- CursorInstallProvider = class {
1507
+ OpenCodeInstallProvider = class {
1517
1508
  installedProjectDir = null;
1518
1509
  /**
1519
- * Install CLEO into a Cursor project.
1510
+ * Install CLEO into an OpenCode project.
1520
1511
  *
1521
1512
  * @param options - Installation options including project directory and MCP server path
1522
1513
  * @returns Result describing what was installed
@@ -1530,12 +1521,12 @@ var init_install3 = __esm({
1530
1521
  if (mcpServerPath) {
1531
1522
  mcpRegistered = this.registerMcpServer(projectDir, mcpServerPath);
1532
1523
  if (mcpRegistered) {
1533
- details.mcpConfigPath = join10(projectDir, ".cursor", "mcp.json");
1524
+ details.mcpConfigPath = join9(projectDir, ".opencode", "config.json");
1534
1525
  }
1535
1526
  }
1536
- instructionFileUpdated = this.updateInstructionFiles(projectDir);
1527
+ instructionFileUpdated = this.updateInstructionFile(projectDir);
1537
1528
  if (instructionFileUpdated) {
1538
- details.instructionFiles = this.getUpdatedFileList(projectDir);
1529
+ details.instructionFile = join9(projectDir, "AGENTS.md");
1539
1530
  }
1540
1531
  this.installedProjectDir = projectDir;
1541
1532
  return {
@@ -1547,23 +1538,23 @@ var init_install3 = __esm({
1547
1538
  };
1548
1539
  }
1549
1540
  /**
1550
- * Uninstall CLEO from the current Cursor project.
1541
+ * Uninstall CLEO from the current OpenCode project.
1551
1542
  *
1552
- * Removes the MCP server registration from .cursor/mcp.json.
1553
- * Does not remove instruction file references (they are harmless if CLEO is not present).
1543
+ * Removes the MCP server registration from .opencode/config.json.
1544
+ * Does not remove AGENTS.md references (they are harmless if CLEO is not present).
1554
1545
  */
1555
1546
  async uninstall() {
1556
1547
  if (!this.installedProjectDir)
1557
1548
  return;
1558
- const mcpPath = join10(this.installedProjectDir, ".cursor", "mcp.json");
1559
- if (existsSync7(mcpPath)) {
1549
+ const configPath = join9(this.installedProjectDir, ".opencode", "config.json");
1550
+ if (existsSync7(configPath)) {
1560
1551
  try {
1561
- const raw = readFileSync5(mcpPath, "utf-8");
1552
+ const raw = readFileSync5(configPath, "utf-8");
1562
1553
  const config = JSON.parse(raw);
1563
1554
  const mcpServers = config.mcpServers;
1564
1555
  if (mcpServers && MCP_SERVER_KEY3 in mcpServers) {
1565
1556
  delete mcpServers[MCP_SERVER_KEY3];
1566
- writeFileSync4(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
1557
+ writeFileSync4(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
1567
1558
  }
1568
1559
  } catch {
1569
1560
  }
@@ -1573,13 +1564,14 @@ var init_install3 = __esm({
1573
1564
  /**
1574
1565
  * Check whether CLEO is installed in the current environment.
1575
1566
  *
1576
- * Checks for MCP server registered in .cursor/mcp.json.
1567
+ * Checks for MCP server registered in .opencode/config.json.
1568
+ * Returns true if the CLEO MCP server entry is found.
1577
1569
  */
1578
1570
  async isInstalled() {
1579
- const mcpPath = join10(process.cwd(), ".cursor", "mcp.json");
1580
- if (existsSync7(mcpPath)) {
1571
+ const configPath = join9(process.cwd(), ".opencode", "config.json");
1572
+ if (existsSync7(configPath)) {
1581
1573
  try {
1582
- const config = JSON.parse(readFileSync5(mcpPath, "utf-8"));
1574
+ const config = JSON.parse(readFileSync5(configPath, "utf-8"));
1583
1575
  const mcpServers = config.mcpServers;
1584
1576
  if (mcpServers && MCP_SERVER_KEY3 in mcpServers) {
1585
1577
  return true;
@@ -1590,31 +1582,31 @@ var init_install3 = __esm({
1590
1582
  return false;
1591
1583
  }
1592
1584
  /**
1593
- * Ensure instruction files contain @-references to CLEO.
1585
+ * Ensure AGENTS.md contains @-references to CLEO instruction files.
1594
1586
  *
1595
- * Updates .cursorrules (legacy) and creates .cursor/rules/cleo.mdc (modern).
1587
+ * Creates AGENTS.md if it does not exist. Appends any missing references.
1596
1588
  *
1597
1589
  * @param projectDir - Project root directory
1598
1590
  */
1599
1591
  async ensureInstructionReferences(projectDir) {
1600
- this.updateInstructionFiles(projectDir);
1592
+ this.updateInstructionFile(projectDir);
1601
1593
  }
1602
1594
  /**
1603
- * Register the CLEO MCP server in .cursor/mcp.json.
1595
+ * Register the CLEO MCP server in .opencode/config.json.
1604
1596
  *
1605
- * Cursor stores MCP server configuration in .cursor/mcp.json
1597
+ * OpenCode stores its MCP server configuration in .opencode/config.json
1606
1598
  * under the mcpServers key.
1607
1599
  *
1608
1600
  * @returns true if registration was performed or updated
1609
1601
  */
1610
1602
  registerMcpServer(projectDir, mcpServerPath) {
1611
- const cursorDir = join10(projectDir, ".cursor");
1612
- const mcpPath = join10(cursorDir, "mcp.json");
1603
+ const openCodeDir = join9(projectDir, ".opencode");
1604
+ const configPath = join9(openCodeDir, "config.json");
1613
1605
  let config = {};
1614
- mkdirSync3(cursorDir, { recursive: true });
1615
- if (existsSync7(mcpPath)) {
1606
+ mkdirSync3(openCodeDir, { recursive: true });
1607
+ if (existsSync7(configPath)) {
1616
1608
  try {
1617
- config = JSON.parse(readFileSync5(mcpPath, "utf-8"));
1609
+ config = JSON.parse(readFileSync5(configPath, "utf-8"));
1618
1610
  } catch {
1619
1611
  }
1620
1612
  }
@@ -1626,114 +1618,250 @@ var init_install3 = __esm({
1626
1618
  command: "node",
1627
1619
  args: [mcpServerPath]
1628
1620
  };
1629
- writeFileSync4(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
1621
+ writeFileSync4(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
1630
1622
  return true;
1631
1623
  }
1632
1624
  /**
1633
- * Update instruction files with CLEO @-references.
1634
- *
1635
- * Handles both legacy (.cursorrules) and modern (.cursor/rules/cleo.mdc) formats.
1625
+ * Update AGENTS.md with CLEO @-references.
1636
1626
  *
1637
- * @returns true if any file was created or modified
1627
+ * @returns true if the file was created or modified
1638
1628
  */
1639
- updateInstructionFiles(projectDir) {
1640
- let updated = false;
1641
- if (this.updateLegacyRules(projectDir)) {
1642
- updated = true;
1629
+ updateInstructionFile(projectDir) {
1630
+ const agentsMdPath = join9(projectDir, "AGENTS.md");
1631
+ let content = "";
1632
+ let existed = false;
1633
+ if (existsSync7(agentsMdPath)) {
1634
+ content = readFileSync5(agentsMdPath, "utf-8");
1635
+ existed = true;
1643
1636
  }
1644
- if (this.updateModernRules(projectDir)) {
1645
- updated = true;
1637
+ const missingRefs = INSTRUCTION_REFERENCES3.filter((ref) => !content.includes(ref));
1638
+ if (missingRefs.length === 0) {
1639
+ return false;
1646
1640
  }
1647
- return updated;
1641
+ const refsBlock = missingRefs.join("\n");
1642
+ if (existed) {
1643
+ const separator = content.endsWith("\n") ? "" : "\n";
1644
+ content = content + separator + refsBlock + "\n";
1645
+ } else {
1646
+ content = refsBlock + "\n";
1647
+ }
1648
+ writeFileSync4(agentsMdPath, content, "utf-8");
1649
+ return true;
1648
1650
  }
1651
+ };
1652
+ }
1653
+ });
1654
+
1655
+ // packages/adapters/src/providers/opencode/spawn.js
1656
+ import { exec as exec3, spawn as nodeSpawn2 } from "node:child_process";
1657
+ import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
1658
+ import { join as join10 } from "node:path";
1659
+ import { promisify as promisify3 } from "node:util";
1660
+ function buildOpenCodeAgentMarkdown(description, instructions) {
1661
+ const normalizedDesc = description.replace(/\s+/g, " ").trim();
1662
+ return [
1663
+ "---",
1664
+ `description: ${JSON.stringify(normalizedDesc)}`,
1665
+ "mode: subagent",
1666
+ "hidden: true",
1667
+ "---",
1668
+ "",
1669
+ instructions.trim(),
1670
+ ""
1671
+ ].join("\n");
1672
+ }
1673
+ async function ensureSubagentDefinition(workingDirectory) {
1674
+ const agentDir = join10(workingDirectory, ".opencode", "agent");
1675
+ const agentPath = join10(agentDir, `${OPENCODE_SUBAGENT_NAME}.md`);
1676
+ const description = "CLEO task executor with protocol compliance.";
1677
+ const instructions = [
1678
+ "# CLEO Subagent",
1679
+ "",
1680
+ "You are a CLEO subagent executing a delegated task.",
1681
+ "Follow the CLEO protocol and complete the assigned work.",
1682
+ "",
1683
+ "@~/.cleo/templates/CLEO-INJECTION.md"
1684
+ ].join("\n");
1685
+ const content = buildOpenCodeAgentMarkdown(description, instructions);
1686
+ await mkdir2(agentDir, { recursive: true });
1687
+ let existing = null;
1688
+ try {
1689
+ existing = await readFile2(agentPath, "utf-8");
1690
+ } catch {
1691
+ existing = null;
1692
+ }
1693
+ if (existing !== content) {
1694
+ await writeFile2(agentPath, content, "utf-8");
1695
+ }
1696
+ return OPENCODE_SUBAGENT_NAME;
1697
+ }
1698
+ var execAsync3, OPENCODE_SUBAGENT_NAME, OPENCODE_FALLBACK_AGENT, OpenCodeSpawnProvider;
1699
+ var init_spawn2 = __esm({
1700
+ "packages/adapters/src/providers/opencode/spawn.js"() {
1701
+ "use strict";
1702
+ execAsync3 = promisify3(exec3);
1703
+ OPENCODE_SUBAGENT_NAME = "cleo-subagent";
1704
+ OPENCODE_FALLBACK_AGENT = "general";
1705
+ OpenCodeSpawnProvider = class {
1706
+ /** Map of instance IDs to tracked process info. */
1707
+ processMap = /* @__PURE__ */ new Map();
1649
1708
  /**
1650
- * Update legacy .cursorrules file with @-references.
1651
- * Only modifies the file if it already exists (does not create it).
1709
+ * Check if the OpenCode CLI is available in PATH.
1652
1710
  *
1653
- * @returns true if the file was modified
1711
+ * @returns true if `opencode` is found via `which`
1654
1712
  */
1655
- updateLegacyRules(projectDir) {
1656
- const rulesPath = join10(projectDir, ".cursorrules");
1657
- if (!existsSync7(rulesPath)) {
1713
+ async canSpawn() {
1714
+ try {
1715
+ await execAsync3("which opencode");
1716
+ return true;
1717
+ } catch {
1658
1718
  return false;
1659
1719
  }
1660
- let content = readFileSync5(rulesPath, "utf-8");
1661
- const missingRefs = INSTRUCTION_REFERENCES3.filter((ref) => !content.includes(ref));
1662
- if (missingRefs.length === 0) {
1663
- return false;
1720
+ }
1721
+ /**
1722
+ * Spawn a subagent via OpenCode CLI.
1723
+ *
1724
+ * Ensures the CLEO subagent definition exists in the project's
1725
+ * .opencode/agent/ directory, then spawns a detached OpenCode
1726
+ * process. The process runs independently of the parent.
1727
+ *
1728
+ * @param context - Spawn context with taskId, prompt, and options
1729
+ * @returns Spawn result with instance ID and status
1730
+ */
1731
+ async spawn(context) {
1732
+ const instanceId = `opencode-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
1733
+ const startTime = (/* @__PURE__ */ new Date()).toISOString();
1734
+ const workingDirectory = context.workingDirectory ?? process.cwd();
1735
+ try {
1736
+ let agentName;
1737
+ try {
1738
+ agentName = await ensureSubagentDefinition(workingDirectory);
1739
+ } catch {
1740
+ agentName = OPENCODE_FALLBACK_AGENT;
1741
+ }
1742
+ const child = nodeSpawn2("opencode", [
1743
+ "run",
1744
+ "--format",
1745
+ "json",
1746
+ "--agent",
1747
+ agentName,
1748
+ "--title",
1749
+ `CLEO ${context.taskId}`,
1750
+ context.prompt
1751
+ ], {
1752
+ cwd: workingDirectory,
1753
+ detached: true,
1754
+ stdio: "ignore"
1755
+ });
1756
+ child.unref();
1757
+ if (child.pid) {
1758
+ this.processMap.set(instanceId, {
1759
+ pid: child.pid,
1760
+ taskId: context.taskId,
1761
+ startTime
1762
+ });
1763
+ }
1764
+ child.on("exit", () => {
1765
+ this.processMap.delete(instanceId);
1766
+ });
1767
+ return {
1768
+ instanceId,
1769
+ taskId: context.taskId,
1770
+ providerId: "opencode",
1771
+ status: "running",
1772
+ startTime
1773
+ };
1774
+ } catch {
1775
+ return {
1776
+ instanceId,
1777
+ taskId: context.taskId,
1778
+ providerId: "opencode",
1779
+ status: "failed",
1780
+ startTime,
1781
+ endTime: (/* @__PURE__ */ new Date()).toISOString()
1782
+ };
1664
1783
  }
1665
- const separator = content.endsWith("\n") ? "" : "\n";
1666
- content = content + separator + missingRefs.join("\n") + "\n";
1667
- writeFileSync4(rulesPath, content, "utf-8");
1668
- return true;
1669
1784
  }
1670
1785
  /**
1671
- * Create or update .cursor/rules/cleo.mdc with CLEO references.
1786
+ * List currently running OpenCode subagent processes.
1672
1787
  *
1673
- * MDC (Markdown Component) format is Cursor's modern rule file format.
1674
- * Each .mdc file in .cursor/rules/ is loaded as a rule set.
1788
+ * Checks each tracked process via kill(pid, 0) to verify it is still alive.
1789
+ * Dead processes are automatically cleaned from the tracking map.
1675
1790
  *
1676
- * @returns true if the file was created or modified
1791
+ * @returns Array of spawn results for running processes
1677
1792
  */
1678
- updateModernRules(projectDir) {
1679
- const rulesDir = join10(projectDir, ".cursor", "rules");
1680
- const mdcPath = join10(rulesDir, "cleo.mdc");
1681
- const expectedContent = [
1682
- "---",
1683
- "description: CLEO task management protocol references",
1684
- 'globs: "**/*"',
1685
- "alwaysApply: true",
1686
- "---",
1687
- "",
1688
- ...INSTRUCTION_REFERENCES3,
1689
- ""
1690
- ].join("\n");
1691
- if (existsSync7(mdcPath)) {
1692
- const existing = readFileSync5(mdcPath, "utf-8");
1693
- if (existing === expectedContent) {
1694
- return false;
1793
+ async listRunning() {
1794
+ const running = [];
1795
+ for (const [instanceId, tracked] of this.processMap.entries()) {
1796
+ try {
1797
+ process.kill(tracked.pid, 0);
1798
+ running.push({
1799
+ instanceId,
1800
+ taskId: tracked.taskId,
1801
+ providerId: "opencode",
1802
+ status: "running",
1803
+ startTime: tracked.startTime
1804
+ });
1805
+ } catch {
1806
+ this.processMap.delete(instanceId);
1695
1807
  }
1696
1808
  }
1697
- mkdirSync3(rulesDir, { recursive: true });
1698
- writeFileSync4(mdcPath, expectedContent, "utf-8");
1699
- return true;
1809
+ return running;
1700
1810
  }
1701
1811
  /**
1702
- * Get list of instruction files that were updated.
1812
+ * Terminate a running spawn by instance ID.
1813
+ *
1814
+ * Sends SIGTERM to the tracked process. If the process is not found
1815
+ * or has already exited, this is a no-op.
1816
+ *
1817
+ * @param instanceId - ID of the spawn instance to terminate
1703
1818
  */
1704
- getUpdatedFileList(projectDir) {
1705
- const files = [];
1706
- if (existsSync7(join10(projectDir, ".cursorrules"))) {
1707
- files.push(join10(projectDir, ".cursorrules"));
1819
+ async terminate(instanceId) {
1820
+ const tracked = this.processMap.get(instanceId);
1821
+ if (!tracked)
1822
+ return;
1823
+ try {
1824
+ process.kill(tracked.pid, "SIGTERM");
1825
+ } catch {
1708
1826
  }
1709
- files.push(join10(projectDir, ".cursor", "rules", "cleo.mdc"));
1710
- return files;
1827
+ this.processMap.delete(instanceId);
1711
1828
  }
1712
1829
  };
1713
1830
  }
1714
1831
  });
1715
1832
 
1716
- // packages/adapters/src/providers/cursor/adapter.js
1833
+ // packages/adapters/src/providers/opencode/adapter.js
1834
+ import { exec as exec4 } from "node:child_process";
1717
1835
  import { existsSync as existsSync8 } from "node:fs";
1718
1836
  import { join as join11 } from "node:path";
1719
- var CursorAdapter;
1837
+ import { promisify as promisify4 } from "node:util";
1838
+ var execAsync4, OpenCodeAdapter;
1720
1839
  var init_adapter3 = __esm({
1721
- "packages/adapters/src/providers/cursor/adapter.js"() {
1840
+ "packages/adapters/src/providers/opencode/adapter.js"() {
1722
1841
  "use strict";
1723
1842
  init_hooks3();
1724
1843
  init_install3();
1725
- CursorAdapter = class {
1726
- id = "cursor";
1727
- name = "Cursor";
1844
+ init_spawn2();
1845
+ execAsync4 = promisify4(exec4);
1846
+ OpenCodeAdapter = class {
1847
+ id = "opencode";
1848
+ name = "OpenCode";
1728
1849
  version = "1.0.0";
1729
1850
  capabilities = {
1730
- supportsHooks: false,
1731
- supportedHookEvents: [],
1732
- supportsSpawn: false,
1851
+ supportsHooks: true,
1852
+ supportedHookEvents: [
1853
+ "onSessionStart",
1854
+ "onSessionEnd",
1855
+ "onToolStart",
1856
+ "onToolComplete",
1857
+ "onError",
1858
+ "onPromptSubmit"
1859
+ ],
1860
+ supportsSpawn: true,
1733
1861
  supportsInstall: true,
1734
1862
  supportsMcp: true,
1735
1863
  supportsInstructionFiles: true,
1736
- instructionFilePattern: ".cursor/rules/*.mdc",
1864
+ instructionFilePattern: "AGENTS.md",
1737
1865
  supportsContextMonitor: false,
1738
1866
  supportsStatusline: false,
1739
1867
  supportsProviderPaths: true,
@@ -1741,16 +1869,21 @@ var init_adapter3 = __esm({
1741
1869
  supportsTaskSync: false
1742
1870
  };
1743
1871
  hooks;
1872
+ spawn;
1744
1873
  install;
1745
1874
  projectDir = null;
1746
1875
  initialized = false;
1747
1876
  constructor() {
1748
- this.hooks = new CursorHookProvider();
1749
- this.install = new CursorInstallProvider();
1877
+ this.hooks = new OpenCodeHookProvider();
1878
+ this.spawn = new OpenCodeSpawnProvider();
1879
+ this.install = new OpenCodeInstallProvider();
1750
1880
  }
1751
1881
  /**
1752
1882
  * Initialize the adapter for a given project directory.
1753
1883
  *
1884
+ * Validates the environment by checking for the OpenCode CLI
1885
+ * and OpenCode configuration directory.
1886
+ *
1754
1887
  * @param projectDir - Root directory of the project
1755
1888
  */
1756
1889
  async initialize(projectDir) {
@@ -1759,6 +1892,8 @@ var init_adapter3 = __esm({
1759
1892
  }
1760
1893
  /**
1761
1894
  * Dispose the adapter and clean up resources.
1895
+ *
1896
+ * Unregisters hooks and releases any tracked state.
1762
1897
  */
1763
1898
  async dispose() {
1764
1899
  if (this.hooks.isRegistered()) {
@@ -1768,12 +1903,12 @@ var init_adapter3 = __esm({
1768
1903
  this.projectDir = null;
1769
1904
  }
1770
1905
  /**
1771
- * Run a health check to verify Cursor is accessible.
1906
+ * Run a health check to verify OpenCode is accessible.
1772
1907
  *
1773
1908
  * Checks:
1774
1909
  * 1. Adapter has been initialized
1775
- * 2. .cursor/ configuration directory exists in the project
1776
- * 3. CURSOR_EDITOR env var is set
1910
+ * 2. OpenCode CLI is available in PATH
1911
+ * 3. .opencode/ configuration directory exists in the project
1777
1912
  *
1778
1913
  * @returns Health status with details about each check
1779
1914
  */
@@ -1786,20 +1921,23 @@ var init_adapter3 = __esm({
1786
1921
  details: { error: "Adapter not initialized" }
1787
1922
  };
1788
1923
  }
1789
- let configExists = false;
1790
- if (this.projectDir) {
1791
- const cursorConfigDir = join11(this.projectDir, ".cursor");
1792
- configExists = existsSync8(cursorConfigDir);
1793
- details.configDirExists = configExists;
1924
+ let cliAvailable = false;
1925
+ try {
1926
+ const { stdout } = await execAsync4("which opencode");
1927
+ cliAvailable = stdout.trim().length > 0;
1928
+ details.cliPath = stdout.trim();
1929
+ } catch {
1930
+ details.cliAvailable = false;
1794
1931
  }
1795
- const editorEnvSet = process.env.CURSOR_EDITOR !== void 0;
1796
- details.editorEnvSet = editorEnvSet;
1797
1932
  if (this.projectDir) {
1798
- const legacyRulesExist = existsSync8(join11(this.projectDir, ".cursorrules"));
1799
- details.legacyRulesExist = legacyRulesExist;
1933
+ const openCodeConfigDir = join11(this.projectDir, ".opencode");
1934
+ const configExists = existsSync8(openCodeConfigDir);
1935
+ details.configDirExists = configExists;
1800
1936
  }
1801
- const healthy = configExists || editorEnvSet;
1802
- details.detected = healthy;
1937
+ const versionEnvSet = process.env.OPENCODE_VERSION !== void 0;
1938
+ details.versionEnvSet = versionEnvSet;
1939
+ const healthy = cliAvailable;
1940
+ details.cliAvailable = cliAvailable;
1803
1941
  return {
1804
1942
  healthy,
1805
1943
  provider: this.id,
@@ -1822,30 +1960,37 @@ var init_adapter3 = __esm({
1822
1960
  }
1823
1961
  });
1824
1962
 
1825
- // packages/adapters/src/providers/cursor/index.js
1826
- var cursor_exports = {};
1827
- __export(cursor_exports, {
1828
- CursorAdapter: () => CursorAdapter,
1829
- CursorHookProvider: () => CursorHookProvider,
1830
- CursorInstallProvider: () => CursorInstallProvider,
1963
+ // packages/adapters/src/providers/opencode/index.js
1964
+ var opencode_exports = {};
1965
+ __export(opencode_exports, {
1966
+ OpenCodeAdapter: () => OpenCodeAdapter,
1967
+ OpenCodeHookProvider: () => OpenCodeHookProvider,
1968
+ OpenCodeInstallProvider: () => OpenCodeInstallProvider,
1969
+ OpenCodeSpawnProvider: () => OpenCodeSpawnProvider,
1831
1970
  createAdapter: () => createAdapter3,
1832
- default: () => cursor_default
1971
+ default: () => opencode_default
1833
1972
  });
1834
1973
  function createAdapter3() {
1835
- return new CursorAdapter();
1974
+ return new OpenCodeAdapter();
1836
1975
  }
1837
- var cursor_default;
1838
- var init_cursor = __esm({
1839
- "packages/adapters/src/providers/cursor/index.js"() {
1976
+ var opencode_default;
1977
+ var init_opencode = __esm({
1978
+ "packages/adapters/src/providers/opencode/index.js"() {
1840
1979
  "use strict";
1841
1980
  init_adapter3();
1842
1981
  init_adapter3();
1843
1982
  init_hooks3();
1844
1983
  init_install3();
1845
- cursor_default = CursorAdapter;
1984
+ init_spawn2();
1985
+ opencode_default = OpenCodeAdapter;
1846
1986
  }
1847
1987
  });
1848
1988
 
1989
+ // packages/adapters/src/index.ts
1990
+ init_claude_code();
1991
+ init_cursor();
1992
+ init_opencode();
1993
+
1849
1994
  // packages/adapters/src/registry.js
1850
1995
  import { readFileSync as readFileSync6 } from "node:fs";
1851
1996
  import { dirname as dirname2, join as join12, resolve } from "node:path";
@@ -1880,26 +2025,6 @@ async function discoverProviders() {
1880
2025
  });
1881
2026
  return providers;
1882
2027
  }
1883
-
1884
- // packages/adapters/src/index.ts
1885
- init_claude_code();
1886
- init_claude_code();
1887
- init_claude_code();
1888
- init_claude_code();
1889
- init_claude_code();
1890
- init_claude_code();
1891
- init_claude_code();
1892
- init_claude_code();
1893
- init_opencode();
1894
- init_opencode();
1895
- init_opencode();
1896
- init_opencode();
1897
- init_cursor();
1898
- init_cursor();
1899
- init_cursor();
1900
- init_claude_code();
1901
- init_opencode();
1902
- init_cursor();
1903
2028
  export {
1904
2029
  ClaudeCodeAdapter,
1905
2030
  ClaudeCodeContextMonitorProvider,
@@ -1917,8 +2042,8 @@ export {
1917
2042
  OpenCodeSpawnProvider,
1918
2043
  checkStatuslineIntegration,
1919
2044
  createAdapter as createClaudeCodeAdapter,
1920
- createAdapter3 as createCursorAdapter,
1921
- createAdapter2 as createOpenCodeAdapter,
2045
+ createAdapter2 as createCursorAdapter,
2046
+ createAdapter3 as createOpenCodeAdapter,
1922
2047
  discoverProviders,
1923
2048
  getProviderManifests,
1924
2049
  getSetupInstructions,