oh-my-codex 0.16.3 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) hide show
  1. package/Cargo.lock +5 -5
  2. package/Cargo.toml +1 -1
  3. package/README.md +3 -3
  4. package/dist/catalog/__tests__/generator.test.js +2 -0
  5. package/dist/catalog/__tests__/generator.test.js.map +1 -1
  6. package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +9 -0
  7. package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -1
  8. package/dist/cli/__tests__/cleanup.test.js +27 -0
  9. package/dist/cli/__tests__/cleanup.test.js.map +1 -1
  10. package/dist/cli/__tests__/codex-plugin-layout.test.js +7 -5
  11. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  12. package/dist/cli/__tests__/doctor-warning-copy.test.js +175 -7
  13. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  14. package/dist/cli/__tests__/index.test.js +147 -12
  15. package/dist/cli/__tests__/index.test.js.map +1 -1
  16. package/dist/cli/__tests__/mcp-serve.test.js +4 -0
  17. package/dist/cli/__tests__/mcp-serve.test.js.map +1 -1
  18. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +2 -0
  19. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
  20. package/dist/cli/__tests__/ralph.test.js +47 -0
  21. package/dist/cli/__tests__/ralph.test.js.map +1 -1
  22. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +10 -5
  23. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -1
  24. package/dist/cli/__tests__/setup-install-mode.test.js +299 -27
  25. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  26. package/dist/cli/__tests__/setup-refresh.test.js +85 -3
  27. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  28. package/dist/cli/__tests__/setup-scope.test.js +1 -1
  29. package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
  30. package/dist/cli/__tests__/setup-skills-overwrite.test.js +2 -1
  31. package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
  32. package/dist/cli/__tests__/team.test.js +108 -0
  33. package/dist/cli/__tests__/team.test.js.map +1 -1
  34. package/dist/cli/__tests__/ultragoal.test.js +91 -0
  35. package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
  36. package/dist/cli/__tests__/uninstall.test.js +54 -8
  37. package/dist/cli/__tests__/uninstall.test.js.map +1 -1
  38. package/dist/cli/cleanup.d.ts.map +1 -1
  39. package/dist/cli/cleanup.js +8 -4
  40. package/dist/cli/cleanup.js.map +1 -1
  41. package/dist/cli/codex-feature-probe.d.ts +9 -0
  42. package/dist/cli/codex-feature-probe.d.ts.map +1 -0
  43. package/dist/cli/codex-feature-probe.js +28 -0
  44. package/dist/cli/codex-feature-probe.js.map +1 -0
  45. package/dist/cli/doctor.d.ts +1 -0
  46. package/dist/cli/doctor.d.ts.map +1 -1
  47. package/dist/cli/doctor.js +214 -23
  48. package/dist/cli/doctor.js.map +1 -1
  49. package/dist/cli/index.d.ts +17 -4
  50. package/dist/cli/index.d.ts.map +1 -1
  51. package/dist/cli/index.js +152 -24
  52. package/dist/cli/index.js.map +1 -1
  53. package/dist/cli/mcp-parity.js +8 -8
  54. package/dist/cli/mcp-parity.js.map +1 -1
  55. package/dist/cli/mcp-serve.d.ts.map +1 -1
  56. package/dist/cli/mcp-serve.js +4 -0
  57. package/dist/cli/mcp-serve.js.map +1 -1
  58. package/dist/cli/plugin-marketplace.d.ts +23 -0
  59. package/dist/cli/plugin-marketplace.d.ts.map +1 -1
  60. package/dist/cli/plugin-marketplace.js +203 -1
  61. package/dist/cli/plugin-marketplace.js.map +1 -1
  62. package/dist/cli/ralph.d.ts.map +1 -1
  63. package/dist/cli/ralph.js +21 -0
  64. package/dist/cli/ralph.js.map +1 -1
  65. package/dist/cli/setup-preferences.d.ts +4 -0
  66. package/dist/cli/setup-preferences.d.ts.map +1 -1
  67. package/dist/cli/setup-preferences.js +7 -0
  68. package/dist/cli/setup-preferences.js.map +1 -1
  69. package/dist/cli/setup.d.ts +5 -3
  70. package/dist/cli/setup.d.ts.map +1 -1
  71. package/dist/cli/setup.js +140 -51
  72. package/dist/cli/setup.js.map +1 -1
  73. package/dist/cli/ultragoal.d.ts +1 -1
  74. package/dist/cli/ultragoal.d.ts.map +1 -1
  75. package/dist/cli/ultragoal.js +70 -5
  76. package/dist/cli/ultragoal.js.map +1 -1
  77. package/dist/cli/uninstall.d.ts +2 -0
  78. package/dist/cli/uninstall.d.ts.map +1 -1
  79. package/dist/cli/uninstall.js +12 -3
  80. package/dist/cli/uninstall.js.map +1 -1
  81. package/dist/config/__tests__/codex-feature-flags.test.d.ts +2 -0
  82. package/dist/config/__tests__/codex-feature-flags.test.d.ts.map +1 -0
  83. package/dist/config/__tests__/codex-feature-flags.test.js +35 -0
  84. package/dist/config/__tests__/codex-feature-flags.test.js.map +1 -0
  85. package/dist/config/__tests__/codex-hooks.test.js +143 -9
  86. package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
  87. package/dist/config/__tests__/generator-idempotent.test.js +85 -9
  88. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  89. package/dist/config/__tests__/generator-notify.test.js +116 -11
  90. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  91. package/dist/config/__tests__/wiki-config-contract.test.js +6 -3
  92. package/dist/config/__tests__/wiki-config-contract.test.js.map +1 -1
  93. package/dist/config/codex-feature-flags.d.ts +21 -0
  94. package/dist/config/codex-feature-flags.d.ts.map +1 -0
  95. package/dist/config/codex-feature-flags.js +56 -0
  96. package/dist/config/codex-feature-flags.js.map +1 -0
  97. package/dist/config/codex-hooks.d.ts +14 -13
  98. package/dist/config/codex-hooks.d.ts.map +1 -1
  99. package/dist/config/codex-hooks.js +108 -8
  100. package/dist/config/codex-hooks.js.map +1 -1
  101. package/dist/config/generator.d.ts +15 -3
  102. package/dist/config/generator.d.ts.map +1 -1
  103. package/dist/config/generator.js +233 -129
  104. package/dist/config/generator.js.map +1 -1
  105. package/dist/config/omx-first-party-mcp.d.ts +3 -1
  106. package/dist/config/omx-first-party-mcp.d.ts.map +1 -1
  107. package/dist/config/omx-first-party-mcp.js +9 -2
  108. package/dist/config/omx-first-party-mcp.js.map +1 -1
  109. package/dist/hooks/__tests__/design-skill.test.d.ts +2 -0
  110. package/dist/hooks/__tests__/design-skill.test.d.ts.map +1 -0
  111. package/dist/hooks/__tests__/design-skill.test.js +55 -0
  112. package/dist/hooks/__tests__/design-skill.test.js.map +1 -0
  113. package/dist/hooks/__tests__/keyword-detector.test.js +92 -2
  114. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  115. package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js +125 -1
  116. package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js.map +1 -1
  117. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +265 -0
  118. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  119. package/dist/hooks/__tests__/skill-catalog-hygiene.test.d.ts +2 -0
  120. package/dist/hooks/__tests__/skill-catalog-hygiene.test.d.ts.map +1 -0
  121. package/dist/hooks/__tests__/skill-catalog-hygiene.test.js +84 -0
  122. package/dist/hooks/__tests__/skill-catalog-hygiene.test.js.map +1 -0
  123. package/dist/hooks/__tests__/skill-guidance-contract.test.js +41 -0
  124. package/dist/hooks/__tests__/skill-guidance-contract.test.js.map +1 -1
  125. package/dist/hooks/agents-overlay.js +2 -2
  126. package/dist/hooks/agents-overlay.js.map +1 -1
  127. package/dist/hooks/keyword-detector.d.ts +1 -0
  128. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  129. package/dist/hooks/keyword-detector.js +12 -6
  130. package/dist/hooks/keyword-detector.js.map +1 -1
  131. package/dist/hooks/keyword-registry.d.ts.map +1 -1
  132. package/dist/hooks/keyword-registry.js +2 -0
  133. package/dist/hooks/keyword-registry.js.map +1 -1
  134. package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
  135. package/dist/hooks/prompt-guidance-contract.js +47 -2
  136. package/dist/hooks/prompt-guidance-contract.js.map +1 -1
  137. package/dist/hud/__tests__/state.test.js +164 -0
  138. package/dist/hud/__tests__/state.test.js.map +1 -1
  139. package/dist/hud/state.d.ts.map +1 -1
  140. package/dist/hud/state.js +4 -5
  141. package/dist/hud/state.js.map +1 -1
  142. package/dist/mcp/__tests__/bootstrap.test.js +3 -0
  143. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  144. package/dist/mcp/__tests__/hermes-bridge.test.d.ts +2 -0
  145. package/dist/mcp/__tests__/hermes-bridge.test.d.ts.map +1 -0
  146. package/dist/mcp/__tests__/hermes-bridge.test.js +374 -0
  147. package/dist/mcp/__tests__/hermes-bridge.test.js.map +1 -0
  148. package/dist/mcp/__tests__/state-paths.test.js +155 -11
  149. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  150. package/dist/mcp/__tests__/state-server.test.js +166 -0
  151. package/dist/mcp/__tests__/state-server.test.js.map +1 -1
  152. package/dist/mcp/bootstrap.d.ts +1 -1
  153. package/dist/mcp/bootstrap.d.ts.map +1 -1
  154. package/dist/mcp/bootstrap.js +2 -0
  155. package/dist/mcp/bootstrap.js.map +1 -1
  156. package/dist/mcp/hermes-bridge.d.ts +81 -0
  157. package/dist/mcp/hermes-bridge.d.ts.map +1 -0
  158. package/dist/mcp/hermes-bridge.js +400 -0
  159. package/dist/mcp/hermes-bridge.js.map +1 -0
  160. package/dist/mcp/hermes-server.d.ts +269 -0
  161. package/dist/mcp/hermes-server.d.ts.map +1 -0
  162. package/dist/mcp/hermes-server.js +121 -0
  163. package/dist/mcp/hermes-server.js.map +1 -0
  164. package/dist/mcp/state-paths.d.ts.map +1 -1
  165. package/dist/mcp/state-paths.js +64 -11
  166. package/dist/mcp/state-paths.js.map +1 -1
  167. package/dist/modes/__tests__/base-session-scope.test.js +22 -0
  168. package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
  169. package/dist/modes/__tests__/base-tmux-pane.test.js +88 -27
  170. package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
  171. package/dist/modes/base.d.ts.map +1 -1
  172. package/dist/modes/base.js +5 -0
  173. package/dist/modes/base.js.map +1 -1
  174. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.d.ts +2 -0
  175. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.d.ts.map +1 -0
  176. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js +316 -0
  177. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js.map +1 -0
  178. package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.d.ts +2 -0
  179. package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.d.ts.map +1 -0
  180. package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js +481 -0
  181. package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js.map +1 -0
  182. package/dist/planning/__tests__/artifacts.test.js +533 -4
  183. package/dist/planning/__tests__/artifacts.test.js.map +1 -1
  184. package/dist/planning/__tests__/context-pack-status.test.js +524 -0
  185. package/dist/planning/__tests__/context-pack-status.test.js.map +1 -1
  186. package/dist/planning/__tests__/markdown-structure.test.d.ts +2 -0
  187. package/dist/planning/__tests__/markdown-structure.test.d.ts.map +1 -0
  188. package/dist/planning/__tests__/markdown-structure.test.js +459 -0
  189. package/dist/planning/__tests__/markdown-structure.test.js.map +1 -0
  190. package/dist/planning/__tests__/ready-context-pack-role-refs.test.js +523 -1
  191. package/dist/planning/__tests__/ready-context-pack-role-refs.test.js.map +1 -1
  192. package/dist/planning/artifacts.d.ts +1 -1
  193. package/dist/planning/artifacts.d.ts.map +1 -1
  194. package/dist/planning/artifacts.js +227 -28
  195. package/dist/planning/artifacts.js.map +1 -1
  196. package/dist/planning/context-pack-status.d.ts +25 -0
  197. package/dist/planning/context-pack-status.d.ts.map +1 -1
  198. package/dist/planning/context-pack-status.js +272 -31
  199. package/dist/planning/context-pack-status.js.map +1 -1
  200. package/dist/planning/markdown-structure.d.ts +20 -0
  201. package/dist/planning/markdown-structure.d.ts.map +1 -0
  202. package/dist/planning/markdown-structure.js +137 -0
  203. package/dist/planning/markdown-structure.js.map +1 -0
  204. package/dist/ralph/__tests__/completion-audit.test.d.ts +2 -0
  205. package/dist/ralph/__tests__/completion-audit.test.d.ts.map +1 -0
  206. package/dist/ralph/__tests__/completion-audit.test.js +121 -0
  207. package/dist/ralph/__tests__/completion-audit.test.js.map +1 -0
  208. package/dist/ralph/completion-audit.d.ts +8 -0
  209. package/dist/ralph/completion-audit.d.ts.map +1 -0
  210. package/dist/ralph/completion-audit.js +99 -0
  211. package/dist/ralph/completion-audit.js.map +1 -0
  212. package/dist/scripts/__tests__/codex-native-hook.test.js +407 -15
  213. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  214. package/dist/scripts/__tests__/notify-dispatcher.test.d.ts +2 -0
  215. package/dist/scripts/__tests__/notify-dispatcher.test.d.ts.map +1 -0
  216. package/dist/scripts/__tests__/notify-dispatcher.test.js +126 -0
  217. package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -0
  218. package/dist/scripts/codex-native-hook.d.ts +1 -0
  219. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  220. package/dist/scripts/codex-native-hook.js +177 -71
  221. package/dist/scripts/codex-native-hook.js.map +1 -1
  222. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
  223. package/dist/scripts/codex-native-pre-post.js +4 -2
  224. package/dist/scripts/codex-native-pre-post.js.map +1 -1
  225. package/dist/scripts/notify-dispatcher.js +30 -1
  226. package/dist/scripts/notify-dispatcher.js.map +1 -1
  227. package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
  228. package/dist/scripts/notify-hook/tmux-injection.js +91 -2
  229. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  230. package/dist/scripts/notify-hook.js +3 -1
  231. package/dist/scripts/notify-hook.js.map +1 -1
  232. package/dist/state/__tests__/workflow-transition.test.js +102 -27
  233. package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
  234. package/dist/state/mode-state-context.d.ts +2 -0
  235. package/dist/state/mode-state-context.d.ts.map +1 -1
  236. package/dist/state/mode-state-context.js +21 -0
  237. package/dist/state/mode-state-context.js.map +1 -1
  238. package/dist/state/operations.d.ts.map +1 -1
  239. package/dist/state/operations.js +9 -3
  240. package/dist/state/operations.js.map +1 -1
  241. package/dist/state/skill-active.d.ts +7 -0
  242. package/dist/state/skill-active.d.ts.map +1 -1
  243. package/dist/state/skill-active.js +25 -8
  244. package/dist/state/skill-active.js.map +1 -1
  245. package/dist/state/workflow-transition-reconcile.d.ts +1 -0
  246. package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
  247. package/dist/state/workflow-transition-reconcile.js +22 -15
  248. package/dist/state/workflow-transition-reconcile.js.map +1 -1
  249. package/dist/state/workflow-transition.js +3 -3
  250. package/dist/state/workflow-transition.js.map +1 -1
  251. package/dist/team/__tests__/approved-execution.test.js +39 -0
  252. package/dist/team/__tests__/approved-execution.test.js.map +1 -1
  253. package/dist/team/__tests__/runtime.test.js +5 -0
  254. package/dist/team/__tests__/runtime.test.js.map +1 -1
  255. package/dist/team/__tests__/scaling.test.js +497 -2
  256. package/dist/team/__tests__/scaling.test.js.map +1 -1
  257. package/dist/team/__tests__/state-root.test.js +1 -1
  258. package/dist/team/__tests__/state-root.test.js.map +1 -1
  259. package/dist/team/__tests__/worker-bootstrap.test.js +8 -0
  260. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  261. package/dist/team/approved-execution.d.ts.map +1 -1
  262. package/dist/team/approved-execution.js +3 -0
  263. package/dist/team/approved-execution.js.map +1 -1
  264. package/dist/team/scaling.d.ts.map +1 -1
  265. package/dist/team/scaling.js +43 -0
  266. package/dist/team/scaling.js.map +1 -1
  267. package/dist/team/state-root.d.ts.map +1 -1
  268. package/dist/team/state-root.js +4 -0
  269. package/dist/team/state-root.js.map +1 -1
  270. package/dist/team/state.d.ts.map +1 -1
  271. package/dist/team/state.js +2 -6
  272. package/dist/team/state.js.map +1 -1
  273. package/dist/ultragoal/__tests__/artifacts.test.js +245 -1
  274. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
  275. package/dist/ultragoal/__tests__/docs-contract.test.js +21 -0
  276. package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
  277. package/dist/ultragoal/artifacts.d.ts +52 -2
  278. package/dist/ultragoal/artifacts.d.ts.map +1 -1
  279. package/dist/ultragoal/artifacts.js +301 -15
  280. package/dist/ultragoal/artifacts.js.map +1 -1
  281. package/dist/utils/__tests__/paths.test.js +31 -1
  282. package/dist/utils/__tests__/paths.test.js.map +1 -1
  283. package/dist/utils/paths.d.ts +6 -0
  284. package/dist/utils/paths.d.ts.map +1 -1
  285. package/dist/utils/paths.js +18 -0
  286. package/dist/utils/paths.js.map +1 -1
  287. package/dist/wiki/lifecycle.js +4 -4
  288. package/dist/wiki/lifecycle.js.map +1 -1
  289. package/package.json +1 -1
  290. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  291. package/plugins/oh-my-codex/.mcp.json +13 -5
  292. package/plugins/oh-my-codex/skills/analyze/SKILL.md +0 -2
  293. package/plugins/oh-my-codex/skills/autopilot/SKILL.md +2 -2
  294. package/plugins/oh-my-codex/skills/code-review/SKILL.md +1 -3
  295. package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +5 -7
  296. package/plugins/oh-my-codex/skills/design/SKILL.md +180 -0
  297. package/plugins/oh-my-codex/skills/doctor/SKILL.md +2 -2
  298. package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +3 -3
  299. package/plugins/oh-my-codex/skills/pipeline/SKILL.md +3 -3
  300. package/plugins/oh-my-codex/skills/plan/SKILL.md +3 -6
  301. package/plugins/oh-my-codex/skills/ralph/SKILL.md +9 -10
  302. package/plugins/oh-my-codex/skills/skill/SKILL.md +2 -1
  303. package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +36 -3
  304. package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +175 -64
  305. package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +8 -8
  306. package/plugins/oh-my-codex/skills/visual-ralph/SKILL.md +2 -2
  307. package/plugins/oh-my-codex/skills/wiki/SKILL.md +13 -13
  308. package/skills/analyze/SKILL.md +0 -2
  309. package/skills/ask-claude/SKILL.md +5 -3
  310. package/skills/ask-gemini/SKILL.md +5 -3
  311. package/skills/autopilot/SKILL.md +2 -2
  312. package/skills/code-review/SKILL.md +1 -3
  313. package/skills/deep-interview/SKILL.md +5 -7
  314. package/skills/design/SKILL.md +180 -0
  315. package/skills/doctor/SKILL.md +2 -2
  316. package/skills/ecomode/SKILL.md +105 -1
  317. package/skills/frontend-ui-ux/SKILL.md +6 -24
  318. package/skills/git-master/SKILL.md +2 -4
  319. package/skills/omx-setup/SKILL.md +3 -3
  320. package/skills/pipeline/SKILL.md +3 -3
  321. package/skills/plan/SKILL.md +3 -6
  322. package/skills/ralph/SKILL.md +9 -10
  323. package/skills/skill/SKILL.md +2 -1
  324. package/skills/swarm/SKILL.md +5 -3
  325. package/skills/tdd/SKILL.md +95 -1
  326. package/skills/ultragoal/SKILL.md +36 -3
  327. package/skills/ultraqa/SKILL.md +175 -64
  328. package/skills/ultrawork/SKILL.md +8 -8
  329. package/skills/visual-ralph/SKILL.md +2 -2
  330. package/skills/web-clone/SKILL.md +348 -1
  331. package/skills/wiki/SKILL.md +13 -13
  332. package/src/scripts/__tests__/codex-native-hook.test.ts +437 -14
  333. package/src/scripts/__tests__/notify-dispatcher.test.ts +153 -0
  334. package/src/scripts/codex-native-hook.ts +205 -61
  335. package/src/scripts/codex-native-pre-post.ts +4 -1
  336. package/src/scripts/notify-dispatcher.ts +40 -1
  337. package/src/scripts/notify-hook/tmux-injection.ts +110 -3
  338. package/src/scripts/notify-hook.ts +3 -1
  339. package/templates/catalog-manifest.json +9 -2
