@memorax/memorax-code 0.1.1 → 0.1.3

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 (246) hide show
  1. package/README.md +16 -12
  2. package/bin/memorax-code-npm-preinstall.mjs +7 -2
  3. package/bin/memorax-code-opencode.mjs +4 -0
  4. package/bin/memorax-code-plugin-postinstall.mjs +424 -108
  5. package/docs/configuration.md +153 -29
  6. package/docs/troubleshooting.md +93 -7
  7. package/lib/dsh-plugin-install.mjs +22 -0
  8. package/lib/memorax-code-adapter-common/src/hooks/capture-cwd-hook.mjs +21 -14
  9. package/lib/memorax-code-adapter-common/src/hooks/ensure-backend-runner.mjs +26 -7
  10. package/lib/memorax-code-adapter-common/src/hooks/memory-skill-reminder-hook.mjs +86 -95
  11. package/lib/memorax-code-adapter-common/src/hooks/memory-skill-reminder-policy.mjs +58 -0
  12. package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-auto-build.mjs +38 -0
  13. package/lib/memorax-code-adapter-common/src/repo-memory/repo-memory-job-supervisor.mjs +1 -1
  14. package/lib/memorax-code-adapter-common/src/windows-cli-invocation.mjs +13 -1
  15. package/lib/memorax-code-backend/dist/app/backend-server.js +210 -0
  16. package/lib/memorax-code-backend/dist/{server-observability.js → app/memory-observability.js} +4 -4
  17. package/lib/memorax-code-backend/dist/{backend-state.js → app/state.js} +1 -1
  18. package/lib/memorax-code-backend/dist/{claude-adapter-lifecycle.js → clients/claude/lifecycle.js} +2 -2
  19. package/lib/memorax-code-backend/dist/{claude-memory-hook-runtime.js → clients/claude/memory-hook-runtime.js} +16 -9
  20. package/lib/memorax-code-backend/dist/clients/codex/lifecycle.js +131 -0
  21. package/lib/memorax-code-backend/dist/{codex-memory-hook-runtime.js → clients/codex/memory-hook-runtime.js} +18 -11
  22. package/lib/memorax-code-backend/dist/{codex-plugin-hooks.js → clients/codex/plugin-hooks.js} +1 -1
  23. package/lib/memorax-code-backend/dist/{codex-plugin-install.js → clients/codex/plugin-install.js} +6 -6
  24. package/lib/memorax-code-backend/dist/clients/dsh/lifecycle.js +75 -0
  25. package/lib/memorax-code-backend/dist/clients/dsh/memory-hook-runtime.js +258 -0
  26. package/lib/memorax-code-backend/dist/clients/dsh/session-turn.js +249 -0
  27. package/lib/memorax-code-backend/dist/clients/opencode/lifecycle.js +54 -0
  28. package/lib/memorax-code-backend/dist/clients/opencode/memory-hook-runtime.js +277 -0
  29. package/lib/memorax-code-backend/dist/clients/opencode/message-turn.js +78 -0
  30. package/lib/memorax-code-backend/dist/codex-adapter-lifecycle.js +1 -131
  31. package/lib/memorax-code-backend/dist/{memorax-code-config.js → config/memorax-code.js} +32 -4
  32. package/lib/memorax-code-backend/dist/{server-cli.js → entrypoints/backend-cli.js} +157 -34
  33. package/lib/memorax-code-backend/dist/jsonl-append.js +1 -75
  34. package/lib/memorax-code-backend/dist/{active-client-selection.js → lifecycle/active-clients.js} +12 -1
  35. package/lib/memorax-code-backend/dist/{backend-service-cleanup.js → lifecycle/backend/cleanup.js} +1 -1
  36. package/lib/memorax-code-backend/dist/{backend-service-record.js → lifecycle/backend/record.js} +1 -1
  37. package/lib/memorax-code-backend/dist/{backend-service-result.js → lifecycle/backend/result.js} +2 -2
  38. package/lib/memorax-code-backend/dist/{service.js → lifecycle/backend/service.js} +16 -16
  39. package/lib/memorax-code-backend/dist/{backend-token-record.js → lifecycle/backend/token-record.js} +1 -1
  40. package/lib/memorax-code-backend/dist/{backend-service-token.js → lifecycle/backend/token.js} +2 -2
  41. package/lib/memorax-code-backend/dist/lifecycle/client-plugin-removal.js +109 -0
  42. package/lib/memorax-code-backend/dist/{client-selection.js → lifecycle/client-selection.js} +11 -5
  43. package/lib/memorax-code-backend/dist/{backend-lifecycle-lock.js → lifecycle/lock.js} +1 -1
  44. package/lib/memorax-code-backend/dist/{memorax-code-lifecycle.js → lifecycle/orchestrator.js} +325 -39
  45. package/lib/memorax-code-backend/dist/memorax-cli.js +3 -1
  46. package/lib/memorax-code-backend/dist/memorax-code.js +1 -1
  47. package/lib/memorax-code-backend/dist/{automatic-memory-retrieval.js → memory/automatic-retrieval.js} +3 -3
  48. package/lib/memorax-code-backend/dist/{automatic-memory-writeback.js → memory/automatic-writeback.js} +82 -21
  49. package/lib/memorax-code-backend/dist/{memory-cli.js → memory/cli.js} +45 -10
  50. package/lib/memorax-code-backend/dist/{memory-hook-command.js → memory/hook-command.js} +156 -9
  51. package/lib/memorax-code-backend/dist/memory/observability.js +1 -0
  52. package/lib/memorax-code-backend/dist/memory/payload-redaction.js +212 -0
  53. package/lib/memorax-code-backend/dist/{memory-reminder-trace-recorder.js → memory/reminder-trace-recorder.js} +20 -7
  54. package/lib/memorax-code-backend/dist/{repository-memory-context.js → memory/repository-session.js} +25 -4
  55. package/lib/memorax-code-backend/dist/{memory-service.js → memory/service.js} +30 -6
  56. package/lib/memorax-code-backend/dist/{memory-turn-coordinator.js → memory/turn-coordinator.js} +7 -3
  57. package/lib/memorax-code-backend/dist/{memory-writeback-buffer.js → memory/writeback-buffer.js} +31 -2
  58. package/lib/memorax-code-backend/dist/{memory-writeback-chunk.js → memory/writeback-chunk.js} +1 -1
  59. package/lib/memorax-code-backend/dist/{memory-writeback-reconciler.js → memory/writeback-reconciler.js} +6 -6
  60. package/lib/memorax-code-backend/dist/{memory-writeback-task-projection.js → memory/writeback-task-projection.js} +4 -4
  61. package/lib/memorax-code-backend/dist/{memorax-adapter.js → provider/memorax/adapter.js} +5 -5
  62. package/lib/memorax-code-backend/dist/{memorax-config.js → provider/memorax/config.js} +4 -4
  63. package/lib/memorax-code-backend/dist/{memorax-http.js → provider/memorax/http.js} +1 -1
  64. package/lib/memorax-code-backend/dist/{repo-memory-readiness.js → repository/readiness.js} +3 -3
  65. package/lib/memorax-code-backend/dist/{repository-memory-scope.js → repository/scope.js} +81 -33
  66. package/lib/memorax-code-backend/dist/server.js +3 -212
  67. package/lib/memorax-code-backend/dist/service-entrypoint.js +1 -1
  68. package/lib/memorax-code-backend/dist/{debug-log.js → shared/debug-log.js} +1 -1
  69. package/lib/memorax-code-backend/dist/shared/jsonl-append.js +75 -0
  70. package/lib/memorax-code-backend/dist/shared/windows-cli-invocation.js +148 -0
  71. package/lib/memorax-code-backend/dist/{trace-config.js → trace/config.js} +43 -5
  72. package/lib/memorax-code-backend/dist/{trace-context.js → trace/context.js} +53 -2
  73. package/lib/memorax-code-backend/dist/{trace-store.js → trace/store.js} +3 -3
  74. package/lib/memorax-code-backend/dist/{server-health.js → transport/http/health.js} +1 -1
  75. package/lib/memorax-code-backend/dist/{server-memory-hook.js → transport/http/memory-hook.js} +3 -3
  76. package/lib/memorax-code-backend/dist/{server-http.js → transport/http/request.js} +1 -1
  77. package/lib/memorax-code-backend/dist/{claude-local-transcript.js → viewer/history/claude-transcript.js} +3 -3
  78. package/lib/memorax-code-backend/dist/{memory-viewer-session-title.js → viewer/history/session-title.js} +1 -1
  79. package/lib/memorax-code-backend/dist/{server-memory-viewer.js → viewer/http/public-routes.js} +25 -14
  80. package/lib/memorax-code-backend/dist/viewer/model.js +1 -0
  81. package/lib/memorax-code-backend/dist/{memory-viewer-activity.js → viewer/projection/activity.js} +2 -2
  82. package/lib/memorax-code-backend/dist/{memory-viewer-history-projection.js → viewer/projection/history.js} +1 -1
  83. package/lib/memorax-code-backend/dist/{memory-viewer-observability.js → viewer/projection/observability.js} +1 -1
  84. package/lib/memorax-code-backend/dist/{memory-viewer-user-projection.js → viewer/projection/user.js} +1 -1
  85. package/lib/memorax-code-backend/dist/{memory-viewer-writeback-status.js → viewer/projection/writeback-status.js} +1 -1
  86. package/lib/memorax-code-backend/dist/{memory-viewer-store.js → viewer/store.js} +59 -32
  87. package/lib/memorax-code-backend/dist/viewer/ui/icon.js +1 -0
  88. package/lib/memorax-code-backend/dist/{memory-viewer-user-html.js → viewer/ui/user-html.js} +14 -12
  89. package/lib/memorax-code-backend/dist/windows-cli-invocation.js +1 -148
  90. package/lib/memorax-code-backend/package.json +3 -3
  91. package/lib/memorax-code-claude-adapter/.claude-plugin/plugin.json +1 -1
  92. package/lib/memorax-code-claude-adapter/hooks/runtime-shell.json +1 -1
  93. package/lib/memorax-code-claude-adapter/package.json +1 -1
  94. package/lib/memorax-code-claude-adapter/runtime-hooks/memory-turn.mjs +5 -0
  95. package/lib/memorax-code-claude-adapter/skills/memorax-code/SKILL.md +23 -15
  96. package/lib/memorax-code-claude-adapter/skills/memorax-code/defaults.json +8 -5
  97. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/memorax-add.md +5 -1
  98. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/memorax-search.md +40 -10
  99. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/personal-read.md +1 -1
  100. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/personal-write.md +33 -13
  101. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-build.md +62 -13
  102. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-read.md +11 -4
  103. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-templates.md +179 -59
  104. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/repo-update.md +18 -7
  105. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/collect_all.py +122 -39
  106. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/detect_updates.py +73 -10
  107. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/github_resource_facets.py +9 -1
  108. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +9 -1
  109. package/lib/memorax-code-claude-adapter/skills/memorax-code/scripts/validate_memory.py +23 -1
  110. package/lib/memorax-code-claude-adapter/src/plugin-install.mjs +2 -0
  111. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/.claude-plugin/plugin.json +1 -1
  112. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/runtime-shell.json +1 -1
  113. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/capture-cwd-hook.mjs +21 -14
  114. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/ensure-backend-runner.mjs +26 -7
  115. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/memory-skill-reminder-hook.mjs +86 -95
  116. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/memory-skill-reminder-policy.mjs +58 -0
  117. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-auto-build.mjs +38 -0
  118. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/repo-memory/repo-memory-job-supervisor.mjs +1 -1
  119. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/windows-cli-invocation.mjs +13 -1
  120. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/package.json +1 -1
  121. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/runtime-hooks/memory-turn.mjs +5 -0
  122. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/SKILL.md +23 -15
  123. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/defaults.json +8 -5
  124. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/memorax-add.md +5 -1
  125. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/memorax-search.md +40 -10
  126. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/personal-read.md +1 -1
  127. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/personal-write.md +33 -13
  128. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-build.md +62 -13
  129. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-read.md +11 -4
  130. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-templates.md +179 -59
  131. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/repo-update.md +18 -7
  132. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/collect_all.py +122 -39
  133. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/detect_updates.py +73 -10
  134. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/github_resource_facets.py +9 -1
  135. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +9 -1
  136. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/scripts/validate_memory.py +23 -1
  137. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/src/plugin-install.mjs +2 -0
  138. package/lib/memorax-code-codex-adapter/.codex-plugin/plugin.json +1 -1
  139. package/lib/memorax-code-codex-adapter/hooks/runtime-shell.json +1 -1
  140. package/lib/memorax-code-codex-adapter/package.json +1 -1
  141. package/lib/memorax-code-codex-adapter/runtime-hooks/memory-skill-reminder.mjs +16 -2
  142. package/lib/memorax-code-codex-adapter/skills/memorax-code/SKILL.md +23 -15
  143. package/lib/memorax-code-codex-adapter/skills/memorax-code/defaults.json +8 -5
  144. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/memorax-add.md +5 -1
  145. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/memorax-search.md +40 -10
  146. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/personal-read.md +1 -1
  147. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/personal-write.md +33 -13
  148. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-build.md +62 -13
  149. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-read.md +11 -4
  150. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-templates.md +179 -59
  151. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/repo-update.md +18 -7
  152. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/collect_all.py +122 -39
  153. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/detect_updates.py +73 -10
  154. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/github_resource_facets.py +9 -1
  155. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +9 -1
  156. package/lib/memorax-code-codex-adapter/skills/memorax-code/scripts/validate_memory.py +23 -1
  157. package/lib/memorax-code-dsh-adapter/cordis.patch.yml +10 -0
  158. package/lib/memorax-code-dsh-adapter/hooks/repo-memory-job.mjs +68 -0
  159. package/lib/memorax-code-dsh-adapter/package.json +69 -0
  160. package/lib/memorax-code-dsh-adapter/skills/memorax-code/SKILL.md +91 -0
  161. package/lib/memorax-code-dsh-adapter/skills/memorax-code/agents/claude.yaml +10 -0
  162. package/lib/memorax-code-dsh-adapter/skills/memorax-code/agents/openai.yaml +7 -0
  163. package/lib/memorax-code-dsh-adapter/skills/memorax-code/defaults.json +12 -0
  164. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/memorax-add.md +86 -0
  165. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/memorax-search.md +91 -0
  166. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/personal-read.md +46 -0
  167. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/personal-write.md +120 -0
  168. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-build.md +319 -0
  169. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-read.md +103 -0
  170. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-templates.md +390 -0
  171. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/repo-update.md +127 -0
  172. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/collect_all.py +579 -0
  173. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/detect_updates.py +919 -0
  174. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/git_commit_facets.py +222 -0
  175. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/github_resource_facets.py +512 -0
  176. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +517 -0
  177. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/prepare_repo_memory.py +411 -0
  178. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/user_profile_memory.py +528 -0
  179. package/lib/memorax-code-dsh-adapter/skills/memorax-code/scripts/validate_memory.py +248 -0
  180. package/lib/memorax-code-dsh-adapter/src/backend-client.mjs +119 -0
  181. package/lib/memorax-code-dsh-adapter/src/dsh-message.mjs +32 -0
  182. package/lib/memorax-code-dsh-adapter/src/dsh-version.mjs +18 -0
  183. package/lib/memorax-code-dsh-adapter/src/http-client.mjs +55 -0
  184. package/lib/memorax-code-dsh-adapter/src/index.mjs +72 -0
  185. package/lib/memorax-code-dsh-adapter/src/personal-context-worker.mjs +48 -0
  186. package/lib/memorax-code-dsh-adapter/src/personal-context.mjs +114 -0
  187. package/lib/memorax-code-dsh-adapter/src/plugin.mjs +724 -0
  188. package/lib/memorax-code-dsh-adapter/src/profile-lifecycle.mjs +1289 -0
  189. package/lib/memorax-code-dsh-adapter/src/protocol.mjs +145 -0
  190. package/lib/memorax-code-dsh-adapter/src/runtime-state.mjs +132 -0
  191. package/lib/memorax-code-opencode-adapter/hooks/repo-memory-job.mjs +37 -0
  192. package/lib/memorax-code-opencode-adapter/package.json +10 -0
  193. package/lib/memorax-code-opencode-adapter/skills/memorax-code/SKILL.md +91 -0
  194. package/lib/memorax-code-opencode-adapter/skills/memorax-code/agents/claude.yaml +10 -0
  195. package/lib/memorax-code-opencode-adapter/skills/memorax-code/agents/openai.yaml +7 -0
  196. package/lib/memorax-code-opencode-adapter/skills/memorax-code/defaults.json +12 -0
  197. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/memorax-add.md +86 -0
  198. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/memorax-search.md +91 -0
  199. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/personal-read.md +46 -0
  200. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/personal-write.md +120 -0
  201. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-build.md +319 -0
  202. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-read.md +103 -0
  203. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-templates.md +390 -0
  204. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/repo-update.md +127 -0
  205. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/collect_all.py +579 -0
  206. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/detect_updates.py +919 -0
  207. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/git_commit_facets.py +222 -0
  208. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/github_resource_facets.py +512 -0
  209. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/gitlab_resource_facets.py +517 -0
  210. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/prepare_repo_memory.py +411 -0
  211. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/user_profile_memory.py +528 -0
  212. package/lib/memorax-code-opencode-adapter/skills/memorax-code/scripts/validate_memory.py +248 -0
  213. package/lib/memorax-code-opencode-adapter/src/adapter-paths.mjs +37 -0
  214. package/lib/memorax-code-opencode-adapter/src/cli.mjs +260 -0
  215. package/lib/memorax-code-opencode-adapter/src/diagnostics.mjs +31 -0
  216. package/lib/memorax-code-opencode-adapter/src/plugin-install.mjs +673 -0
  217. package/lib/memorax-code-opencode-adapter/src/plugin.mjs +536 -0
  218. package/lib/memorax-code-opencode-adapter/src/repo-memory-server-runner.mjs +207 -0
  219. package/lib/resolve-claude-command.mjs +154 -1
  220. package/lib/resolve-codex-command.mjs +56 -1
  221. package/lib/run-entrypoint.mjs +6 -0
  222. package/package.json +7 -3
  223. package/lib/memorax-code-backend/dist/client-plugin-removal.js +0 -67
  224. /package/lib/memorax-code-backend/dist/{claude-transcript-turn.js → clients/claude/transcript-turn.js} +0 -0
  225. /package/lib/memorax-code-backend/dist/{codex-effective-prompt.js → clients/codex/effective-prompt.js} +0 -0
  226. /package/lib/memorax-code-backend/dist/{codex-rollout-turn.js → clients/codex/rollout-turn.js} +0 -0
  227. /package/lib/memorax-code-backend/dist/{codex-session-turn-index.js → clients/codex/session-turn-index.js} +0 -0
  228. /package/lib/memorax-code-backend/dist/{codex-workspace-links.js → clients/codex/workspace-links.js} +0 -0
  229. /package/lib/memorax-code-backend/dist/{backend-env.js → config/backend-env.js} +0 -0
  230. /package/lib/memorax-code-backend/dist/{proxy-env.js → config/proxy-env.js} +0 -0
  231. /package/lib/memorax-code-backend/dist/{entrypoint.js → entrypoints/main.js} +0 -0
  232. /package/lib/memorax-code-backend/dist/{backend-process.js → lifecycle/backend/process.js} +0 -0
  233. /package/lib/memorax-code-backend/dist/{backend-shutdown-request.js → lifecycle/backend/shutdown-request.js} +0 -0
  234. /package/lib/memorax-code-backend/dist/{backend-status.js → lifecycle/backend/status.js} +0 -0
  235. /package/lib/memorax-code-backend/dist/{adapter-lifecycle-participant.js → lifecycle/contracts.js} +0 -0
  236. /package/lib/memorax-code-backend/dist/{install-watchdog.js → lifecycle/install-watchdog.js} +0 -0
  237. /package/lib/memorax-code-backend/dist/{memory-observability.js → lifecycle/participant.js} +0 -0
  238. /package/lib/memorax-code-backend/dist/{memory-project.js → memory/project.js} +0 -0
  239. /package/lib/memorax-code-backend/dist/{incremental-jsonl-projection.js → shared/incremental-jsonl-projection.js} +0 -0
  240. /package/lib/memorax-code-backend/dist/{utils.js → shared/record.js} +0 -0
  241. /package/lib/memorax-code-backend/dist/{server-json.js → transport/http/json.js} +0 -0
  242. /package/lib/memorax-code-backend/dist/{memory-viewer-data-projection-cache.js → viewer/projection/cache.js} +0 -0
  243. /package/lib/memorax-code-backend/dist/{memory-viewer-event-identity.js → viewer/projection/event-identity.js} +0 -0
  244. /package/lib/memorax-code-backend/dist/{memory-viewer-redaction.js → viewer/projection/redaction.js} +0 -0
  245. /package/lib/memorax-code-backend/dist/{memory-viewer-turn-reference.js → viewer/projection/turn-reference.js} +0 -0
  246. /package/lib/memorax-code-backend/dist/{memory-viewer-logo.js → viewer/ui/logo.js} +0 -0
@@ -18,8 +18,10 @@ import {
18
18
  normalizeMemoraxMemoryOutputLanguage,
19
19
  } from "../lib/memorax-code-adapter-common/src/memorax-defaults.mjs";
20
20
  import { stagePackagedClientHookRuntime } from "../lib/client-hook-runtime.mjs";
21
+ import { discoverDshProfiles } from "../lib/dsh-plugin-install.mjs";
21
22
  import { ensureClaudeCommandEnv } from "../lib/resolve-claude-command.mjs";
22
23
  import { ensureCodexCommandEnv } from "../lib/resolve-codex-command.mjs";
24
+ import { commandOnPath } from "../lib/vscode-extension-command.mjs";
23
25
  import { resolveWindowsCliInvocation } from "../lib/windows-cli-invocation.mjs";
24
26
 
25
27
  const PLUGIN_NAME = "memorax-code-codex-adapter";
@@ -30,14 +32,17 @@ const HOOK_TRUST_SELECTION_ENV = "MEMORAX_CODE_CODEX_HOOK_TRUST_SELECTION_JSON";
30
32
  const PREFIX = "[MemoraX Code Install]:";
31
33
  const BACKEND_PREFIX = "[MemoraX Code Backend]:";
32
34
  const GREEN = "\x1b[32m";