package/dist/cli/setup.js CHANGED
@@ -9,8 +9,8 @@ import { spawnSync } from "child_process";
9
9
  import { createInterface } from "readline/promises";
10
10
  import { homedir } from "os";
11
11
  import { codexHome, codexConfigPath, codexPromptsDir, codexAgentsDir, userSkillsDir, omxStateDir, detectLegacySkillRootOverlap, omxPlansDir, omxLogsDir, } from "../utils/paths.js";
12
- import { buildMergedConfig, getRootModelName, getRootTomlArray, hasLegacyOmxTeamRunTable, isOmxManagedNotifyCommand, stripExistingOmxBlocks, stripExistingSharedMcpRegistryBlock, stripOmxEnvSettings, stripOmxFeatureFlags, stripOmxSeededBehavioralDefaults, upsertPluginModeRuntimeFeatureFlags, upsertManagedCodexHookTrustState, stripManagedCodexHookTrustState, OMX_PLUGIN_DEVELOPER_INSTRUCTIONS, } from "../config/generator.js";
13
- import { mergeManagedCodexHooksConfig } from "../config/codex-hooks.js";
12
+ import { buildMergedConfig, getRootModelName, getRootTomlArray, hasLegacyOmxTeamRunTable, isOmxManagedNotifyCommand, sanitizePreviousNotifyCommand, stripExistingOmxBlocks, stripExistingSharedMcpRegistryBlock, mergeSharedMcpRegistryBlock, stripOmxEnvSettings, stripOmxFeatureFlags, stripOmxSeededBehavioralDefaults, upsertPluginModeRuntimeFeatureFlags, upsertManagedCodexHookTrustState, stripManagedCodexHookTrustState, OMX_PLUGIN_DEVELOPER_INSTRUCTIONS, } from "../config/generator.js";
13
+ import { buildManagedCodexNativeHookWindowsShimContent, buildManagedCodexNativeHookWindowsShimPath, mergeManagedCodexHooksConfig, } from "../config/codex-hooks.js";
14
14
  import { getLegacyUnifiedMcpRegistryCandidate, getUnifiedMcpRegistryCandidates, loadUnifiedMcpRegistry, planClaudeCodeMcpSettingsSync, } from "../config/mcp-registry.js";