35
+ const BRIGHT_CYAN = "\x1b[96m";
33
36
  const BLUE = "\x1b[34m";
34
37
  const RED = "\x1b[31m";
35
38
  const BOLD = "\x1b[1m";
39
+ const UNDERLINE = "\x1b[4m";
36
40
  const RESET = "\x1b[0m";
37
41
 
38
42
  if (truthyEnv(process.env.MEMORAX_CODE_SKIP_POSTINSTALL)) process.exit(0);
39
43
  const skipCodexPluginInstall = truthyEnv(process.env.MEMORAX_CODE_SKIP_CODEX_PLUGIN_INSTALL);
40
44
  const skipClaudeAdapterInstall = truthyEnv(process.env.MEMORAX_CODE_SKIP_CLAUDE_ADAPTER_INSTALL);
45
+ const skipOpenCodeAdapterInstall = truthyEnv(process.env.MEMORAX_CODE_SKIP_OPENCODE_ADAPTER_INSTALL);
41
46
 
42
47
  const scriptDir = dirname(fileURLToPath(import.meta.url));
43
48
  const memoraxCodeBin = join(scriptDir, "memorax-code.mjs");
@@ -48,10 +53,23 @@ const codexCommand = codexRuntime.command;
48
53
  const claudeRuntime = ensureClaudeCommandEnv();
49
54
  const claudeCommand = claudeRuntime.command;
50
55
  const updatePostinstall = postinstallUpdateMode();
51
- const scriptedAnswers = (canPrompt() || canPromptForHookUpdate()) && process.stdin.isTTY !== true
56
+ const scriptedAnswers = (canPrompt() || canPromptForUpdate()) && process.stdin.isTTY !== true
52
57
  ? parseScriptedAnswers(readFileSync(0, "utf8"))
53
58
  : undefined;
54
59
  const previousClients = readPersistedClientSelection();