15
15
  import { generateAgentToml } from "../agents/native-config.js";
16
16
  import { AGENT_DEFINITIONS } from "../agents/definitions.js";
@@ -22,8 +22,9 @@ import { tryReadCatalogManifest } from "../catalog/reader.js";
22
22
  import { DEFAULT_FRONTIER_MODEL } from "../config/models.js";
23
23
  import { addGeneratedAgentsMarker, hasOmxManagedAgentsSections, isOmxGeneratedAgentsMd, upsertManagedAgentsBlock, } from "../utils/agents-md.js";
24
24
  import { DEFAULT_HUD_CONFIG } from "../hud/types.js";
25
- import { SETUP_INSTALL_MODES, SETUP_SCOPES, getSetupScopeFilePath, readPersistedSetupPreferences, } from "./setup-preferences.js";
26
- import { OMX_LOCAL_MARKETPLACE_NAME, resolvePackagedOmxMarketplace, upsertLocalOmxMarketplaceRegistration, } from "./plugin-marketplace.js";
25
+ import { SETUP_INSTALL_MODES, SETUP_MCP_MODES, SETUP_SCOPES, getSetupScopeFilePath, readPersistedSetupPreferences, } from "./setup-preferences.js";
26
+ import { OMX_LOCAL_MARKETPLACE_NAME, OMX_PLUGIN_NAME, materializePackagedOmxPluginCache, resolvePackagedOmxMarketplace, upsertLocalOmxMarketplaceRegistration, upsertLocalOmxPluginEnablement, upsertLocalOmxPluginMcpServerEnablement, } from "./plugin-marketplace.js";
27
+ import { resolveCodexHookFeatureFlagForCli } from "./codex-feature-probe.js";
27
28
  async function resolveStatusLinePresetForSetup(projectRoot, options) {
28
29
  if (options.force) {
29
30
  return DEFAULT_HUD_CONFIG.statusLine.preset;
@@ -44,7 +45,7 @@ async function resolveStatusLinePresetForSetup(projectRoot, options) {
44
45
  return undefined;
45
46
  }
46
47
  import { resolveAgentsModelTableContext, upsertAgentsModelTable, } from "../utils/agents-model-table.js";
47
- export { SETUP_INSTALL_MODES, SETUP_SCOPES };
48
+ export { SETUP_INSTALL_MODES, SETUP_MCP_MODES, SETUP_SCOPES };
48
49
  const PROJECT_GITIGNORE_ENTRIES = [
49
50
  ".omx/",
50
51
  ".codex/*",
@@ -58,6 +59,7 @@ const PROJECT_GITIGNORE_ENTRIES = [
58
59
  ];
59
60
  const LEGACY_PROJECT_GITIGNORE_ENTRIES = [".codex/"];
60
61
  const SETUP_ONLY_INSTALLABLE_SKILLS = new Set(["wiki"]);
62
+ const DEFAULT_SETUP_MCP_MODE = "none";
61
63
  const HARD_DEPRECATED_SKILL_NAMES = new Set(["web-clone"]);
62
64
  function isCatalogInstallableStatus(status) {
63
65
  return status === "active" || status === "internal";
@@ -354,6 +356,7 @@ function formatPersistedSetupPreferenceSummary(preferences) {
354
356
  return [
355
357
  `scope=${preferences.scope ?? "not recorded"}`,
356
358
  `installMode=${preferences.installMode ?? "not recorded"}`,
359
+ `mcpMode=${preferences.mcpMode ?? "not recorded"}`,
357
360
  ].join(", ");
358
361
  }
359
362
  async function promptForPersistedSetupReview(preferences) {
@@ -582,7 +585,7 @@ async function discoverOmxPluginCacheDirs(cacheRoot = join(codexHome(), "plugins
582
585
  async function discoverOmxPluginCacheDir(cacheRoot = join(codexHome(), "plugins", "cache")) {
583
586
  return (await discoverOmxPluginCacheDirs(cacheRoot))[0] ?? null;
584
587
  }
585
- async function refreshOmxPluginDiscoveryCache(pkgRoot, options) {
588
+ async function refreshOmxPluginDiscoveryCache(pkgRoot, options, codexHomeDir = codexHome()) {
586
589
  const packagedMarketplace = await resolvePackagedOmxMarketplace(pkgRoot);
587
590
  if (!packagedMarketplace) {
588
591
  return { status: "unavailable", staleDirs: [] };
@@ -590,7 +593,7 @@ async function refreshOmxPluginDiscoveryCache(pkgRoot, options) {
590
593
  const [pkg, expectedSkillNames, cachedDirs] = await Promise.all([
591
594
  readFile(join(pkgRoot, "package.json"), "utf-8").then((raw) => JSON.parse(raw)),
592
595
  listChildDirectoryNames(join(packagedMarketplace.pluginRoot, "skills")),
593
- discoverOmxPluginCacheDirs(),
596
+ discoverOmxPluginCacheDirs(join(codexHomeDir, "plugins", "cache")),
594
597
  ]);
595
598
  const expectedVersion = typeof pkg.version === "string" ? pkg.version : null;
596
599
  const staleDirs = [];
@@ -628,6 +631,17 @@ async function refreshOmxPluginDiscoveryCache(pkgRoot, options) {
628
631
  staleDirs,
629
632
  };
630
633
  }
634
+ function resolveSetupMcpMode(scope, requestedMcpMode, persistedReviewDecision, persistedPreferences) {
635
+ if (requestedMcpMode) {
636
+ return { mcpMode: requestedMcpMode, source: "cli" };
637
+ }
638
+ if (persistedPreferences?.mcpMode &&
639
+ persistedReviewDecision === "keep" &&
640
+ persistedPreferences.scope === scope) {
641
+ return { mcpMode: persistedPreferences.mcpMode, source: "persisted" };
642
+ }
643
+ return { mcpMode: DEFAULT_SETUP_MCP_MODE, source: "default" };
644
+ }
631
645
  async function resolveSetupInstallMode(projectRoot, scope, requestedInstallMode, installModePrompt, persistedReviewDecision = "keep", persistedPreferences) {
632
646
  if (requestedInstallMode) {
633
647
  return { installMode: requestedInstallMode, source: "cli" };
@@ -888,7 +902,7 @@ function insertRootTomlKey(config, line) {
888
902
  const after = lines.slice(firstTableIndex);
889
903
  return [...before, line, "", ...after].join("\n") + "\n";
890
904
  }
891
- async function ensurePluginMarketplaceRegistration(configPath, pkgRoot, backupContext, summary, options) {
905
+ async function ensurePluginMarketplaceRegistration(configPath, pkgRoot, mcpMode, backupContext, summary, options) {
892
906
  const packagedMarketplace = await resolvePackagedOmxMarketplace(pkgRoot);
893
907
  if (!packagedMarketplace) {
894
908
  summary.skipped += 1;
@@ -897,7 +911,7 @@ async function ensurePluginMarketplaceRegistration(configPath, pkgRoot, backupCo
897
911
  const existingConfig = existsSync(configPath)
898
912
  ? await readFile(configPath, "utf-8")
899
913
  : "";
900
- const nextConfig = upsertLocalOmxMarketplaceRegistration(existingConfig, pkgRoot);
914
+ const nextConfig = upsertLocalOmxMarketplaceRegistration(upsertLocalOmxPluginMcpServerEnablement(upsertLocalOmxPluginEnablement(existingConfig), mcpMode === "compat"), pkgRoot);
901
915
  const destinationExists = existsSync(configPath);
902
916
  if (nextConfig === existingConfig) {
903
917
  summary.unchanged += 1;
@@ -916,11 +930,11 @@ async function ensurePluginMarketplaceRegistration(configPath, pkgRoot, backupCo
916
930
  }
917
931
  return "updated";
918
932
  }
919
- async function applyPluginModeHooksConfig(configPath, hooksPath, pkgRoot, backupContext, summary, options) {
933
+ async function applyPluginModeHooksConfig(configPath, hooksPath, pkgRoot, codexHomeDir, backupContext, summary, options) {
920
934
  const existingConfig = existsSync(configPath)
921
935
  ? await readFile(configPath, "utf-8")
922
936
  : "";
923
- const nextConfig = upsertManagedCodexHookTrustState(upsertPluginModeRuntimeFeatureFlags(stripManagedCodexHookTrustState(existingConfig)), pkgRoot, hooksPath);
937
+ const nextConfig = upsertManagedCodexHookTrustState(upsertPluginModeRuntimeFeatureFlags(stripManagedCodexHookTrustState(existingConfig), options.codexHookFeatureFlag), pkgRoot, hooksPath, { platform: process.platform, codexHomeDir });
924
938
  if (nextConfig !== existingConfig) {
925
939
  if (await ensureBackup(configPath, existsSync(configPath), backupContext, options)) {
926
940
  summary.backedUp += 1;
@@ -937,8 +951,9 @@ async function applyPluginModeHooksConfig(configPath, hooksPath, pkgRoot, backup
937
951
  const existingHooksContent = existsSync(hooksPath)
938
952
  ? await readFile(hooksPath, "utf-8")
939
953
  : null;
940
- const hooksConfig = mergeManagedCodexHooksConfig(existingHooksContent, pkgRoot, hooksPath);
954
+ const hooksConfig = mergeManagedCodexHooksConfig(existingHooksContent, pkgRoot, hooksPath, { platform: process.platform, codexHomeDir });
941
955
  await syncManagedContent(hooksConfig, hooksPath, summary, backupContext, options, `native hooks ${hooksPath}`);
956
+ await syncManagedWindowsNativeHookShim(codexHomeDir, pkgRoot, summary, backupContext, options);
942
957
  if (options.verbose) {
943
958
  console.log(` ${options.dryRun ? "would configure" : "configured"} plugin-mode native hooks and runtime feature flags at ${hooksPath}`);
944
959
  }
@@ -1028,7 +1043,7 @@ async function cleanupPluginModeLegacyAgentsMd(agentsMdPath, backupContext, opti
1028
1043
  return true;
1029
1044
  }
1030
1045
  export async function setup(options = {}) {
1031
- const { force = false, dryRun = false, installMode: requestedInstallMode, scope: requestedScope, verbose = false, setupScopePrompt, persistedSetupReviewPrompt, installModePrompt, modelUpgradePrompt, pluginAgentsMdPrompt, pluginDeveloperInstructionsPrompt, pluginDeveloperInstructionsOverwritePrompt, } = options;
1046
+ const { force = false, dryRun = false, installMode: requestedInstallMode, mcpMode: requestedMcpMode, scope: requestedScope, verbose = false, setupScopePrompt, persistedSetupReviewPrompt, installModePrompt, modelUpgradePrompt, pluginAgentsMdPrompt, pluginDeveloperInstructionsPrompt, pluginDeveloperInstructionsOverwritePrompt, } = options;
1032
1047
  const pkgRoot = getPackageRoot();
1033
1048
  const projectRoot = process.cwd();
1034
1049
  const persistedPreferences = await readPersistedSetupPreferences(projectRoot, { warnOnLegacyScope: true });
@@ -1039,8 +1054,12 @@ export async function setup(options = {}) {
1039
1054
  Boolean(persistedPreferences?.installMode) &&
1040
1055
  (!persistedPreferences?.scope ||
1041
1056
  persistedPreferences.scope === effectiveScopeForInstallMode);
1057
+ const wouldUsePersistedMcpMode = !requestedMcpMode &&
1058
+ Boolean(persistedPreferences?.mcpMode) &&
1059
+ (!persistedPreferences?.scope ||
1060
+ persistedPreferences.scope === effectiveScopeForInstallMode);
1042
1061
  const shouldReviewPersistedSetup = hasPersistedSetupPreferences(persistedPreferences) &&
1043
- (wouldUsePersistedScope || wouldUsePersistedInstallMode) &&
1062
+ (wouldUsePersistedScope || wouldUsePersistedInstallMode || wouldUsePersistedMcpMode) &&
1044
1063
  (typeof persistedSetupReviewPrompt === "function" ||
1045
1064
  (process.stdin.isTTY && process.stdout.isTTY));
1046
1065
  if (shouldReviewPersistedSetup) {
@@ -1051,6 +1070,7 @@ export async function setup(options = {}) {
1051
1070
  }
1052
1071
  const resolvedScope = await resolveSetupScope(projectRoot, requestedScope, persistedReviewDecision, persistedPreferences, setupScopePrompt);
1053
1072
  const resolvedInstallMode = await resolveSetupInstallMode(projectRoot, resolvedScope.scope, requestedInstallMode, installModePrompt, persistedReviewDecision, persistedPreferences);
1073
+ const resolvedMcpMode = resolveSetupMcpMode(resolvedScope.scope, requestedMcpMode, persistedReviewDecision, persistedPreferences);
1054
1074
  const scopeDirs = resolveScopeDirectories(resolvedScope.scope, projectRoot);
1055
1075
  const scopeSourceMessage = resolvedScope.source === "persisted" ? " (from .omx/setup-scope.json)" : "";
1056
1076
  const backupContext = getBackupContext(resolvedScope.scope, projectRoot);
@@ -1077,6 +1097,10 @@ export async function setup(options = {}) {
1077
1097
  : "";
1078
1098
  console.log(`Using setup install mode: ${resolvedInstallMode.installMode}${installModeSourceMessage}\n`);
1079
1099
  }
1100
+ const mcpModeSourceMessage = resolvedMcpMode.source === "persisted"
1101
+ ? " (from .omx/setup-scope.json)"
1102
+ : "";
1103
+ console.log(`Using setup MCP mode: ${resolvedMcpMode.mcpMode}${mcpModeSourceMessage}\n`);
1080
1104
  // Step 1: Ensure directories exist
1081
1105
  console.log("[1/8] Creating directories...");
1082
1106
  const dirs = isPluginInstallMode
@@ -1102,16 +1126,15 @@ export async function setup(options = {}) {
1102
1126
  if (verbose)
1103
1127
  console.log(` mkdir ${dir}`);
1104
1128
  }
1105
- const setupPreferencesToPersist = resolvedInstallMode &&
1106
- (resolvedScope.scope === "user" ||
1107
- resolvedInstallMode.installMode === "plugin")
1108
- ? {
1109
- scope: resolvedScope.scope,
1110
- installMode: resolvedInstallMode.installMode,
1111
- }
1112
- : {
1113
- scope: resolvedScope.scope,
1114
- };
1129
+ const setupPreferencesToPersist = {
1130
+ scope: resolvedScope.scope,
1131
+ mcpMode: resolvedMcpMode.mcpMode,
1132
+ ...(resolvedInstallMode &&
1133
+ (resolvedScope.scope === "user" ||
1134
+ resolvedInstallMode.installMode === "plugin")
1135
+ ? { installMode: resolvedInstallMode.installMode }
1136
+ : {}),
1137
+ };
1115
1138
  await persistSetupPreferences(projectRoot, setupPreferencesToPersist, {
1116
1139
  dryRun,
1117
1140
  verbose,
@@ -1217,6 +1240,35 @@ export async function setup(options = {}) {
1217
1240
  console.log("[5/8] Updating config.toml...");
1218
1241
  let resolvedConfig = "";
1219
1242
  let omxManagesTui = false;
1243
+ const codexHookFeatureFlag = resolveCodexHookFeatureFlagForCli({
1244
+ codexFeaturesProbe: options.codexFeaturesProbe,
1245
+ codexVersionProbe: options.codexVersionProbe,
1246
+ });
1247
+ if (verbose) {
1248
+ console.log(` Native Codex hook feature flag: [features].${codexHookFeatureFlag}`);
1249
+ }
1250
+ const shouldSyncSharedMcpRegistry = resolvedMcpMode.mcpMode === "compat";
1251
+ const registryCandidates = getUnifiedMcpRegistryCandidates();
1252
+ const defaultRegistryCandidates = registryCandidates.slice(0, 1);
1253
+ const sharedMcpRegistry = shouldSyncSharedMcpRegistry
1254
+ ? await loadUnifiedMcpRegistry({
1255
+ candidates: options.mcpRegistryCandidates ?? defaultRegistryCandidates,
1256
+ })
1257
+ : { servers: [], warnings: [] };
1258
+ const legacyRegistryCandidate = getLegacyUnifiedMcpRegistryCandidate();
1259
+ if (shouldSyncSharedMcpRegistry &&
1260
+ !options.mcpRegistryCandidates &&
1261
+ !sharedMcpRegistry.sourcePath &&
1262
+ existsSync(legacyRegistryCandidate) &&
1263
+ !existsSync(defaultRegistryCandidates[0])) {
1264
+ console.log(` warning: legacy shared MCP registry detected at ${legacyRegistryCandidate} but ignored by default; move or copy it to ${defaultRegistryCandidates[0]} and rerun setup with --mcp compat if you still want setup to sync those servers`);
1265
+ }
1266
+ if (verbose && sharedMcpRegistry.sourcePath) {
1267
+ console.log(` shared MCP registry: ${sharedMcpRegistry.sourcePath} (${sharedMcpRegistry.servers.length} servers)`);
1268
+ }
1269
+ for (const warning of sharedMcpRegistry.warnings) {
1270
+ console.log(` warning: ${warning}`);
1271
+ }
1220
1272
  if (isPluginInstallMode) {
1221
1273
  const configCleaned = await cleanupPluginModeLegacyConfig(scopeDirs.codexConfigFile, backupContext, { dryRun, verbose });
1222
1274
  if (configCleaned)
@@ -1224,8 +1276,8 @@ export async function setup(options = {}) {
1224
1276
  console.log(configCleaned
1225
1277
  ? ` ${dryRun ? "Would clean" : "Cleaned"} legacy OMX config entries for plugin mode.\n`
1226
1278
  : " Config refresh skipped; no legacy OMX config entries found.\n");
1227
- await applyPluginModeHooksConfig(scopeDirs.codexConfigFile, scopeDirs.codexHooksFile, pkgRoot, backupContext, summary.config, { dryRun, verbose });
1228
- const pluginMarketplaceResult = await ensurePluginMarketplaceRegistration(scopeDirs.codexConfigFile, pkgRoot, backupContext, summary.config, { dryRun, verbose });
1279
+ await applyPluginModeHooksConfig(scopeDirs.codexConfigFile, scopeDirs.codexHooksFile, pkgRoot, scopeDirs.codexHomeDir, backupContext, summary.config, { dryRun, verbose, codexHookFeatureFlag });
1280
+ const pluginMarketplaceResult = await ensurePluginMarketplaceRegistration(scopeDirs.codexConfigFile, pkgRoot, resolvedMcpMode.mcpMode, backupContext, summary.config, { dryRun, verbose });
1229
1281
  if (pluginMarketplaceResult === "unavailable") {
1230
1282
  console.log(` warning: packaged ${OMX_LOCAL_MARKETPLACE_NAME} Codex plugin marketplace metadata not found; /skills plugin discovery was not registered.`);
1231
1283
  }
@@ -1235,16 +1287,30 @@ export async function setup(options = {}) {
1235
1287
  else {
1236
1288
  console.log(` Local Codex plugin marketplace ${OMX_LOCAL_MARKETPLACE_NAME} already registered (${pkgRoot}).`);
1237
1289
  }
1290
+ const packagedMarketplace = await resolvePackagedOmxMarketplace(pkgRoot);
1238
1291
  const pluginCacheRefresh = await refreshOmxPluginDiscoveryCache(pkgRoot, {
1239
1292
  dryRun,
1240
1293
  verbose,
1241
- });
1294
+ }, scopeDirs.codexHomeDir);
1242
1295
  if (pluginCacheRefresh.status === "refreshed") {
1243
1296
  console.log(` ${dryRun ? "Would invalidate" : "Invalidated"} ${pluginCacheRefresh.staleDirs.length} stale Codex plugin discovery cache entr${pluginCacheRefresh.staleDirs.length === 1 ? "y" : "ies"} so plugin skills refresh from the packaged manifest.`);
1244
1297
  }
1245
1298
  else if (pluginCacheRefresh.status === "unchanged") {
1246
1299
  console.log(" Codex plugin discovery cache already matches packaged plugin metadata.");
1247
1300
  }
1301
+ const pluginCacheMaterialize = await materializePackagedOmxPluginCache(scopeDirs.codexHomeDir, packagedMarketplace, { dryRun });
1302
+ if (pluginCacheMaterialize.status === "materialized") {
1303
+ console.log(` ${dryRun ? "Would install" : "Installed"} local Codex plugin cache for ${OMX_LOCAL_MARKETPLACE_NAME}/${OMX_PLUGIN_NAME} at ${pluginCacheMaterialize.cacheDir}.`);
1304
+ }
1305
+ else if (pluginCacheMaterialize.status === "unchanged") {
1306
+ console.log(" Local Codex plugin cache already exposes packaged OMX skills.");
1307
+ }
1308
+ if (shouldSyncSharedMcpRegistry) {
1309
+ resolvedConfig = await syncSharedMcpRegistryIntoConfig(scopeDirs.codexConfigFile, sharedMcpRegistry, summary.config, backupContext, { dryRun, verbose });
1310
+ if (resolvedScope.scope === "user") {
1311
+ await syncClaudeCodeMcpSettings(sharedMcpRegistry, summary.config, backupContext, { dryRun, verbose });
1312
+ }
1313
+ }
1248
1314
  resolvedConfig = existsSync(scopeDirs.codexConfigFile)
1249
1315
  ? await readFile(scopeDirs.codexConfigFile, "utf-8")
1250
1316
  : "";
@@ -1270,46 +1336,30 @@ export async function setup(options = {}) {
1270
1336
  }
1271
1337
  }
1272
1338
  else {
1273
- const registryCandidates = getUnifiedMcpRegistryCandidates();
1274
- const defaultRegistryCandidates = registryCandidates.slice(0, 1);
1275
- const legacyRegistryCandidate = getLegacyUnifiedMcpRegistryCandidate();
1276
- const sharedMcpRegistry = await loadUnifiedMcpRegistry({
1277
- candidates: options.mcpRegistryCandidates ?? defaultRegistryCandidates,
1278
- });
1279
- if (!options.mcpRegistryCandidates &&
1280
- !sharedMcpRegistry.sourcePath &&
1281
- existsSync(legacyRegistryCandidate) &&
1282
- !existsSync(defaultRegistryCandidates[0])) {
1283
- console.log(` warning: legacy shared MCP registry detected at ${legacyRegistryCandidate} but ignored by default; move it to ${defaultRegistryCandidates[0]} if you still want setup to sync those servers`);
1284
- }
1285
- if (verbose && sharedMcpRegistry.sourcePath) {
1286
- console.log(` shared MCP registry: ${sharedMcpRegistry.sourcePath} (${sharedMcpRegistry.servers.length} servers)`);
1287
- }
1288
- for (const warning of sharedMcpRegistry.warnings) {
1289
- console.log(` warning: ${warning}`);
1290
- }
1291
1339
  const statusLinePreset = await resolveStatusLinePresetForSetup(projectRoot, { force });
1292
- const managedConfig = await updateManagedConfig(scopeDirs.codexConfigFile, scopeDirs.codexHooksFile, pkgRoot, sharedMcpRegistry, resolvedScope.scope, scopeDirs.codexHomeDir, summary.config, backupContext, {
1340
+ const managedConfig = await updateManagedConfig(scopeDirs.codexConfigFile, scopeDirs.codexHooksFile, pkgRoot, sharedMcpRegistry, resolvedMcpMode.mcpMode, resolvedScope.scope, scopeDirs.codexHomeDir, summary.config, backupContext, {
1293
1341
  dryRun,
1294
1342
  modelUpgradePrompt,
1295
1343
  verbose,
1296
1344
  statusLinePreset,
1297
1345
  forceStatusLinePreset: force,
1346
+ codexHookFeatureFlag,
1298
1347
  });
1299
1348
  resolvedConfig = managedConfig.finalConfig;
1300
1349
  omxManagesTui = managedConfig.omxManagesTui;
1301
1350
  if (managedConfig.repairedLegacyTeamRunTable) {
1302
1351
  console.log(" Removed retired [mcp_servers.omx_team_run] config during refresh.");
1303
1352
  }
1304
- if (resolvedScope.scope === "user") {
1353
+ if (shouldSyncSharedMcpRegistry && resolvedScope.scope === "user") {
1305
1354
  await syncClaudeCodeMcpSettings(sharedMcpRegistry, summary.config, backupContext, { dryRun, verbose });
1306
1355
  }
1307
1356
  console.log(` Config refresh complete (${scopeDirs.codexConfigFile}).\n`);
1308
1357
  const existingHooksContent = existsSync(scopeDirs.codexHooksFile)
1309
1358
  ? await readFile(scopeDirs.codexHooksFile, "utf-8")
1310
1359
  : null;
1311
- const hooksConfig = mergeManagedCodexHooksConfig(existingHooksContent, pkgRoot);
1360
+ const hooksConfig = mergeManagedCodexHooksConfig(existingHooksContent, pkgRoot, scopeDirs.codexHooksFile, { platform: process.platform, codexHomeDir: scopeDirs.codexHomeDir });
1312
1361
  await syncManagedContent(hooksConfig, scopeDirs.codexHooksFile, summary.config, backupContext, { dryRun, verbose }, `native hooks ${scopeDirs.codexHooksFile}`);
1362
+ await syncManagedWindowsNativeHookShim(scopeDirs.codexHomeDir, pkgRoot, summary.config, backupContext, { dryRun, verbose });
1313
1363
  console.log(` Native Codex hooks refresh complete (${scopeDirs.codexHooksFile}).\n`);
1314
1364
  }
1315
1365
  // Step 5.5: Verify team CLI interop surface is available.
@@ -1616,6 +1666,13 @@ async function syncManagedContent(content, dstPath, summary, backupContext, opti
1616
1666
  console.log(` ${options.dryRun ? "would update" : "updated"} ${verboseLabel}`);
1617
1667
  }
1618
1668
  }
1669
+ async function syncManagedWindowsNativeHookShim(codexHomeDir, pkgRoot, summary, backupContext, options) {
1670
+ if (process.platform !== "win32")
1671
+ return;
1672
+ const shimPath = buildManagedCodexNativeHookWindowsShimPath(codexHomeDir);
1673
+ const shimContent = buildManagedCodexNativeHookWindowsShimContent(pkgRoot);
1674
+ await syncManagedContent(shimContent, shimPath, summary, backupContext, options, `native hook Windows shim ${shimPath}`);
1675
+ }
1619
1676
  async function syncManagedAgentsContent(content, dstPath, summary, backupContext, options) {
1620
1677
  const destinationExists = existsSync(dstPath);
1621
1678
  let existing = "";
@@ -2059,13 +2116,17 @@ async function buildNotifyMergePlan(existingConfig, pkgRoot, codexHomeDir, scope
2059
2116
  const previousNotify = metadata.previousNotify;
2060
2117
  if (Array.isArray(previousNotify) &&
2061
2118
  previousNotify.every((item) => typeof item === "string")) {
2119
+ const sanitizedPreviousNotify = sanitizePreviousNotifyCommand(previousNotify, pkgRoot);
2120
+ if (!sanitizedPreviousNotify) {
2121
+ return { notifyCommand: omxNotify };
2122
+ }
2062
2123
  return {
2063
2124
  notifyCommand: dispatcherNotify,
2064
2125
  metadataPath,
2065
2126
  metadata: {
2066
2127
  managedBy: "oh-my-codex",
2067
2128
  version: 1,
2068
- previousNotify,
2129
+ previousNotify: sanitizedPreviousNotify,
2069
2130
  omxNotify,
2070
2131
  dispatcherNotify,
2071
2132
  },
@@ -2083,13 +2144,13 @@ async function buildNotifyMergePlan(existingConfig, pkgRoot, codexHomeDir, scope
2083
2144
  metadata: {
2084
2145
  managedBy: "oh-my-codex",
2085
2146
  version: 1,
2086
- previousNotify: existingNotify,
2147
+ previousNotify: sanitizePreviousNotifyCommand(existingNotify, pkgRoot),
2087
2148
  omxNotify,
2088
2149
  dispatcherNotify,
2089
2150
  },
2090
2151
  };
2091
2152
  }
2092
- async function updateManagedConfig(configPath, hooksPath, pkgRoot, sharedMcpRegistry, scope, codexHomeDir, summary, backupContext, options) {
2153
+ async function updateManagedConfig(configPath, hooksPath, pkgRoot, sharedMcpRegistry, mcpMode, scope, codexHomeDir, summary, backupContext, options) {
2093
2154
  const existing = existsSync(configPath)
2094
2155
  ? await readFile(configPath, "utf-8")
2095
2156
  : "";
@@ -2113,6 +2174,9 @@ async function updateManagedConfig(configPath, hooksPath, pkgRoot, sharedMcpRegi
2113
2174
  const finalConfig = buildMergedConfig(existing, pkgRoot, {
2114
2175
  includeTui: omxManagesTui,
2115
2176
  codexHooksFile: hooksPath,
2177
+ codexHomeDir,
2178
+ hookCommandPlatform: process.platform,
2179
+ codexHookFeatureFlag: options.codexHookFeatureFlag,
2116
2180
  modelOverride,
2117
2181
  sharedMcpServers: sharedMcpRegistry.servers,
2118
2182
  sharedMcpRegistrySource: sharedMcpRegistry.sourcePath,
@@ -2120,6 +2184,7 @@ async function updateManagedConfig(configPath, hooksPath, pkgRoot, sharedMcpRegi
2120
2184
  statusLinePreset: options.statusLinePreset,
2121
2185
  forceStatusLinePreset: options.forceStatusLinePreset,
2122
2186
  notifyCommand: notifyPlan.notifyCommand,
2187
+ includeFirstPartyMcp: mcpMode === "compat",
2123
2188
  });
2124
2189
  const changed = existing !== finalConfig;
2125
2190
  if (!changed) {
@@ -2156,6 +2221,30 @@ async function updateManagedConfig(configPath, hooksPath, pkgRoot, sharedMcpRegi
2156
2221
  repairedLegacyTeamRunTable: hadLegacyTeamRunTable && !hasLegacyOmxTeamRunTable(finalConfig),
2157
2222
  };
2158
2223
  }
2224
+ async function syncSharedMcpRegistryIntoConfig(configPath, sharedMcpRegistry, summary, backupContext, options) {
2225
+ if (sharedMcpRegistry.servers.length === 0) {
2226
+ return existsSync(configPath) ? await readFile(configPath, "utf-8") : "";
2227
+ }
2228
+ const existing = existsSync(configPath)
2229
+ ? await readFile(configPath, "utf-8")
2230
+ : "";
2231
+ const finalConfig = mergeSharedMcpRegistryBlock(existing, sharedMcpRegistry.servers, sharedMcpRegistry.sourcePath);
2232
+ if (existing === finalConfig) {
2233
+ summary.unchanged += 1;
2234
+ return finalConfig;
2235
+ }
2236
+ if (await ensureBackup(configPath, existsSync(configPath), backupContext, options)) {
2237
+ summary.backedUp += 1;
2238
+ }
2239
+ if (!options.dryRun) {
2240
+ await writeFile(configPath, finalConfig);
2241
+ }
2242
+ summary.updated += 1;
2243
+ if (options.verbose) {
2244
+ console.log(` ${options.dryRun ? "would sync" : "synced"} shared MCP registry servers into ${configPath}`);
2245
+ }
2246
+ return finalConfig;
2247
+ }
2159
2248
  function getClaudeCodeSettingsPath(homeDir = homedir()) {
2160
2249
  return join(homeDir, ".claude", "settings.json");
2161
2250
  }