60
+ const persistedDshSelection = readPersistedDshSelection();
61
+ let dshProfiles = [];
62
+ let dshProfilesVerified = true;
63
+ try {
64
+ dshProfiles = discoverDshProfiles();
65
+ } catch (error) {
66
+ dshProfilesVerified = false;
67
+ const code = typeof error?.code === "string" ? ` (${error.code})` : "";
68
+ logRed(`DeepSeek Harness Profile discovery could not be verified${code}; DSH setup was skipped, but other client setup will continue.`);
69
+ }
70
+ const dshSelected = dshProfilesVerified
71
+ && dshProfiles.length > 0
72
+ && persistedDshSelection !== false;
55
73
  if (seedMissingMemoraxCodeConfig() === "failed") {
56
74
  printPostinstallSummary("not-verified");
57
75
  process.exit(0);
@@ -70,22 +88,46 @@ try {
70
88
  process.exit(0);
71
89
  }
72
90
  runCommonPreflight();
73
- const requestedClients = previousClients ?? ["codex", "claude"];
91
+ const requestedClients = ["codex", "claude", "opencode"];
74
92
  const codexPreflight = requestedClients.includes("codex") && !skipCodexPluginInstall
75
- ? runCodexPreflight()
93
+ ? runCodexPreflight({
94
+ integrationSelected: !updatePostinstall
95
+ || previousClients === undefined
96
+ || previousClients.includes("codex"),
97
+ })
76
98
  : { ok: true, pluginCache: { marketplaceName: CLI_MARKETPLACE_NAME, versions: [] } };
77
99
  const claudePreflight = requestedClients.includes("claude") && !skipClaudeAdapterInstall
78
- ? runClaudePreflight()
100
+ ? runClaudePreflight({
101
+ integrationSelected: !updatePostinstall
102
+ || previousClients === undefined
103
+ || previousClients.includes("claude"),
104
+ })
105
+ : { ok: true };
106
+ const opencodePreflight = requestedClients.includes("opencode") && !skipOpenCodeAdapterInstall
107
+ ? runOpenCodePreflight({
108
+ integrationSelected: !updatePostinstall
109
+ || previousClients === undefined
110
+ || previousClients.includes("opencode"),
111
+ })
79
112
  : { ok: true };
80
- const installClients = requestedClients.filter((client) => {
113
+ const detectedClients = requestedClients.filter((client) => {
81
114
  if (client === "codex") return !skipCodexPluginInstall && codexPreflight.ok;
82
- return !skipClaudeAdapterInstall && claudePreflight.ok;
115
+ if (client === "claude") return !skipClaudeAdapterInstall && claudePreflight.ok;
116
+ return !skipOpenCodeAdapterInstall && opencodePreflight.ok;
83
117
  });
84
- const selectedClients = previousClients ?? installClients;
85
- if (previousClients) {
86
- log(clientSelectionMessage(previousClients));
118
+ const selectedClients = updatePostinstall && previousClients !== undefined
119
+ ? await chooseUpdateClients(previousClients, detectedClients, scriptedAnswers)
120
+ : detectedClients;
121
+ const installClients = detectedClients.filter((client) => selectedClients.includes(client));
122
+ if (updatePostinstall && previousClients !== undefined) {
123
+ log(clientSelectionMessage(selectedClients, { dshSelected }));
87
124
  } else {
88
- log(detectedClientMessage(installClients));
125
+ log(detectedClientMessage(installClients, dshSelected ? dshProfiles : []));
126
+ }
127
+ if (dshSelected) {
128
+ log(`DeepSeek Harness profiles: found (${dshProfiles.map((profile) => profile.name).join(", ")}); supported profiles will be reconciled by \`memorax-code start\`.`);
129
+ } else if (dshProfiles.length > 0) {
130
+ log("DeepSeek Harness profiles were detected, but the DSH integration is disabled by [clients].dsh.");
89
131
  }
90
132
  if (requestedClients.includes("codex") && !skipCodexPluginInstall && !codexPreflight.ok) {
91
133
  log("Codex runtime was not detected; skipping its adapter setup.");
@@ -93,13 +135,18 @@ if (requestedClients.includes("codex") && !skipCodexPluginInstall && !codexPrefl
93
135
  if (requestedClients.includes("claude") && !skipClaudeAdapterInstall && !claudePreflight.ok) {
94
136
  log("Claude Code runtime was not detected; skipping its adapter setup.");
95
137
  }
138
+ if (requestedClients.includes("opencode") && !skipOpenCodeAdapterInstall && !opencodePreflight.ok) {
139
+ log("OpenCode runtime or configuration was not detected; skipping its adapter setup.");
140
+ }
96
141
  if (writeClientSelectionConfig(selectedClients) === "failed") {
97
142
  printPostinstallSummary("not-verified");
98
143
  process.exit(0);
99
144
  }
100
- const clientMode = clientModeFor(installClients);
145
+ const clientMode = clientModeFor(installClients, {
146
+ includeDsh: dshProfilesVerified && persistedDshSelection !== false,
147
+ });
101
148
  let memoraxConfigResult = "skipped";
102
- if (installClients.length > 0) {
149
+ if (installClients.length > 0 || dshSelected) {
103
150
  memoraxConfigResult = await maybeConfigureMemoraxMemory(scriptedAnswers);
104
151
  }
105
152
  if (memoraxConfigResult === "configured") {
@@ -110,7 +157,12 @@ if (memoraxConfigResult === "configured") {
110
157
  }
111
158
  const codexClientEnabled = installClients.includes("codex");
112
159
  const claudeClientEnabled = installClients.includes("claude");
113
- const codexHooksBeforeUpdate = codexClientEnabled && updatePostinstall
160
+ const opencodeClientEnabled = installClients.includes("opencode");
161
+ const codexClientNewlyEnabled = codexClientEnabled
162
+ && updatePostinstall
163
+ && previousClients !== undefined
164
+ && !previousClients.includes("codex");
165
+ const codexHooksBeforeUpdate = codexClientEnabled && updatePostinstall && !codexClientNewlyEnabled
114
166
  ? inspectCodexPluginHooksForUpdate()
115
167
  : undefined;
116
168
  const result = codexClientEnabled
@@ -122,11 +174,17 @@ if (codexClientEnabled && result.status !== 0 && process.env.npm_lifecycle_event
122
174
  }
123
175
 
124
176
  if (codexClientEnabled && result.status === 0) {
125
- if (updatePostinstall) await maybeTrustUpdatedCodexPluginHooks(scriptedAnswers, codexHooksBeforeUpdate);
126
- else await maybeActivateCodexPluginHooks(scriptedAnswers);
177
+ if (codexClientNewlyEnabled) {
178
+ await maybeActivateCodexPluginHooks(scriptedAnswers, { updatePrompt: true });
179
+ } else if (updatePostinstall) {
180
+ await maybeTrustUpdatedCodexPluginHooks(scriptedAnswers, codexHooksBeforeUpdate);
181
+ } else {
182
+ await maybeActivateCodexPluginHooks(scriptedAnswers);
183
+ }
127
184
  }
128
185
  const skipCodexAdapter = !codexClientEnabled;
129
186
  const skipClaudeAdapter = !claudeClientEnabled;
187
+ const skipOpenCodeAdapter = !opencodeClientEnabled;
130
188
  const codexSkipReason = postinstallClientSkipReason({
131
189
  explicitlySkipped: skipCodexPluginInstall,
132
190
  selected: selectedClients.includes("codex"),
@@ -137,21 +195,39 @@ const claudeSkipReason = postinstallClientSkipReason({
137
195
  selected: selectedClients.includes("claude"),
138
196
  enabled: claudeClientEnabled,
139
197
  });
198
+ const opencodeSkipReason = postinstallClientSkipReason({
199
+ explicitlySkipped: skipOpenCodeAdapterInstall,
200
+ selected: selectedClients.includes("opencode"),
201
+ enabled: opencodeClientEnabled,
202
+ });
140
203
 
141
- let backendAndAdaptersStatus = startBackendAndCheck({
204
+ const backendAndAdapters = startBackendAndCheck({
142
205
  skipCodexAdapter,
143
206
  clientMode,
144
207
  codexSkipReason,
145
208
  skipClaudeAdapter,
146
209
  claudeAdapterRequired: !skipClaudeAdapter,
147
210
  claudeSkipReason,
211
+ skipOpenCodeAdapter,
212
+ opencodeAdapterRequired: !skipOpenCodeAdapter,
213
+ opencodeSkipReason,
148
214
  });
215
+ const backendAndAdaptersStatus = backendAndAdapters.status;
149
216
  if (backendAndAdaptersStatus === "enabled") {
150
217
  logGreen(`Client Hook runtime ${stagedHookRuntime.generationId} activated.`);
151
218
  }
152
219
  if (backendAndAdaptersStatus === "enabled") {
153
- printNextSteps({ codexAdapterEnabled: !skipCodexAdapter, claudeAdapterEnabled: !skipClaudeAdapter });
154
- printCommonCommands({ codexAdapterEnabled: !skipCodexAdapter, claudeAdapterEnabled: !skipClaudeAdapter });
220
+ printNextSteps({
221
+ codexAdapterEnabled: !skipCodexAdapter,
222
+ claudeAdapterEnabled: !skipClaudeAdapter,
223
+ dshAdapterEnabled: backendAndAdapters.dshAdapterEnabled,
224
+ opencodeAdapterEnabled: !skipOpenCodeAdapter,
225
+ });
226
+ printCommonCommands({
227
+ codexAdapterEnabled: !skipCodexAdapter,
228
+ claudeAdapterEnabled: !skipClaudeAdapter,
229
+ opencodeAdapterEnabled: !skipOpenCodeAdapter,
230
+ });
155
231
  }
156
232
  printPostinstallSummary(backendAndAdaptersStatus);
157
233
  if (backendAndAdaptersStatus === "enabled") {
@@ -163,26 +239,31 @@ process.exit(0);
163
239
 
164
240
  async function maybeConfigureMemoraxMemory(scriptedAnswers) {
165
241
  printMemoraxDisclosure();
166
- if (!canPrompt()) {
242
+ const promptAvailable = canPrompt();
243
+ if (promptAvailable && readMemoraxInstallStatus()?.configured) {
244
+ log("Existing MemoraX credentials detected; keeping the effective configuration unchanged.");
245
+ return "preserved";
246
+ }
247
+ if (!promptAvailable) {
167
248
  log(`This install cannot prompt for a MemoraX ID and key. Register at ${MEMORAX_ACCOUNT_URL}, then edit \`~/.memorax-code/config.toml\` or rerun interactively with \`--foreground-scripts\`.`);
168
249
  return "skipped";
169
250
  }
170
251
  if (scriptedAnswers) {
171
252
  return await configureMemoraxMemoryFromAnswers(scriptedAnswers);
172
253
  }
254
+ printMemoraxRegistrationLink();
255
+ printMemoraxUserIdGuidance();
173
256
  let rl = createInterface({ input: process.stdin, output: process.stderr });
174
257
  try {
175
- const configureNow = await rl.question(`${PREFIX} Connect MemoraX Code to MemoraX now? [Y/n] `);
176
- if (/^n(?:o)?$/i.test(configureNow.trim())) {
177
- log("MemoraX connection skipped. MemoraX Code memory is not fully configured until valid credentials are supplied.");
178
- return "skipped";
179
- }
180
- log(`If you do not have a MemoraX account/API key, register at ${MEMORAX_ACCOUNT_URL}.`);
181
- const userId = (await rl.question(`${PREFIX} MemoraX base user ID: `)).trim();
258
+ const userId = await questionRequiredLine(
259
+ rl,
260
+ `${PREFIX} Your MemoraX user ID (required, e.g. your-name): `,
261
+ "MemoraX user ID is required.",
262
+ );
182
263
  const outputLanguage = await questionPreferredLanguage(rl);
183
264
  rl.close();
184
265
  rl = undefined;
185
- const apiKey = (await questionMasked(`${PREFIX} MemoraX API key: `)).trim();
266
+ const apiKey = await questionRequiredMasked(`${PREFIX} MemoraX API key (required): `);
186
267
  return await writeMemoraxConfigFromInput({
187
268
  userId,
188
269
  apiKey,
@@ -194,29 +275,67 @@ async function maybeConfigureMemoraxMemory(scriptedAnswers) {
194
275
  }
195
276
  }
196
277
 
197
- async function configureMemoraxMemoryFromAnswers(answers) {
198
- if (answers.length === 0) {
199
- log(`No MemoraX connection response was received. Register at ${MEMORAX_ACCOUNT_URL}, then edit \`~/.memorax-code/config.toml\` or rerun interactively with \`--foreground-scripts\`.`);
200
- return "skipped";
278
+ async function chooseUpdateClients(previousClients, detectedClients, scriptedAnswers) {
279
+ const selected = new Set(previousClients);
280
+ const availableDisabledClients = detectedClients.filter((client) => !selected.has(client));
281
+ if (availableDisabledClients.length === 0) return [...previousClients];
282
+
283
+ if (!canPromptForUpdate()) {
284
+ for (const client of availableDisabledClients) {
285
+ const label = clientLabel(client);
286
+ log(`${label} runtime is available, but its integration remains disabled because this update cannot prompt. Rerun \`memorax-code update\` from an interactive terminal to choose whether to enable it.`);
287
+ }
288
+ return [...previousClients];
201
289
  }
202
- log("Connect MemoraX Code to MemoraX now? [Y/n]");
203
- const configureNow = String(answers.shift() ?? "").trim();
204
- if (/^n(?:o)?$/i.test(configureNow)) {
205
- log("MemoraX connection skipped. MemoraX Code memory is not fully configured until valid credentials are supplied.");
206
- return "skipped";
290
+
291
+ let rl;
292
+ try {
293
+ for (const client of availableDisabledClients) {
294
+ const label = clientLabel(client);
295
+ const question = `${label} runtime is available, but its integration is disabled in [clients]. Enable it now? [Y/n]`;
296
+ let answer;
297
+ if (scriptedAnswers) {
298
+ log(question);
299
+ answer = String(scriptedAnswers.shift() ?? "").trim();
300
+ } else {
301
+ rl ??= createInterface({ input: process.stdin, output: process.stderr });
302
+ answer = (await rl.question(`${PREFIX} ${question} `)).trim();
303
+ }
304
+ if (/^n(?:o)?$/i.test(answer)) {
305
+ log(`Keeping the ${label} integration disabled.`);
306
+ } else {
307
+ selected.add(client);
308
+ logGreen(`Enabling the ${label} integration.`);
309
+ }
310
+ }
311
+ } finally {
312
+ rl?.close();
207
313
  }
208
- log(`If you do not have a MemoraX account/API key, register at ${MEMORAX_ACCOUNT_URL}.`);
209
- log("MemoraX base user ID: <provided>");
210
- const userId = String(answers.shift() ?? "").trim();
211
- const outputLanguageAnswer = String(answers.shift() ?? "").trim();
212
- log(`Preferred language [ZH/en] (used for Memory extraction): ${outputLanguageAnswer ? "<provided>" : "<default>"}`);
213
- log("MemoraX API key: <provided>");
214
- const apiKey = String(answers.shift() ?? "").trim();
314
+ return ["codex", "claude", "opencode"].filter((client) => selected.has(client));
315
+ }
316
+
317
+ async function configureMemoraxMemoryFromAnswers(answers) {
318
+ printMemoraxRegistrationLink();
319
+ printMemoraxUserIdGuidance();
320
+ const userId = requiredScriptedAnswer(answers, {
321
+ prompt: "Your MemoraX user ID (required, e.g. your-name)",
322
+ requiredMessage: "MemoraX user ID is required.",
323
+ missingMessage: "No MemoraX user ID response was received; MemoraX configuration is incomplete.",
324
+ });
325
+ if (!userId) return "skipped";
326
+ const outputLanguage = scriptedPreferredLanguage(answers);
327
+ if (!outputLanguage) return "skipped";
328
+ const apiKey = requiredScriptedAnswer(answers, {
329
+ prompt: "MemoraX API key (required)",
330
+ requiredMessage: "MemoraX API key is required.",
331
+ missingMessage: "No MemoraX API key response was received; MemoraX configuration is incomplete.",
332
+ });
333
+ if (!apiKey) return "skipped";
215
334
  return await writeMemoraxConfigFromInput({
216
335
  userId,
217
336
  apiKey,
218
337
  endpoint: memoraxInstallEndpoint(),
219
- outputLanguage: preferredLanguage(outputLanguageAnswer),
338
+ outputLanguage,
220
339
  });
221
340
  }
222
341
 
@@ -226,9 +345,19 @@ function printMemoraxDisclosure() {
226
345
  log("Newly generated configuration enables automatic writeback. Existing configuration is never enabled implicitly; disable it with `[memory.writeback] enabled = false` or `MEMORAX_CODE_MEMORAX_WRITEBACK_ENABLED=false`.");
227
346
  }
228
347
 
348
+ function printMemoraxUserIdGuidance() {
349
+ log("MemoraX uses one user ID to keep your coding memories consistent across supported agents and devices.");
350
+ log("Choose a stable ID and use the same value everywhere; MemoraX Code separates repositories automatically.");
351
+ }
352
+
353
+ function printMemoraxRegistrationLink() {
354
+ log("No MemoraX account or API key yet?");
355
+ log(`→ Register here: ${BRIGHT_CYAN}${BOLD}${UNDERLINE}${MEMORAX_ACCOUNT_URL}${RESET}`);
356
+ }
357
+
229
358
  async function writeMemoraxConfigFromInput({ userId, apiKey, endpoint, outputLanguage }) {
230
359
  if (!userId || !apiKey) {
231
- logRed("MemoraX config was not written because base user ID or API key was empty.");
360
+ logRed("MemoraX config was not written because MemoraX user ID or API key was empty.");
232
361
  return "skipped";
233
362
  }
234
363
  if (!outputLanguage) {
@@ -244,6 +373,45 @@ async function writeMemoraxConfigFromInput({ userId, apiKey, endpoint, outputLan
244
373
  return "configured";
245
374
  }
246
375
 
376
+ async function questionRequiredLine(rl, prompt, requiredMessage) {
377
+ while (true) {
378
+ const answer = (await rl.question(prompt)).trim();
379
+ if (answer) return answer;
380
+ logRed(requiredMessage);
381
+ }
382
+ }
383
+
384
+ async function questionRequiredMasked(prompt) {
385
+ while (true) {
386
+ const answer = (await questionMasked(prompt)).trim();
387
+ if (answer) return answer;
388
+ logRed("MemoraX API key is required.");
389
+ }
390
+ }
391
+
392
+ function requiredScriptedAnswer(answers, { prompt, requiredMessage, missingMessage }) {
393
+ while (answers.length > 0) {
394
+ const answer = String(answers.shift() ?? "").trim();
395
+ log(`${prompt}: ${answer ? "<provided>" : "<empty>"}`);
396
+ if (answer) return answer;
397
+ logRed(requiredMessage);
398
+ }
399
+ logRed(missingMessage);
400
+ return undefined;
401
+ }
402
+
403
+ function scriptedPreferredLanguage(answers) {
404
+ while (answers.length > 0) {
405
+ const answer = String(answers.shift() ?? "").trim();
406
+ log(`Preferred language [ZH/en] (used for Memory extraction): ${answer ? "<provided>" : "<default>"}`);
407
+ const language = preferredLanguage(answer);
408
+ if (language) return language;
409
+ logRed("Preferred language must be zh or en.");
410
+ }
411
+ logRed("No preferred language response was received; MemoraX configuration is incomplete.");
412
+ return undefined;
413
+ }
414
+
247
415
  async function questionPreferredLanguage(rl) {
248
416
  while (true) {
249
417
  const answer = await rl.question(`${PREFIX} Preferred language [ZH/en] (used for Memory extraction): `);
@@ -350,7 +518,7 @@ async function maybeTrustUpdatedCodexPluginHooks(scriptedAnswers, previousHooks)
350
518
  if (report.hooks.length === 0) return "unchanged";
351
519
 
352
520
  printUpdatedCodexHooks(report.hooks, previousHooks);
353
- if (!canPromptForHookUpdate()) {
521
+ if (!canPromptForUpdate()) {
354
522
  warnUpdatedHookTrustSkipped("This update is running without an interactive terminal, so the new or changed Hooks remain untrusted.");
355
523
  return "skipped";
356
524
  }
@@ -470,8 +638,8 @@ function warnUpdatedHookTrustSkipped(message) {
470
638
  logRed("Review and authorize the current MemoraX Code Codex Hooks with `memorax-code codex-plugin trust-hooks`.");
471
639
  }
472
640
 
473
- async function maybeActivateCodexPluginHooks(scriptedAnswers) {
474
- if (!canPrompt()) {
641
+ async function maybeActivateCodexPluginHooks(scriptedAnswers, { updatePrompt = false } = {}) {
642
+ if (!(updatePrompt ? canPromptForUpdate() : canPrompt())) {
475
643
  log("Codex hook activation was not prompted. Run `memorax-code codex-plugin activate --yes` later to activate and trust MemoraX Code Codex Adapter hooks.");
476
644
  return "skipped";
477
645
  }
@@ -512,7 +680,7 @@ function canPrompt() {
512
680
  return canPromptOnStderr();
513
681
  }
514
682
 
515
- function canPromptForHookUpdate() {
683
+ function canPromptForUpdate() {
516
684
  return updatePostinstall && canPromptOnStderr();
517
685
  }
518
686
 
@@ -543,7 +711,22 @@ function readPersistedClientSelection() {
543
711
  try {
544
712
  const clients = parse(readFileSync(path, "utf8"))?.clients;
545
713
  if (!clients || typeof clients !== "object" || typeof clients.codex !== "boolean" || typeof clients.claude !== "boolean") return undefined;
546
- return [clients.codex ? "codex" : undefined, clients.claude ? "claude" : undefined].filter(Boolean);
714
+ return [
715
+ clients.codex ? "codex" : undefined,
716
+ clients.claude ? "claude" : undefined,
717
+ clients.opencode === true ? "opencode" : undefined,
718
+ ].filter(Boolean);
719
+ } catch {
720
+ return undefined;
721
+ }
722
+ }
723
+
724
+ function readPersistedDshSelection() {
725
+ const path = memoraxCodeConfigPath();
726
+ if (!existsSync(path)) return undefined;
727
+ try {
728
+ const value = parse(readFileSync(path, "utf8"))?.clients?.dsh;
729
+ return typeof value === "boolean" ? value : undefined;
547
730
  } catch {
548
731
  return undefined;
549
732
  }
@@ -561,7 +744,8 @@ function writeClientSelectionConfig(clients) {
561
744
  }
562
745
 
563
746
  function setManagedClientSelection(text, clients) {
564
- const withClaude = setTomlField(text, "clients", "claude", String(clients.includes("claude")));
747
+ const withOpenCode = setTomlField(text, "clients", "opencode", String(clients.includes("opencode")));
748
+ const withClaude = setTomlField(withOpenCode, "clients", "claude", String(clients.includes("claude")));
565
749
  return setTomlField(withClaude, "clients", "codex", String(clients.includes("codex")));
566
750
  }
567
751
 
@@ -609,6 +793,8 @@ function defaultMemoraxCodeConfig() {
609
793
  "[clients]",
610
794
  "codex = true # Manage the Codex adapter.",
611
795
  "claude = true # Manage the Claude adapter.",
796
+ "dsh = true # Manage the DeepSeek Harness adapter when Profiles exist.",
797
+ "opencode = true # Manage the OpenCode adapter.",
612
798
  "",
613
799
  "# MemoraX remote-memory connection. Credentials may also come from the environment.",
614
800
  "[memorax]",
@@ -628,7 +814,7 @@ function defaultMemoraxCodeConfig() {
628
814
  "[memory.add]",
629
815
  `output_language = "${MEMORAX_DEFAULT_MEMORY_OUTPUT_LANGUAGE}" # Language for newly generated MemoraX memories.`,
630
816
  "",
631
- "# Controls how often Codex and Claude Code native client sessions see the MemoraX Code skill reminder.",
817
+ "# Controls how often supported native client sessions see the MemoraX Code skill reminder.",
632
818
  "[memory.skill_reminder]",
633
819
  "interval_turns = 5 # Show the MemoraX Code skill reminder every N native client turns, starting on the first turn.",
634
820
  "",
@@ -647,6 +833,14 @@ function defaultMemoraxCodeConfig() {
647
833
  "enabled = true # Enable local Claude session memory trace collection.",
648
834
  "capture_content = true # Store content in local Claude trace events.",
649
835
  "",
836
+ "[trace.dsh]",
837
+ "enabled = true # Enable local DSH session memory trace collection.",
838
+ "capture_content = true # Store content in local DSH trace events.",
839
+ "",
840
+ "[trace.opencode]",
841
+ "enabled = true # Enable local OpenCode session memory trace collection.",
842
+ "capture_content = true # Store content in local OpenCode trace events.",
843
+ "",
650
844
  ].join("\n");
651
845
  }
652
846
 
@@ -705,20 +899,23 @@ function tomlString(value) {
705
899
  function runCommonPreflight() {
706
900
  log("Checking local install state...");
707
901
  if (updatePostinstall) {
708
- log("Package update detected; refreshing MemoraX Code assets without interactive setup prompts.");
902
+ log("Package update detected; refreshing MemoraX Code assets and checking client availability.");
709
903
  }
710
904
  const memoraxCodeVersion = runNodeMemoraxCodeCommand(["--version"], { print: false });
711
905
  log(`MemoraX Code backend package: ${commandSummary(memoraxCodeVersion) ?? packageVersionSummary()}`);
712
906
  if (skipCodexPluginInstall) {
713
- log("Codex plugin registration is disabled for this npm postinstall; backend and Claude Code setup can still continue.");
907
+ log("Codex plugin registration is disabled for this npm postinstall; other client setup can still continue.");
714
908
  }
715
909
  if (skipClaudeAdapterInstall) {
716
- log("Claude Code adapter setup is disabled for this npm postinstall; backend and Codex setup can still continue.");
910
+ log("Claude Code adapter setup is disabled for this npm postinstall; other client setup can still continue.");
911
+ }
912
+ if (skipOpenCodeAdapterInstall) {
913
+ log("OpenCode adapter setup is disabled for this npm postinstall; other client setup can still continue.");
717
914
  }
718
915
  return {};
719
916
  }
720
917
 
721
- function runCodexPreflight() {
918
+ function runCodexPreflight({ integrationSelected = true } = {}) {
722
919
  const version = runExternalCommand(codexCommand, ["--version"], { print: false, timeout: 10_000 });
723
920
  const runtimeLabel = codexRuntime.source === "app-bundled"
724
921
  ? "Codex App runtime"
@@ -732,16 +929,45 @@ function runCodexPreflight() {
732
929
  const pluginCache = installedPluginCache();
733
930
  log(`Existing Codex plugin cache: ${pluginCache.versions.length > 0 ? `found (${pluginCache.versions.join(", ")})` : "not installed"}`);
734
931
  log(`Codex client process: ${codexClientRunning() ? "running" : "not detected"}`);
735
- log("Keeping Codex provider config unchanged and enabling the shared memory hook integration.");
932
+ log(integrationSelected
933
+ ? "Keeping Codex provider config unchanged and enabling the shared memory hook integration."
934
+ : "Keeping Codex provider config unchanged while checking whether to enable its integration.");
736
935
  return { ok: true, pluginCache };
737
936
  }
738
937
 
739
- function runClaudePreflight() {
938
+ function runClaudePreflight({ integrationSelected = true } = {}) {
740
939
  const version = runExternalCommand(claudeCommand, ["--version"], { print: false, timeout: 10_000 });
741
- const runtimeLabel = claudeRuntime.source === "vscode-bundled" ? "Claude VS Code runtime" : "Claude CLI";
940
+ const runtimeLabel = claudeRuntime.source === "app-bundled"
941
+ ? "Claude Code App runtime"
942
+ : claudeRuntime.source === "vscode-bundled"
943
+ ? "Claude VS Code runtime"
944
+ : "Claude CLI";
742
945
  log(`${runtimeLabel}: ${commandSummary(version) ?? "not runnable"}`);
743
946
  if (version.status !== 0) return { ok: false };
744
- log("Keeping Claude Code provider config unchanged and enabling the shared memory Hook integration.");
947
+ log(integrationSelected
948
+ ? "Keeping Claude Code provider config unchanged and enabling the shared memory Hook integration."
949
+ : "Keeping Claude Code provider config unchanged while checking whether to enable its integration.");
950
+ return { ok: true };
951
+ }
952
+
953
+ function runOpenCodePreflight({ integrationSelected = true } = {}) {
954
+ const explicitConfigDir = stringOption(process.env.OPENCODE_CONFIG_DIR);
955
+ const configHome = stringOption(process.env.XDG_CONFIG_HOME) ?? join(homedir(), ".config");
956
+ const configDir = resolve(explicitConfigDir ?? join(configHome, "opencode"));
957
+ const configDetected = explicitConfigDir !== undefined || existsSync(configDir);
958
+ const cliDetected = commandOnPath(
959
+ "opencode",
960
+ process.env.PATH,
961
+ process.platform,
962
+ process.env.PATHEXT,
963
+ );
964
+ const detected = configDetected || cliDetected;
965
+ log(`OpenCode configuration: ${configDetected ? `found (${configDir})` : "not detected"}`);
966
+ log(`OpenCode CLI: ${cliDetected ? "found in PATH" : "not detected"}`);
967
+ if (!detected) return { ok: false };
968
+ log(integrationSelected
969
+ ? "Keeping OpenCode provider config unchanged and enabling the shared memory plugin integration."
970
+ : "Keeping OpenCode provider config unchanged while checking whether to enable its integration.");
745
971
  return { ok: true };
746
972
  }
747
973
 
@@ -768,7 +994,17 @@ function installedPluginCacheVersions(marketplaceName) {
768
994
  }
769
995
  }
770
996
 
771
- function startBackendAndCheck({ skipCodexAdapter = false, clientMode = "all", codexSkipReason, skipClaudeAdapter = false, claudeAdapterRequired = !skipClaudeAdapter, claudeSkipReason } = {}) {
997
+ function startBackendAndCheck({
998
+ skipCodexAdapter = false,
999
+ clientMode = "all",
1000
+ codexSkipReason,
1001
+ skipClaudeAdapter = false,
1002
+ claudeAdapterRequired = !skipClaudeAdapter,
1003
+ claudeSkipReason,
1004
+ skipOpenCodeAdapter = false,
1005
+ opencodeAdapterRequired = !skipOpenCodeAdapter,
1006
+ opencodeSkipReason,
1007
+ } = {}) {
772
1008
  logGreen("Starting backend with `memorax-code start`...");
773
1009
  const adapterFlags = clientLifecycleFlags({ clientMode });
774
1010
  const startArgs = ["start", ...adapterFlags];
@@ -780,18 +1016,18 @@ function startBackendAndCheck({ skipCodexAdapter = false, clientMode = "all", co
780
1016
  if (clientHookRuntimeActivationFailed(started)) {
781
1017
  logRed("Client Hook runtime activation failed; automatic lifecycle recovery was skipped.");
782
1018
  logRed("The previously active runtime remains authoritative.");
783
- return "not-verified";
1019
+ return { status: "not-verified", dshAdapterEnabled: false };
784
1020
  }
785
1021
  if (lifecycleLockFailureCode(started)) {
786
1022
  logRed("Automatic stop/start recovery is skipped because another MemoraX Code lifecycle command still owns the Backend authority.");
787
1023
  printLifecycleLockFailureSuggestions();
788
- return "not-verified";
1024
+ return { status: "not-verified", dshAdapterEnabled: false };
789
1025
  }
790
1026
  const runtimeAuthorityFailure = runtimeAuthorityFailureCode(started);
791
1027
  if (runtimeAuthorityFailure) {
792
1028
  logRed("Automatic stop/start recovery is skipped because persisted Backend runtime authority requires explicit repair.");
793
1029
  printRuntimeAuthorityFailureSuggestions(runtimeAuthorityFailure);
794
- return "not-verified";
1030
+ return { status: "not-verified", dshAdapterEnabled: false };
795
1031
  }
796
1032
  logRed("Attempting automatic recovery: `memorax-code stop` then `memorax-code start`...");
797
1033
  runMemoraxCodeCommand(["stop", ...adapterFlags]);
@@ -802,7 +1038,7 @@ function startBackendAndCheck({ skipCodexAdapter = false, clientMode = "all", co
802
1038
  logRed("Diagnostic: running `memorax-code status` so the failure is visible.");
803
1039
  runMemoraxCodeCommand(statusArgs);
804
1040
  printFailureSuggestions();
805
- return "not-verified";
1041
+ return { status: "not-verified", dshAdapterEnabled: false };
806
1042
  }
807
1043
  }
808
1044
  logGreen(recovered ? "Backend start completed after automatic recovery." : "Backend start completed.");
@@ -811,19 +1047,27 @@ function startBackendAndCheck({ skipCodexAdapter = false, clientMode = "all", co
811
1047
  if (checked.status !== 0) {
812
1048
  logRed("Backend status check failed during npm postinstall.");
813
1049
  printFailureSuggestions();
814
- return "not-verified";
1050
+ return { status: "not-verified", dshAdapterEnabled: false };
815
1051
  }
816
1052
  logGreen("Backend status check completed.");
817
1053
  const enabled = memoraxCodeEnabled(checked, {
818
1054
  codexAdapterRequired: !skipCodexAdapter,
819
1055
  claudeAdapterRequired,
1056
+ opencodeAdapterRequired,
820
1057
  });
821
1058
  if (!enabled) {
822
- if (skipCodexAdapter || skipClaudeAdapter) printSkippedAdapterDiagnostics({ codexSkipReason, claudeSkipReason });
823
- else printUnavailableDiagnostics();
824
- return "unavailable";
1059
+ printUnavailableDiagnostics({ codexSkipReason, claudeSkipReason, opencodeSkipReason });
1060
+ return { status: "unavailable", dshAdapterEnabled: false };
825
1061
  }
826
- return "enabled";
1062
+ return {
1063
+ status: "enabled",
1064
+ dshAdapterEnabled: dshAdapterReady(checked),
1065
+ };
1066
+ }
1067
+
1068
+ function dshAdapterReady(statusResult) {
1069
+ const output = `${statusResult.stdout ?? ""}\n${statusResult.stderr ?? ""}`;
1070
+ return /\bDSH adapter:\s*ok\b[^\r\n]*\bintegration=plugin\b/im.test(stripAnsi(output));
827
1071
  }
828
1072
 
829
1073
  function pendingClientHookRuntimeEnv() {
@@ -862,13 +1106,12 @@ function clientLifecycleFlags({ clientMode = "all" } = {}) {
862
1106
  return ["--clients", clientMode];
863
1107
  }
864
1108
 
865
- function clientModeFor(clients) {
866
- const hasCodex = clients.includes("codex");
867
- const hasClaude = clients.includes("claude");
868
- if (hasCodex && hasClaude) return "all";
869
- if (hasCodex) return "codex";
870
- if (hasClaude) return "claude";
871
- return "none";
1109
+ function clientModeFor(clients, { includeDsh = false } = {}) {
1110
+ const selected = ["codex", "claude", "dsh", "opencode"].filter((client) => (
1111
+ client === "dsh" ? includeDsh : clients.includes(client)
1112
+ ));
1113
+ if (selected.length === 4) return "all";
1114
+ return selected.length > 0 ? selected.join(",") : "none";
872
1115
  }
873
1116
 
874
1117
  function postinstallClientSkipReason({ explicitlySkipped, selected, enabled }) {
@@ -877,22 +1120,51 @@ function postinstallClientSkipReason({ explicitlySkipped, selected, enabled }) {
877
1120
  return enabled ? undefined : "client-selection";
878
1121
  }
879
1122
 
880
- function clientSelectionMessage(clients) {
1123
+ function clientSelectionMessage(clients, { dshSelected = false } = {}) {
1124
+ if (dshSelected) {
1125
+ const labels = [
1126
+ clients.includes("codex") ? "Codex" : undefined,
1127
+ clients.includes("claude") ? "Claude Code" : undefined,
1128
+ "DeepSeek Harness",
1129
+ clients.includes("opencode") ? "OpenCode" : undefined,
1130
+ ].filter(Boolean);
1131
+ return `Configuring MemoraX Code for ${joinedLabels(labels)}.`;
1132
+ }
881
1133
  const hasCodex = clients.includes("codex");
882
1134
  const hasClaude = clients.includes("claude");
1135
+ const hasOpenCode = clients.includes("opencode");
1136
+ if (hasCodex && hasClaude && hasOpenCode) return "Configuring MemoraX Code for Codex, Claude Code, and OpenCode.";
883
1137
  if (hasCodex && hasClaude) return "Configuring MemoraX Code for Codex and Claude Code.";
1138
+ if (hasCodex && hasOpenCode) return "Configuring MemoraX Code for Codex and OpenCode.";
1139
+ if (hasClaude && hasOpenCode) return "Configuring MemoraX Code for Claude Code and OpenCode.";
884
1140
  if (hasCodex) return "Configuring MemoraX Code for Codex only.";
885
1141
  if (hasClaude) return "Configuring MemoraX Code for Claude Code only.";
1142
+ if (hasOpenCode) return "Configuring MemoraX Code for OpenCode only.";
886
1143
  return "Skipping client adapter setup for this npm postinstall.";
887
1144
  }
888
1145
 
889
- function detectedClientMessage(clients) {
890
- if (clients.length === 0) {
1146
+ function clientLabel(client) {
1147
+ if (client === "codex") return "Codex";
1148
+ if (client === "claude") return "Claude Code";
1149
+ return "OpenCode";
1150
+ }
1151
+
1152
+ function detectedClientMessage(clients, dshProfiles = []) {
1153
+ if (clients.length === 0 && dshProfiles.length === 0) {
891
1154
  return "No supported client runtime was detected; starting the shared Backend without client adapters.";
892
1155
  }
1156
+ if (clients.length === 0) {
1157
+ return "Detected existing DeepSeek Harness profiles; configuring the native DSH plugin and shared Backend.";
1158
+ }
893
1159
  return `Detected supported client runtimes. ${clientSelectionMessage(clients)}`;
894
1160
  }
895
1161
 
1162
+ function joinedLabels(labels) {
1163
+ if (labels.length < 2) return labels[0] ?? "";
1164
+ if (labels.length === 2) return `${labels[0]} and ${labels[1]}`;
1165
+ return `${labels.slice(0, -1).join(", ")}, and ${labels.at(-1)}`;
1166
+ }
1167
+
896
1168
  function codexHome() {
897
1169
  return process.env.CODEX_HOME || join(homedir(), ".codex");
898
1170
  }
@@ -1020,35 +1292,65 @@ function codexClientRunning() {
1020
1292
  });
1021
1293
  }
1022
1294
 
1023
- function printNextSteps({ codexAdapterEnabled = true, claudeAdapterEnabled = true } = {}) {
1024
- const clientText = enabledClientText({ codexAdapterEnabled, claudeAdapterEnabled });
1025
- if (clientText && updatePostinstall) {
1295
+ function printNextSteps({
1296
+ codexAdapterEnabled = true,
1297
+ claudeAdapterEnabled = true,
1298
+ dshAdapterEnabled = false,
1299
+ opencodeAdapterEnabled = true,
1300
+ } = {}) {
1301
+ const hookClientText = enabledClientText({
1302
+ codexAdapterEnabled,
1303
+ claudeAdapterEnabled,
1304
+ opencodeAdapterEnabled,
1305
+ });
1306
+ if (hookClientText && updatePostinstall) {
1026
1307
  logGreen(`${bold("The new Hook runtime is active")}; existing sessions with the stable shell select it on their next user prompt.`);
1027
- log(`Restart or refresh ${clientText} only if its plugin shell was installed, changed, or newly enabled, or if MemoraX Code is not active on the next prompt.`);
1028
- } else if (clientText) {
1029
- logGreen(`${bold(`Restart or refresh ${clientText}`)} before opening a new MemoraX Code session.`);
1030
- } else {
1308
+ log(`Restart or refresh ${hookClientText} only if its plugin shell was installed, changed, or newly enabled, or if MemoraX Code is not active on the next prompt.`);
1309
+ } else if (hookClientText) {
1310
+ logGreen(`${bold(`Restart or refresh ${hookClientText}`)} before opening a new MemoraX Code session.`);
1311
+ }
1312
+ if (dshAdapterEnabled) {
1313
+ logGreen(`${bold("Restart or refresh DeepSeek Harness")} so its Profiles load the installed MemoraX Code plugin.`);
1314
+ } else if (!hookClientText) {
1031
1315
  logGreen(`${bold("MemoraX Code backend is running")}; client adapters were skipped for this install.`);
1032
1316
  }
1033
1317
  if (codexAdapterEnabled && !updatePostinstall) {
1034
1318
  logGreen(`After restart, ${bold("enable the MemoraX Code Codex Adapter plugin")} from Codex Plugins or CLI \`/plugins\` if it is not already enabled.`);
1035
1319
  }
1036
- const statusCommands = statusCommandText({ codexAdapterEnabled, claudeAdapterEnabled });
1037
- log(`If MemoraX Code is not active ${updatePostinstall ? "on the next prompt" : "in new sessions"}, run ${statusCommands}.`);
1320
+ const statusCommands = statusCommandText({ codexAdapterEnabled, claudeAdapterEnabled, opencodeAdapterEnabled });
1321
+ if (hookClientText || !dshAdapterEnabled) {
1322
+ log(`If MemoraX Code is not active ${updatePostinstall ? "on the next prompt" : "in new sessions"}, run ${statusCommands}.`);
1323
+ }
1324
+ if (dshAdapterEnabled) {
1325
+ log("If MemoraX Code is not active after restarting or refreshing DeepSeek Harness, run `memorax-code status`.");
1326
+ }
1038
1327
  log("If npm hides install details, reinstall with `--foreground-scripts`.");
1039
1328
  }
1040
1329
 
1041
- function enabledClientText({ codexAdapterEnabled = true, claudeAdapterEnabled = true } = {}) {
1042
- if (codexAdapterEnabled && claudeAdapterEnabled) return "Codex or Claude Code";
1043
- if (codexAdapterEnabled) return "Codex";
1044
- if (claudeAdapterEnabled) return "Claude Code";
1045
- return "";
1046
- }
1047
-
1048
- function statusCommandText({ codexAdapterEnabled = true, claudeAdapterEnabled = true } = {}) {
1330
+ function enabledClientText({
1331
+ codexAdapterEnabled = true,
1332
+ claudeAdapterEnabled = true,
1333
+ opencodeAdapterEnabled = true,
1334
+ } = {}) {
1335
+ const labels = [
1336
+ codexAdapterEnabled ? "Codex" : undefined,
1337
+ claudeAdapterEnabled ? "Claude Code" : undefined,
1338
+ opencodeAdapterEnabled ? "OpenCode" : undefined,
1339
+ ].filter(Boolean);
1340
+ if (labels.length < 2) return labels[0] ?? "";
1341
+ if (labels.length === 2) return `${labels[0]} or ${labels[1]}`;
1342
+ return `${labels.slice(0, -1).join(", ")}, or ${labels.at(-1)}`;
1343
+ }
1344
+
1345
+ function statusCommandText({
1346
+ codexAdapterEnabled = true,
1347
+ claudeAdapterEnabled = true,
1348
+ opencodeAdapterEnabled = true,
1349
+ } = {}) {
1049
1350
  const commands = ["`memorax-code status`"];
1050
1351
  if (codexAdapterEnabled) commands.push("`memorax-code-codex status`");
1051
1352
  if (claudeAdapterEnabled) commands.push("`memorax-code-claude status`");
1353
+ if (opencodeAdapterEnabled) commands.push("`memorax-code-opencode status`");
1052
1354
  if (commands.length === 1) return commands[0];
1053
1355
  if (commands.length === 2) return `${commands[0]} and ${commands[1]}`;
1054
1356
  return `${commands.slice(0, -1).join(", ")}, and ${commands.at(-1)}`;
@@ -1128,19 +1430,17 @@ function readMemoraxInstallStatus() {
1128
1430
  }
1129
1431
  }
1130
1432
 
1131
- function printUnavailableDiagnostics() {
1433
+ function printUnavailableDiagnostics({ codexSkipReason, claudeSkipReason, opencodeSkipReason } = {}) {
1132
1434
  logRed("MemoraX Code is not enabled for new client sessions.");
1133
- logRed("Check `memorax-code status`, `memorax-code-codex status`, and `memorax-code-claude status` for Backend and adapter details.");
1134
- logRed("If Codex or Claude Code is open, restart or refresh it after fixing the reported status.");
1135
- printCommonCommands();
1136
- }
1137
-
1138
- function printSkippedAdapterDiagnostics({ codexSkipReason, claudeSkipReason } = {}) {
1435
+ logRed("Check `memorax-code status`, `memorax-code-codex status`, `memorax-code-claude status`, and `memorax-code-opencode status` for Backend and adapter details.");
1436
+ logRed("If Codex, Claude Code, or OpenCode is open, restart or refresh it after fixing the reported status.");
1139
1437
  if (codexSkipReason) printCodexSkippedDiagnostics(codexSkipReason);
1140
1438
  if (claudeSkipReason) printClaudeSkippedDiagnostics(claudeSkipReason);
1439
+ if (opencodeSkipReason) printOpenCodeSkippedDiagnostics(opencodeSkipReason);
1141
1440
  printCommonCommands({
1142
1441
  codexAdapterEnabled: !codexSkipReason,
1143
1442
  claudeAdapterEnabled: !claudeSkipReason,
1443
+ opencodeAdapterEnabled: !opencodeSkipReason,
1144
1444
  });
1145
1445
  }
1146
1446
 
@@ -1156,10 +1456,15 @@ function printClaudeSkippedDiagnostics() {
1156
1456
  log("Run `memorax-code start` after installing Claude Code, then restart or refresh Claude Code.");
1157
1457
  }
1158
1458
 
1459
+ function printOpenCodeSkippedDiagnostics() {
1460
+ logRed("OpenCode adapter setup was skipped for this npm postinstall, so MemoraX Code left the OpenCode integration unchanged.");
1461
+ log("Run `memorax-code start --clients opencode` after installing OpenCode, then restart or refresh OpenCode.");
1462
+ }
1463
+
1159
1464
  function printFailureSuggestions() {
1160
1465
  logRed("Suggested recovery: run `memorax-code stop`, then `memorax-code start`, then `memorax-code status`.");
1161
1466
  logRed("If the Backend port is busy, stop the process using 127.0.0.1:8787 and retry `memorax-code start`.");
1162
- logRed("If client sessions still bypass MemoraX Code, restart or refresh Codex or Claude Code and verify the relevant adapter status.");
1467
+ logRed("If client sessions still bypass MemoraX Code, restart or refresh the affected client and verify the relevant adapter status.");
1163
1468
  printCommonCommands();
1164
1469
  }
1165
1470
 
@@ -1181,7 +1486,11 @@ function printLifecycleLockFailureSuggestions() {
1181
1486
  printCommonCommands();
1182
1487
  }
1183
1488
 
1184
- function printCommonCommands({ codexAdapterEnabled = true, claudeAdapterEnabled = true } = {}) {
1489
+ function printCommonCommands({
1490
+ codexAdapterEnabled = true,
1491
+ claudeAdapterEnabled = true,
1492
+ opencodeAdapterEnabled = true,
1493
+ } = {}) {
1185
1494
  log("Common commands:");
1186
1495
  log("- `memorax-code status`: check the local backend and adapter state.");
1187
1496
  log("- `memorax-cli status`: check required MemoraX configuration and effective memory switches.");
@@ -1189,9 +1498,14 @@ function printCommonCommands({ codexAdapterEnabled = true, claudeAdapterEnabled
1189
1498
  log("- `memorax-code stop`: stop the local memory backend and disable managed client integrations.");
1190
1499
  if (codexAdapterEnabled) log("- `memorax-code-codex sessions`: verify recent native Codex session registration.");
1191
1500
  if (claudeAdapterEnabled) log("- `memorax-code-claude sessions`: verify recent native Claude Code session registration.");
1501
+ if (opencodeAdapterEnabled) log("- `memorax-code-opencode doctor`: verify the managed OpenCode plugin, runtime evidence, and Backend health.");
1192
1502
  }
1193
1503
 
1194
- function memoraxCodeEnabled(statusResult, { codexAdapterRequired = true, claudeAdapterRequired = true } = {}) {
1504
+ function memoraxCodeEnabled(statusResult, {
1505
+ codexAdapterRequired = true,
1506
+ claudeAdapterRequired = true,
1507
+ opencodeAdapterRequired = true,
1508
+ } = {}) {
1195
1509
  const output = `${statusResult.stdout ?? ""}\n${statusResult.stderr ?? ""}`;
1196
1510
  const normalized = stripAnsi(output);
1197
1511
  const backendOk = /MemoraX Code Backend status:\s*Enabled\b/im.test(normalized)
@@ -1201,10 +1515,12 @@ function memoraxCodeEnabled(statusResult, { codexAdapterRequired = true, claudeA
1201
1515
  || /Backend:\s*(?:running|ok)\b/im.test(normalized);
1202
1516
  const codexAdapterOk = /Codex adapter:\s*ok\b/im.test(normalized);
1203
1517
  const claudeAdapterOk = /Claude adapter:\s*ok\b/im.test(normalized);
1518
+ const opencodeAdapterOk = /OpenCode adapter:\s*ok\b/im.test(normalized);
1204
1519
  return backendOk
1205
1520
  && serviceOk
1206
1521
  && (!codexAdapterRequired || codexAdapterOk)
1207
- && (!claudeAdapterRequired || claudeAdapterOk);
1522
+ && (!claudeAdapterRequired || claudeAdapterOk)
1523
+ && (!opencodeAdapterRequired || opencodeAdapterOk);
1208
1524
  }
1209
1525
 
1210
1526
  function log(message) {