commandmate 0.24.0 → 0.25.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 (240) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +307 -307
  3. package/.next/app-path-routes-manifest.json +23 -23
  4. package/.next/build-manifest.json +5 -5
  5. package/.next/prerender-manifest.json +12 -12
  6. package/.next/react-loadable-manifest.json +3 -3
  7. package/.next/required-server-files.json +1 -1
  8. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  9. package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
  10. package/.next/server/app/api/app/update-check/route.js +1 -1
  11. package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
  12. package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
  13. package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
  14. package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
  15. package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
  16. package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
  17. package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
  18. package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
  19. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  20. package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  21. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  22. package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
  23. package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
  24. package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
  25. package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
  26. package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
  27. package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
  28. package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
  29. package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
  30. package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
  31. package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
  32. package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
  33. package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
  38. package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
  41. package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
  46. package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
  47. package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
  48. package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
  49. package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
  50. package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
  51. package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
  52. package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
  53. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  54. package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
  55. package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
  56. package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  57. package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
  58. package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
  59. package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
  60. package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
  61. package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
  62. package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
  63. package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
  64. package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
  65. package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
  66. package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
  67. package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
  68. package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
  69. package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
  70. package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
  71. package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
  72. package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
  73. package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
  74. package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
  75. package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
  76. package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
  77. package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
  78. package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
  79. package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
  80. package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
  81. package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
  82. package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
  83. package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
  84. package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
  85. package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
  86. package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
  87. package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
  88. package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
  89. package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
  90. package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
  91. package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
  92. package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
  93. package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
  94. package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
  95. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
  96. package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
  97. package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
  98. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
  99. package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
  100. package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
  101. package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
  102. package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
  103. package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
  104. package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
  105. package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
  106. package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
  107. package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
  108. package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
  109. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
  110. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
  111. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
  112. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
  113. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
  114. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
  115. package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
  116. package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
  117. package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
  118. package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
  119. package/.next/server/app/api/worktrees/[id]/start-polling/route_client-reference-manifest.js +1 -1
  120. package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
  121. package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
  122. package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
  123. package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
  124. package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
  125. package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
  126. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
  127. package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
  128. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
  129. package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
  130. package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
  131. package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
  132. package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
  133. package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
  134. package/.next/server/app/chat/page.js +2 -2
  135. package/.next/server/app/chat/page.js.nft.json +1 -1
  136. package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
  137. package/.next/server/app/login/page.js +2 -2
  138. package/.next/server/app/login/page.js.nft.json +1 -1
  139. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  140. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  141. package/.next/server/app/more/page.js +2 -2
  142. package/.next/server/app/more/page.js.nft.json +1 -1
  143. package/.next/server/app/more/page_client-reference-manifest.js +1 -1
  144. package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
  145. package/.next/server/app/page.js +1 -1
  146. package/.next/server/app/page.js.nft.json +1 -1
  147. package/.next/server/app/page_client-reference-manifest.js +1 -1
  148. package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
  149. package/.next/server/app/repositories/page.js +2 -2
  150. package/.next/server/app/repositories/page.js.nft.json +1 -1
  151. package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
  152. package/.next/server/app/review/page.js +1 -1
  153. package/.next/server/app/review/page.js.nft.json +1 -1
  154. package/.next/server/app/review/page_client-reference-manifest.js +1 -1
  155. package/.next/server/app/sessions/page.js +1 -1
  156. package/.next/server/app/sessions/page.js.nft.json +1 -1
  157. package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  158. package/.next/server/app/skills/[skillId]/page.js +2 -2
  159. package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
  160. package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
  161. package/.next/server/app/skills/installed/page.js +2 -2
  162. package/.next/server/app/skills/installed/page.js.nft.json +1 -1
  163. package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
  164. package/.next/server/app/skills/page.js +2 -2
  165. package/.next/server/app/skills/page.js.nft.json +1 -1
  166. package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  167. package/.next/server/app/worktrees/[id]/files/[...path]/page.js +2 -2
  168. package/.next/server/app/worktrees/[id]/files/[...path]/page.js.nft.json +1 -1
  169. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
  170. package/.next/server/app/worktrees/[id]/page.js +6 -6
  171. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
  172. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
  173. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
  174. package/.next/server/app-paths-manifest.json +23 -23
  175. package/.next/server/chunks/2119.js +1 -1
  176. package/.next/server/chunks/2404.js +1 -1
  177. package/.next/server/chunks/2445.js +1 -1
  178. package/.next/server/chunks/3346.js +1 -1
  179. package/.next/server/chunks/5164.js +1 -1
  180. package/.next/server/chunks/5571.js +1 -1
  181. package/.next/server/chunks/5959.js +3 -3
  182. package/.next/server/chunks/6130.js +1 -1
  183. package/.next/server/chunks/6285.js +1 -1
  184. package/.next/server/chunks/848.js +1 -1
  185. package/.next/server/chunks/8730.js +1 -0
  186. package/.next/server/chunks/880.js +1 -1
  187. package/.next/server/chunks/9328.js +1 -1
  188. package/.next/server/middleware-build-manifest.js +1 -1
  189. package/.next/server/middleware-manifest.json +5 -5
  190. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  191. package/.next/server/pages/500.html +1 -1
  192. package/.next/server/pages-manifest.json +1 -1
  193. package/.next/server/server-reference-manifest.json +1 -1
  194. package/.next/static/chunks/2053-dfac2d49227cc942.js +1 -0
  195. package/.next/static/chunks/3898-ef488bfa804507d9.js +1 -0
  196. package/.next/static/chunks/5229-35f9acab97a553c5.js +1 -0
  197. package/.next/static/chunks/{6381-18a6a02a94d00d76.js → 6381-51f9c4a128aadc0b.js} +1 -1
  198. package/.next/static/chunks/{9599-d29d2f8eeaf7c249.js → 8649-f551b0010dba4986.js} +1 -1
  199. package/.next/static/chunks/9263.f2034ec525abcf72.js +1 -0
  200. package/.next/static/chunks/app/chat/page-439b35c9cb90dbe0.js +1 -0
  201. package/.next/static/chunks/app/login/page-eefd515d8c37e5ee.js +1 -0
  202. package/.next/static/chunks/app/more/page-889b7546a8a553dc.js +1 -0
  203. package/.next/static/chunks/app/page-a8d04ac0e3e4c9fc.js +1 -0
  204. package/.next/static/chunks/app/repositories/page-f3c4d8839b1ca203.js +1 -0
  205. package/.next/static/chunks/app/review/page-6dc88649fe88ac16.js +1 -0
  206. package/.next/static/chunks/app/sessions/page-2c9ed9e969097688.js +1 -0
  207. package/.next/static/chunks/app/skills/[skillId]/page-19beef6121c4c982.js +1 -0
  208. package/.next/static/chunks/app/skills/installed/page-d5b9cef6d21fabda.js +1 -0
  209. package/.next/static/chunks/app/skills/page-06ef637e07dd9377.js +1 -0
  210. package/.next/static/chunks/app/worktrees/[id]/files/[...path]/{page-9ddcb224594f620f.js → page-5fed3984fafcd910.js} +1 -1
  211. package/.next/static/chunks/app/worktrees/[id]/page-207c69540fd856ef.js +1 -0
  212. package/.next/static/chunks/{webpack-3534d858912a6c92.js → webpack-9d892a9ff07c289d.js} +1 -1
  213. package/.next/static/css/e865c4979a41aa03.css +1 -0
  214. package/.next/trace +12 -12
  215. package/README.md +96 -45
  216. package/dist/server/src/config/activity-bar-config.js +5 -1
  217. package/dist/server/src/lib/auto-yes-poller.js +40 -4
  218. package/dist/server/src/lib/cli-tools/codex.js +58 -29
  219. package/dist/server/src/lib/detection/cli-patterns.js +148 -6
  220. package/dist/server/src/lib/detection/status-detector.js +28 -0
  221. package/package.json +1 -1
  222. package/.next/server/chunks/3451.js +0 -1
  223. package/.next/static/chunks/2053-52d3c82014e1cd54.js +0 -1
  224. package/.next/static/chunks/5229-0610b4e3288e777d.js +0 -1
  225. package/.next/static/chunks/744-3ad06d8c8ca482fc.js +0 -1
  226. package/.next/static/chunks/9263.5259f73f89220d64.js +0 -1
  227. package/.next/static/chunks/app/chat/page-15d13fc024d78f5d.js +0 -1
  228. package/.next/static/chunks/app/login/page-0247a3fb569bb22b.js +0 -1
  229. package/.next/static/chunks/app/more/page-b8ba537baeac8d5b.js +0 -1
  230. package/.next/static/chunks/app/page-afc64708362f31e5.js +0 -1
  231. package/.next/static/chunks/app/repositories/page-3469dacb6be7842f.js +0 -1
  232. package/.next/static/chunks/app/review/page-2d9cb7e068f8f35a.js +0 -1
  233. package/.next/static/chunks/app/sessions/page-7470c2bfd89e0df9.js +0 -1
  234. package/.next/static/chunks/app/skills/[skillId]/page-5e24481162f7ea78.js +0 -1
  235. package/.next/static/chunks/app/skills/installed/page-efd2d710a27f9735.js +0 -1
  236. package/.next/static/chunks/app/skills/page-0498adfc6e48684b.js +0 -1
  237. package/.next/static/chunks/app/worktrees/[id]/page-e611d30e47989e5d.js +0 -1
  238. package/.next/static/css/3ac44cfc082d02ad.css +0 -1
  239. /package/.next/static/{smu4mnL7qMf8w38n9dQJE → ehkNc5xDMDkXlua08Bwq0}/_buildManifest.js +0 -0
  240. /package/.next/static/{smu4mnL7qMf8w38n9dQJE → ehkNc5xDMDkXlua08Bwq0}/_ssgManifest.js +0 -0
package/README.md CHANGED
@@ -12,12 +12,12 @@
12
12
  **[commandmate website →](https://kewton.github.io/CommandMate/)**
13
13
 
14
14
  <p align="center">
15
- <img src="./docs/images/demo-desktop.gif" width="600" alt="CommandMate Desktop Demo" />
15
+ <img src="./docs/images/demo-desktop.gif" width="600" alt="A task contract is sent, the verification gates run, and the exit code returns RESULT passed" />
16
16
  </p>
17
17
 
18
- > **Orchestrate your agent CLIs, not your terminal tabs.**
18
+ > **From vibe coding to Vibe Engineering.**
19
19
 
20
- CommandMate is a local control plane for agent CLIs.
20
+ Vibe Engineering the AI does the building; the system, not your expertise, guarantees the engineering.
21
21
 
22
22
  ```bash
23
23
  npx commandmate@latest
@@ -27,11 +27,11 @@ npx commandmate@latest
27
27
 
28
28
  ---
29
29
 
30
- CommandMate adds orchestration and visibility on top of your existing agent CLIs.
31
- It does not replace tmux, Git worktrees, or your terminal. It makes them easier to manage at scale.
30
+ CommandMate adds the machinery a contract before the work, verification gates after it, Skills that carry the method — on top of the agent CLIs you already use.
31
+ It does not replace tmux, Git worktrees, your terminal, or your agent CLI. It puts a frame around them, so the work arrives verified instead of merely finished.
32
32
 
33
33
  <p align="center">
34
- <img src="./docs/images/demo-mobile.gif" width="300" alt="CommandMate Mobile Demo" />
34
+ <img src="./docs/images/demo-mobile.gif" width="300" alt="A waiting agent reaches you, and the prompt is answered from a phone" />
35
35
  </p>
36
36
 
37
37
  Works on desktop and mobile — monitor and steer sessions from any browser, including your phone.
@@ -44,8 +44,13 @@ If this is the kind of AI development workflow you want, [give the repo a star](
44
44
 
45
45
  | Feature | What it does | Why it matters |
46
46
  |---------|-------------|----------------|
47
+ | **Task Contract** | Declare the goal, the changeable scope and the gates before the work starts, then `send --contract` hands them to the agent | The agent works to a written definition of done instead of guessing at one |
48
+ | **Verification Gates** | Gates declared in `.commandmate/verify.yaml` run through `verify` / `wait --verify` and return exit `0` / `20` / `21` | "Done" is what a verification run returned, not what the agent said |
49
+ | **Evidence & Metrics** | The built-in work-evidence and scope gates, plus `verify history`, `task show` and `report metrics` | Commits, gate logs and numbers are left behind for the next decision |
50
+ | **Skills Catalog** | Install and update official Skills per worktree, from the web UI or `commandmate skill` | The method is installed for the agent to read, not kept in someone's head |
51
+ | **Never miss a waiting agent** | A waiting agent shows up as a badge, a toast, the tab title, the PWA app badge and a push notification | You find out the moment an agent needs you, even away from the desk |
47
52
  | **Git Worktree Sessions** | One session per worktree, parallel execution | Multiple issues progress simultaneously without interference |
48
- | **Multi-Agent Support** | Choose Claude Code, Codex, Gemini, or local models per issue | Pick the right agent for each task |
53
+ | **Multi-Agent Support** | Choose Claude Code, Codex, Gemini CLI, Copilot, OpenCode, Antigravity or local models per worktree | Pick the right agent for each task |
49
54
  | **Auto Yes Mode** | Agent runs without stopping for confirmations | Optional unattended mode for trusted workflows — review the Security section before enabling |
50
55
  | **Web UI (Desktop & Mobile)** | Full session control from any browser | Monitor and steer from your desk or your phone |
51
56
  | **File Viewer & Markdown Editor** | Browse and edit worktree files in the browser | Review changes and update AI instructions without opening an IDE |
@@ -111,12 +116,16 @@ development machine or phone will already have.
111
116
  flowchart LR
112
117
  A["Browser / Phone"] -->|HTTP| B["CommandMate Server"]
113
118
  B --> C["Session Manager"]
119
+ G["Task Contract\n.commandmate/tasks/*.yaml"] --> C
114
120
  C -->|"spawn / attach"| D["tmux sessions\n(per worktree)"]
115
- D --> E["Claude Code CLI"]
121
+ D --> E["Agent CLI"]
116
122
  C <-->|"read / write"| F[("Local DB\n& State")]
123
+ E --> H["Verification Gates\n.commandmate/verify.yaml"]
124
+ H -->|"exit 0 / 20 / 21"| B
117
125
  ```
118
126
 
119
127
  Each Git worktree gets its own tmux session, so multiple tasks run in parallel without interference.
128
+ The contract goes in before the session starts; the gates run after it stops, and their exit code is the verdict.
120
129
 
121
130
  ---
122
131
 
@@ -405,55 +414,92 @@ npm start
405
414
  ---
406
415
 
407
416
  <details>
408
- <summary><strong>Comparison</strong></summary>
409
-
410
- | Feature | CommandMate | Remote Control (Official) | Happy Coder | claude-squad | Omnara |
411
- |---------|:-----------:|:------------------------:|:-----------:|:------------:|:------:|
412
- | Auto Yes Mode | Yes | No | No | Yes (TUI only) | No |
413
- | Git Worktree Management | Yes | No | No | Yes (TUI only) | No |
414
- | Parallel Sessions | Yes | **No (1 only)** | Yes | Yes | No |
415
- | Mobile Web UI | Yes | Yes (claude.ai) | Yes | **No** | Yes |
416
- | File Viewer | Yes | No | No | No | No |
417
- | Markdown Editor | Yes | No | No | No | No |
418
- | Screenshot Instructions | Yes | No | No | Not possible | No |
419
- | Scheduled Execution | Yes | No | No | No | No |
420
- | Survives Laptop Close | Yes (daemon) | **No (terminal must stay open)** | Yes | Yes | Yes |
421
- | Token Authentication | Yes | N/A (Anthropic account) | N/A (app) | No | N/A (cloud) |
422
- | Free / OSS | Yes | Requires Pro/Max | Free + Paid | Yes | $20/mo |
423
- | Runs 100% Locally | Yes | Via Anthropic API | Server-routed | Yes | Cloud fallback |
417
+ <summary><strong>With / Without CommandMate</strong></summary>
418
+
419
+ The comparison that matters is not against other products; it is against the way of working.
420
+
421
+ | Dimension | Vibe coding | Vibe Engineering with CommandMate |
422
+ |---|---|---|
423
+ | What "done" means | The agent says it's done | A verification run says so — exit 0 / 20 / 21 |
424
+ | Scope of change | Whatever the agent touched | Declared in the contract, enforced by the scope gate |
425
+ | Method | In someone's head | Installed as Skills from the Catalog (`cmate-task-contract`, `cmate-verify`, …) |
426
+ | Evidence | A chat transcript | Commits, gate logs, `verify history`, `report metrics` |
427
+ | Parallel work | Terminal tabs | One worktree and one contract per task |
428
+ | When it stops | You notice, eventually | Waiting is surfaced: badge, toast, tab title, push |
429
+ | Which agent | Locked to one | Claude Code, Codex, Gemini CLI, Copilot, OpenCode, Antigravity, local models |
424
430
 
425
431
  </details>
426
432
 
427
433
  ---
428
434
 
429
- ## Optional Workflow Layer
435
+ ## Vibe Engineering workflow
430
436
 
431
437
  <a id="issue-driven-development"></a>
432
438
 
433
- If your team wants more structure, CommandMate can also help you standardize
434
- issue refinement, design review, planning, implementation, and acceptance checks.
435
- These workflows build on top of the same CLI sessions and worktrees. They are optional, not required.
439
+ We do not make the AI smarter. We make the software-engineering ability its user needed into a system.
440
+ That system is three things you can hand to any agent: the method, as installed Skills; the contract,
441
+ declared before the work; the gates, which decide afterwards whether the work is done.
442
+
443
+ ```
444
+ Requirement → Contract → Agent runs (any CLI, per worktree) → Verified result
445
+ ```
446
+
447
+ ### 1. Install the method as Skills
436
448
 
437
- CommandMate is built for developers who spend less time editing files and more time defining issues, reviewing direction, and accepting outcomes from coding agents. The commands below turn that workflow into a repeatable process.
449
+ Skills come from the official Catalog
450
+ ([Kewton/commandmate-skills](https://github.com/Kewton/commandmate-skills)) and install into the
451
+ worktree you choose — from the web UI (`/skills`, or the Skills pane of a worktree) or from the CLI.
438
452
 
453
+ ```bash
454
+ commandmate skill list
455
+ commandmate skill install cmate-task-contract --worktree <worktree-id> --version <version> --yes
439
456
  ```
440
- Define Issue → Refine with AI → Review Direction → Generate Plan → Agent Executes
457
+
458
+ | Skill | What it covers |
459
+ |-------|----------------|
460
+ | `cmate-issue-authoring` | Turns a feature description into a set of implementable issues |
461
+ | `cmate-issue-refinement` | Refines a vague issue into an implementable specification, read-only |
462
+ | `cmate-task-contract` | Drafts `.commandmate/tasks/<name>.yaml` from an issue: goal, scope, gates |
463
+ | `cmate-verify` | Declares the gates in `.commandmate/verify.yaml` and runs them for a real exit code |
464
+ | `cmate-verify-advisor` | Proposes gate improvements from the verification history |
465
+ | `cmate-worker-development` | The six steps a worker follows: read, investigate, plan, implement, verify, evidence |
466
+ | `cmate-acceptance-test` | Checks the issue's acceptance criteria and returns Go / Conditional Go / No-Go |
467
+ | `cmate-orchestrate` | Plans several issues in parallel, dispatches them with contracts, judges by exit code |
468
+
469
+ The Catalog also publishes `cmate-repository-analysis`, `cmate-orchestrate-monitor`,
470
+ `cmate-worktree-setup` and `cmate-worktree-cleanup`. See the
471
+ [Skills guide](./docs/user-guide/skills.md) for the support matrix, the install roots, and the
472
+ rollback story.
473
+
474
+ ### 2. Declare the contract, then let the gates judge
475
+
476
+ ```bash
477
+ # .commandmate/tasks/issue-123.yaml declares goal, scope.allow / scope.deny and the gates to run
478
+ commandmate send <worktree-id> --contract .commandmate/tasks/issue-123.yaml
479
+ commandmate wait <worktree-id> --verify
441
480
  ```
442
481
 
443
- | Step | Command | What happens |
444
- |------|---------|-------------|
445
- | Refine the issue | `/issue-enhance` | AI asks clarifying questions and fills in missing details |
446
- | Review the issue | `/multi-stage-issue-review` | Multi-stage review (consistency, impact scope) with automated fixes |
447
- | Review the design | `/multi-stage-design-review` | 4-stage review (general → consistency → impact → security) |
448
- | Plan the work | `/work-plan` | Generates a task breakdown with dependencies |
449
- | Implement via TDD | `/tdd-impl` | Red-Green-Refactor cycle, automated |
450
- | Verify acceptance | `/acceptance-test` | Validates all acceptance criteria from the issue |
451
- | Create the PR | `/create-pr` | Auto-generates title, description, and labels |
452
- | Dev (full) | `/pm-auto-dev` | TDD implementation → acceptance test → refactoring → progress report |
453
- | Issue → Dev (full) | `/pm-auto-issue2dev` | Issue review → design review → work plan → TDD → acceptance test → refactoring → progress report |
454
- | Design → Dev (full) | `/pm-auto-design2dev` | Design review → work plan → TDD → acceptance test → refactoring → progress report |
455
-
456
- For details, see the [issues](https://github.com/Kewton/CommandMate/issues), [dev reports](./dev-reports/issue/), and [workflow examples](./docs/en/user-guide/workflow-examples.md) in the CommandMate repository.
482
+ `--contract` supplies the message, so you do not pass one yourself. `wait --verify` runs the gates
483
+ once the agent stops and returns the verdict as its exit code: **0** everything passed, **20** a gate
484
+ failed, **21** the work-evidence gate found neither a commit nor an uncommitted change.
485
+
486
+ The contract format is specified in [Task Contract](./docs/design/task-contract.md), the gate format
487
+ in [Verification gates](./docs/design/verification-config.md) both specifications are written in
488
+ Japanese, but the YAML they specify is the same on either side.
489
+
490
+ ### Read next
491
+
492
+ | Document | What it gives you |
493
+ |----------|-------------------|
494
+ | [Concept](./docs/en/concept.md) | The Vision, the Mission, and how each implementation item maps to a feature |
495
+ | [Tutorial](./docs/en/user-guide/tutorial.md) | Fork a sample repository and run one task through contract and verification in about fifteen minutes |
496
+ | [Product Highlights](./docs/en/features/product-highlights.md) | A feature-by-feature tour of the product |
497
+ | [CLI Operations Guide](./docs/en/user-guide/cli-operations-guide.md) | Every agent-facing command, in depth |
498
+
499
+ > **Developing CommandMate itself?** The `/work-plan`, `/pm-auto-dev` and other slash commands under
500
+ > `.claude/commands` belong to **this repository only** — they are not installed into yours, and the
501
+ > portable equivalents are the Catalog Skills above. See the
502
+ > [Commands guide](./docs/en/user-guide/commands-guide.md).
457
503
 
458
504
  ---
459
505
 
@@ -462,9 +508,14 @@ For details, see the [issues](https://github.com/Kewton/CommandMate/issues), [de
462
508
  | Document | Description |
463
509
  |----------|-------------|
464
510
  | [CLI Setup Guide](./docs/en/user-guide/cli-setup-guide.md) | Installation and initial setup |
511
+ | [Tutorial](./docs/en/user-guide/tutorial.md) | Fork a sample repository and go from contract to verified result in about fifteen minutes |
465
512
  | [Web App Guide](./docs/en/user-guide/webapp-guide.md) | Basic web app operations |
466
513
  | [Quick Start](./docs/en/user-guide/quick-start.md) | Using Claude Code commands |
467
- | [Concept](./docs/en/concept.md) | Vision and problems solved |
514
+ | [CLI Operations Guide](./docs/en/user-guide/cli-operations-guide.md) | Driving sessions from the CLI: execution contracts, verification gates, Skills, agent instances |
515
+ | [Concept](./docs/en/concept.md) | The canonical Vision, Mission and core principle, and how each implementation item maps to a feature |
516
+ | [Product Highlights](./docs/en/features/product-highlights.md) | A feature-by-feature tour of the product |
517
+ | [Skills Guide](./docs/en/user-guide/skills.md) | Installing official Catalog Skills into a worktree |
518
+ | [Agent Event Hooks](./docs/en/user-guide/agent-event-hooks.md) | Structured agent events instead of terminal scraping |
468
519
  | [Architecture](./docs/en/architecture.md) | System design |
469
520
  | [Deployment Guide](./docs/en/DEPLOYMENT.md) | Production environment setup |
470
521
  | [UI/UX Guide](./docs/en/UI_UX_GUIDE.md) | UI implementation details |
@@ -9,7 +9,7 @@
9
9
  * - `src/components/worktree/ActivityPane.tsx`
10
10
  * - `src/components/worktree/WorktreeDetailRefactored.tsx`
11
11
  *
12
- * The Activity Bar is a 48px-wide vertical bar that hosts 7 activities.
12
+ * The Activity Bar is a 48px-wide vertical bar that hosts the activities below.
13
13
  * Re-clicking the active icon toggles the ActivityPane closed (null).
14
14
  */
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -33,6 +33,10 @@ exports.ACTIVITIES = [
33
33
  { id: 'todo', labelKey: 'activityBar.todo', icon: lucide_react_1.ListTodo },
34
34
  // Issue #1441: worktree-scoped Skill install/uninstall management.
35
35
  { id: 'skills', labelKey: 'activityBar.skills', icon: lucide_react_1.Sparkles },
36
+ // Issue #1816: the execution contract and the verification gates. Appended
37
+ // rather than inserted so the existing ArrowUp/ArrowDown order — which users
38
+ // and tests both index by position — is unchanged.
39
+ { id: 'verification', labelKey: 'activityBar.verification', icon: lucide_react_1.ShieldCheck },
36
40
  ];
37
41
  /**
38
42
  * Set of valid ActivityId values for runtime validation.
@@ -296,7 +296,43 @@ async function detectAndRespondToPrompt(worktreeId, pollerState, cliToolId, clea
296
296
  if (isDuplicatePrompt(pollerState, promptKey)) {
297
297
  return 'duplicate';
298
298
  }
299
- // 3. Resolve auto answer under the execution contract's policy (Issue #1547).
299
+ // 3. Issue #1829: codex's own launch dialogs are CodexTool.waitForReady()'s
300
+ // to answer, not the poller's. Every one of them defaults to option 1, and
301
+ // the base rules answer the default:
302
+ //
303
+ // "Hooks need review" -> 1. Review hooks (undoes Issue #1760; the pane
304
+ // then sits two screens deep in a review UI that
305
+ // only `t`/`esc` leave, reported as `running`)
306
+ // "Update available" -> 1. Update now (undoes Issue #890; runs
307
+ // `npm install -g @openai/codex`, killing codex)
308
+ // "Do you trust …" -> 1. Yes, continue
309
+ //
310
+ // waitForReady answers the same screens deliberately and differently ('3',
311
+ // '2', '1' — each without a trailing Enter), but only during startSession,
312
+ // while this poller runs on its own 2s phase for the life of the session.
313
+ // Whichever sees the dialog first decides, so the fix is to leave them all
314
+ // to the tool. Auto-answer layer only: detectPrompt above still reports the
315
+ // prompt, so the human keeps seeing the screen and the response poller
316
+ // still notifies them about it.
317
+ const launchDialog = cliToolId === 'codex' ? (0, cli_patterns_1.getCodexLifecycleDialog)(cleanOutput) : null;
318
+ if (launchDialog) {
319
+ // Recorded through the #1684 channel so `capture --json` and `cmate wait`
320
+ // can name the reason instead of showing a worker that went quiet.
321
+ (0, auto_yes_suppression_state_1.recordPolicySuppression)(worktreeId, cliToolId, instanceId, {
322
+ reason: 'agent-launch-dialog',
323
+ mode: null,
324
+ promptType: promptDetection.promptData.type,
325
+ });
326
+ logger.warn('poller:auto-yes-skipped-launch-dialog', {
327
+ worktreeId,
328
+ cliToolId,
329
+ instanceId,
330
+ dialog: launchDialog,
331
+ promptType: promptDetection.promptData.type,
332
+ });
333
+ return 'no_answer';
334
+ }
335
+ // 4. Resolve auto answer under the execution contract's policy (Issue #1547).
300
336
  // Auto-Yes calls detectPrompt directly instead of going through
301
337
  // status-detector, so this is the only place the policy can gate an
302
338
  // auto-answer: a prompt the policy withholds is left for a human, and the
@@ -328,7 +364,7 @@ async function detectAndRespondToPrompt(worktreeId, pollerState, cliToolId, clea
328
364
  if (answer === null) {
329
365
  return 'no_answer';
330
366
  }
331
- // 4. Send answer to tmux (Issue #896: resolve the instance-specific session)
367
+ // 5. Send answer to tmux (Issue #896: resolve the instance-specific session)
332
368
  const manager = manager_1.CLIToolManager.getInstance();
333
369
  const cliTool = manager.getTool(cliToolId);
334
370
  const sessionName = cliTool.getSessionName(worktreeId, instanceId);
@@ -343,10 +379,10 @@ async function detectAndRespondToPrompt(worktreeId, pollerState, cliToolId, clea
343
379
  finally {
344
380
  (0, tmux_capture_cache_1.invalidateCache)(sessionName);
345
381
  }
346
- // 5. Update timestamp and reset error count
382
+ // 6. Update timestamp and reset error count
347
383
  updateLastServerResponseTimestamp(compositeKey, Date.now());
348
384
  resetErrorCount(compositeKey);
349
- // 6. Record answered prompt key and timestamp
385
+ // 7. Record answered prompt key and timestamp
350
386
  pollerState.lastAnsweredPromptKey = promptKey;
351
387
  pollerState.lastAnsweredAt = Date.now();
352
388
  logger.info('poller:response-sent', { worktreeId, cliToolId, instanceId });
@@ -31,33 +31,6 @@ const CODEX_POLL_INTERVAL_MS = 1000;
31
31
  const CODEX_INIT_MAX_ATTEMPTS = 30;
32
32
  /** Timeout for waiting for prompt before sending a message */
33
33
  const CODEX_PROMPT_WAIT_TIMEOUT_MS = 15000;
34
- /**
35
- * Anchors of codex's "Hooks need review" dialog (Issue #1760, measured on
36
- * codex-cli 0.147.0):
37
- *
38
- * ```
39
- * Hooks need review
40
- * 5 hooks are new or changed.
41
- * Hooks can run outside the sandbox after you trust them.
42
- *
43
- * > 1. Review hooks
44
- * 2. Trust all and continue
45
- * 3. Continue without trusting (hooks won't run)
46
- * ```
47
- *
48
- * It has to be handled here rather than in `getCodexActiveDialog`, which
49
- * classifies it as `null`: its wording matches none of that function's three
50
- * anchors (`Skip until next version` / `Do you trust` / `Press enter to
51
- * continue`). Measured consequence of leaving it alone, on a pane with the
52
- * generated `hooks.json` present: `isCodexPromptReady` stays false for the full
53
- * 30-attempt window and the session is then handed to `sendMessage` still
54
- * sitting on the dialog. Every launch, because "continue without trusting" is
55
- * not remembered — verified by relaunching and getting the same screen.
56
- *
57
- * Both strings are required so a "hooks" mention elsewhere cannot select an
58
- * option on a live prompt.
59
- */
60
- const CODEX_HOOKS_REVIEW_ANCHORS = ['Hooks need review', 'Continue without trusting'];
61
34
  /**
62
35
  * Option 3, "Continue without trusting (hooks won't run)".
63
36
  *
@@ -72,21 +45,57 @@ const CODEX_HOOKS_REVIEW_ANCHORS = ['Hooks need review', 'Continue without trust
72
45
  * Sent alone, like the other numbered dialogs (Issue #890): codex confirms a
73
46
  * numbered selection instantly, and a trailing Enter would land on the next
74
47
  * screen. Verified live — the prompt was ready on the following poll.
48
+ *
49
+ * Re-verified on codex-cli 0.148.0 for Issue #1829, against the objection that
50
+ * the dialog's own footer says `Press enter to confirm`. With the trust hashes
51
+ * invalidated and Auto-Yes off, a session launched onto this dialog reached
52
+ * `› Ask Codex to do anything` and then ran the message it was sent — on the
53
+ * `'3'` alone. The footer and the number key are not exclusive: the number
54
+ * selects AND confirms, Enter confirms the highlighted option. That is also why
55
+ * a trailing Enter is so costly here — the number having already advanced the
56
+ * screen, the Enter lands on the NEXT one, which is precisely how a pane ends up
57
+ * two screens deep in the hooks review UI.
75
58
  */
76
59
  const CODEX_HOOKS_REVIEW_DECLINE_KEY = '3';
60
+ /**
61
+ * How many times `waitForReady` may press `esc` to climb out of codex's hooks
62
+ * review screens (Issue #1829).
63
+ *
64
+ * Two is the depth of the UI — detail -> list -> closed — and the cap exists
65
+ * because the alternative is one press per poll: 30 keystrokes into whatever is
66
+ * really on screen if the classifier is ever wrong about a frame. Two spare
67
+ * presses cover a redraw landing between capture and send.
68
+ */
69
+ const CODEX_HOOKS_SCREEN_MAX_ESCAPES = 4;
77
70
  /**
78
71
  * Whether the pane is sitting on the hooks review dialog.
79
72
  *
80
73
  * Position-independent on purpose, unlike `getCodexActiveDialog`: the only
81
74
  * caller checks `isCodexPromptReady` first and returns when a genuine prompt
82
75
  * exists, so residual dialog text above a live prompt is never reached, and a
83
- * one-shot guard stops the key being sent twice.
76
+ * one-shot guard stops the key being sent twice. Callers OUTSIDE this launch
77
+ * sequence must use `getCodexLifecycleDialog` instead, which is position-based.
78
+ *
79
+ * The dialog has to be handled here rather than in `getCodexActiveDialog`, which
80
+ * classifies it as `null`: its wording matches none of that function's three
81
+ * anchors (`Skip until next version` / `Do you trust` / `Press enter to
82
+ * continue`). Measured consequence of leaving it alone, on a pane with the
83
+ * generated `hooks.json` present: `isCodexPromptReady` stays false for the full
84
+ * 30-attempt window and the session is then handed to `sendMessage` still
85
+ * sitting on the dialog. Every launch, because "continue without trusting" is
86
+ * not remembered — verified by relaunching and getting the same screen.
87
+ *
88
+ * The anchors themselves live in `detection/cli-patterns` (Issue #1829): the
89
+ * Auto-Yes poller has to recognise the same screen in order to keep its hands
90
+ * off it, and two copies of the anchors would be two chances to disagree about
91
+ * what this dialog is.
84
92
  *
85
93
  * @param output - ANSI-stripped pane capture
86
94
  * @returns True when both anchors of the dialog are present
95
+ * @see CODEX_HOOKS_REVIEW_ANCHORS
87
96
  */
88
97
  function isCodexHooksReviewDialog(output) {
89
- return CODEX_HOOKS_REVIEW_ANCHORS.every((anchor) => output.includes(anchor));
98
+ return cli_patterns_1.CODEX_HOOKS_REVIEW_ANCHORS.every((anchor) => output.includes(anchor));
90
99
  }
91
100
  /**
92
101
  * Codex CLI tool implementation
@@ -185,6 +194,7 @@ class CodexTool extends base_1.BaseCLITool {
185
194
  let updateDialogHandled = false;
186
195
  let trustDialogHandled = false;
187
196
  let hooksReviewHandled = false;
197
+ let hooksScreenEscapes = 0;
188
198
  for (let i = 0; i < CODEX_INIT_MAX_ATTEMPTS; i++) {
189
199
  try {
190
200
  const rawOutput = await (0, tmux_1.capturePane)(sessionName, 50);
@@ -208,6 +218,25 @@ class CodexTool extends base_1.BaseCLITool {
208
218
  await new Promise((resolve) => setTimeout(resolve, cli_tool_timing_config_1.CODEX_DIALOG_SETTLE_MS));
209
219
  continue;
210
220
  }
221
+ // Issue #1829: back out of the two screens the hooks dialog leads to.
222
+ // Confirming its option 1 -- which the Auto-Yes poller did on two live
223
+ // sessions, and which a human can do too -- opens a review UI whose only
224
+ // exits are `t` and `esc`. `t` is out: it writes `[hooks.state…]` into
225
+ // the operator's own ~/.codex/config.toml, the grant Issue #1760
226
+ // declined on their behalf. So `esc`, once per poll until the screens
227
+ // are gone. Before this, nothing sent either key: the whole 30-attempt
228
+ // window elapsed, waitForReady returned as if ready, and the session was
229
+ // left parked there -- reported as `running`, because neither screen
230
+ // carries an option, a confirm footer or a thinking indicator.
231
+ const hooksScreen = (0, cli_patterns_1.getCodexLifecycleDialog)(output);
232
+ if ((hooksScreen === 'hooks-list' || hooksScreen === 'hooks-detail') &&
233
+ hooksScreenEscapes < CODEX_HOOKS_SCREEN_MAX_ESCAPES) {
234
+ await (0, tmux_1.sendSpecialKey)(sessionName, 'Escape');
235
+ hooksScreenEscapes++;
236
+ logger.info('codex-hooks-screen-escaped');
237
+ await new Promise((resolve) => setTimeout(resolve, cli_tool_timing_config_1.CODEX_DIALOG_SETTLE_MS));
238
+ continue;
239
+ }
211
240
  // Issue #892: classify the bottom-most ACTIVE dialog by position. A dialog
212
241
  // whose text is only residual scrollback above a genuine prompt returns
213
242
  // null here, so no stray key is sent after it has been dismissed.
@@ -4,11 +4,12 @@
4
4
  * Shared between response-poller.ts and API routes
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.CLAUDE_SESSION_ERROR_REGEX_PATTERNS = exports.CLAUDE_SESSION_ERROR_PATTERNS = exports.extractAnsiSequences = exports.stripAnsi = exports.ANTIGRAVITY_SKIP_PATTERNS = exports.ANTIGRAVITY_SELECTION_LIST_PATTERN = exports.ANTIGRAVITY_SEPARATOR_PATTERN = exports.ANTIGRAVITY_THINKING_PATTERN = exports.ANTIGRAVITY_PROMPT_PATTERN = exports.VIBE_LOCAL_THINKING_PATTERN = exports.VIBE_LOCAL_PROMPT_PATTERN = exports.COPILOT_SKIP_PATTERNS = exports.COPILOT_SELECTION_LIST_PATTERN = exports.COPILOT_SEPARATOR_PATTERN = exports.COPILOT_THINKING_PATTERN = exports.COPILOT_PROMPT_PATTERN = exports.OPENCODE_SKIP_PATTERNS = exports.OPENCODE_SEPARATOR_PATTERN = exports.CLAUDE_SELECTION_LIST_FOOTER = exports.CLAUDE_MODEL_OVERLAY_FOOTER_PATTERN = exports.OPENCODE_SELECTION_LIST_PATTERN = exports.OPENCODE_PROCESSING_INDICATOR = exports.OPENCODE_RESPONSE_COMPLETE = exports.OPENCODE_LOADING_PATTERN = exports.OPENCODE_THINKING_PATTERN = exports.OPENCODE_PROMPT_AFTER_RESPONSE = exports.OPENCODE_PROMPT_PATTERN = exports.GEMINI_THINKING_PATTERN = exports.GEMINI_PROMPT_PATTERN = exports.MAX_PASTED_TEXT_RETRIES = exports.PASTED_TEXT_DETECT_DELAY = exports.PASTED_TEXT_PATTERN = exports.CODEX_STATUS_BAR_PATTERN = exports.CODEX_PAGER_FOOTER_PATTERN = exports.CODEX_APPROVAL_FOOTER_PATTERN = exports.CODEX_SELECTION_LIST_PATTERN = exports.CODEX_SEPARATOR_PATTERN = exports.CODEX_DIALOG_PATTERN = exports.CODEX_PROMPT_PATTERN = exports.CLAUDE_TRUST_DIALOG_PATTERN = exports.CLAUDE_SEPARATOR_PATTERN = exports.CLAUDE_PROMPT_PATTERN = exports.CODEX_INTERRUPT_HINT_PATTERN = exports.CODEX_THINKING_PATTERN = exports.CLAUDE_INTERRUPT_HINT_PATTERN = exports.CLAUDE_THINKING_PATTERN = exports.CLAUDE_SPINNER_CHARS = void 0;
7
+ exports.CLAUDE_SESSION_ERROR_REGEX_PATTERNS = exports.CLAUDE_SESSION_ERROR_PATTERNS = exports.extractAnsiSequences = exports.stripAnsi = exports.ANTIGRAVITY_SKIP_PATTERNS = exports.ANTIGRAVITY_SELECTION_LIST_PATTERN = exports.ANTIGRAVITY_SEPARATOR_PATTERN = exports.ANTIGRAVITY_THINKING_PATTERN = exports.ANTIGRAVITY_PROMPT_PATTERN = exports.VIBE_LOCAL_THINKING_PATTERN = exports.VIBE_LOCAL_PROMPT_PATTERN = exports.COPILOT_SKIP_PATTERNS = exports.COPILOT_SELECTION_LIST_PATTERN = exports.COPILOT_SEPARATOR_PATTERN = exports.COPILOT_THINKING_PATTERN = exports.COPILOT_PROMPT_PATTERN = exports.OPENCODE_SKIP_PATTERNS = exports.OPENCODE_SEPARATOR_PATTERN = exports.CLAUDE_SELECTION_LIST_FOOTER = exports.CLAUDE_MODEL_OVERLAY_FOOTER_PATTERN = exports.OPENCODE_SELECTION_LIST_PATTERN = exports.OPENCODE_PROCESSING_INDICATOR = exports.OPENCODE_RESPONSE_COMPLETE = exports.OPENCODE_LOADING_PATTERN = exports.OPENCODE_THINKING_PATTERN = exports.OPENCODE_PROMPT_AFTER_RESPONSE = exports.OPENCODE_PROMPT_PATTERN = exports.GEMINI_THINKING_PATTERN = exports.GEMINI_PROMPT_PATTERN = exports.MAX_PASTED_TEXT_RETRIES = exports.PASTED_TEXT_DETECT_DELAY = exports.PASTED_TEXT_PATTERN = exports.CODEX_STATUS_BAR_PATTERN = exports.CODEX_PAGER_FOOTER_PATTERN = exports.CODEX_APPROVAL_FOOTER_PATTERN = exports.CODEX_SELECTION_LIST_PATTERN = exports.CODEX_SEPARATOR_PATTERN = exports.CODEX_HOOKS_REVIEW_ANCHORS = exports.CODEX_DIALOG_PATTERN = exports.CODEX_PROMPT_PATTERN = exports.CLAUDE_TRUST_DIALOG_PATTERN = exports.CLAUDE_SEPARATOR_PATTERN = exports.CLAUDE_PROMPT_PATTERN = exports.CODEX_INTERRUPT_HINT_PATTERN = exports.CODEX_THINKING_PATTERN = exports.CLAUDE_INTERRUPT_HINT_PATTERN = exports.CLAUDE_THINKING_PATTERN = exports.CLAUDE_SPINNER_CHARS = void 0;
8
8
  exports.isCodexTurnActive = isCodexTurnActive;
9
9
  exports.findClaudeChromeStart = findClaudeChromeStart;
10
10
  exports.isCodexPromptReady = isCodexPromptReady;
11
11
  exports.getCodexActiveDialog = getCodexActiveDialog;
12
+ exports.getCodexLifecycleDialog = getCodexLifecycleDialog;
12
13
  exports.detectThinking = detectThinking;
13
14
  exports.getCliToolPatterns = getCliToolPatterns;
14
15
  exports.stripBoxDrawing = stripBoxDrawing;
@@ -330,7 +331,18 @@ function isCodexPromptReady(output) {
330
331
  * update dialog wins over its own "Press enter to continue" footer, because Enter
331
332
  * on the update dialog could confirm the default "1. Update now" (npm install).
332
333
  */
333
- function getCodexActiveDialog(output) {
334
+ /**
335
+ * The lines of Codex's ACTIVE region: everything strictly below the bottom-most
336
+ * genuine input-prompt line, or the whole frame when there is no prompt line
337
+ * (Issue #892).
338
+ *
339
+ * This is the one rule that keeps every Codex dialog classifier honest.
340
+ * capturePane returns scrollback, so a dialog that was answered minutes ago is
341
+ * still in the frame; only what sits BELOW the live prompt is still awaiting a
342
+ * key. Shared by getCodexActiveDialog and getCodexLifecycleDialog so the two
343
+ * cannot drift into disagreeing about what "active" means.
344
+ */
345
+ function codexActiveRegionLines(output) {
334
346
  const lines = output.split('\n');
335
347
  // Index of the bottom-most genuine input-prompt line (-1 if none).
336
348
  let promptIdx = -1;
@@ -340,10 +352,12 @@ function getCodexActiveDialog(output) {
340
352
  break;
341
353
  }
342
354
  }
343
- // Active region = lines strictly below the genuine prompt (the whole frame when
344
- // there is no genuine prompt). Residual dialog text above a live prompt is
345
- // excluded, so a dialog lingering in scrollback is never treated as active.
346
- const active = lines.slice(promptIdx + 1).join('\n');
355
+ return lines.slice(promptIdx + 1);
356
+ }
357
+ function getCodexActiveDialog(output) {
358
+ // Residual dialog text above a live prompt is excluded, so a dialog lingering
359
+ // in scrollback is never treated as active.
360
+ const active = codexActiveRegionLines(output).join('\n');
347
361
  if (active === '') {
348
362
  return null;
349
363
  }
@@ -359,6 +373,134 @@ function getCodexActiveDialog(output) {
359
373
  }
360
374
  return null;
361
375
  }
376
+ /**
377
+ * Anchors of codex's "Hooks need review" launch dialog — screen 1 of the three
378
+ * it can put in front of a session (Issue #1760, re-measured on codex-cli
379
+ * 0.148.0 for Issue #1829):
380
+ *
381
+ * ```
382
+ * Hooks need review
383
+ * 4 hooks are new or changed.
384
+ * Hooks can run outside the sandbox after you trust them.
385
+ *
386
+ * > 1. Review hooks
387
+ * 2. Trust all and continue
388
+ * 3. Continue without trusting (hooks won't run)
389
+ * Press enter to confirm or esc to go back
390
+ * ```
391
+ *
392
+ * The hook COUNT is data — 0.147.0 said 5, 0.148.0 said 4 — so neither anchor
393
+ * reads it. Both strings are required so a "hooks" mention elsewhere cannot
394
+ * select an option on a live prompt.
395
+ */
396
+ exports.CODEX_HOOKS_REVIEW_ANCHORS = ['Hooks need review', 'Continue without trusting'];
397
+ /**
398
+ * Footer of screen 2, the hooks LIST, new in codex-cli 0.148.0 (Issue #1829):
399
+ * `Press t to trust all; enter to review hooks; esc to close`.
400
+ *
401
+ * The semicolon is what separates it from screen 3's footer — "trust all;" and
402
+ * "trust;" are disjoint — and matching the footer rather than the table above it
403
+ * keeps the two screens distinguishable by a single line each.
404
+ */
405
+ const CODEX_HOOKS_LIST_FOOTER_PATTERN = /press\s+t\s+to\s+trust\s+all\s*;/i;
406
+ /**
407
+ * Footer of screen 3, the per-hook review DETAIL (Issue #1829):
408
+ * `Press t to trust; esc to go back`. Where both live sessions in the Issue were
409
+ * found parked.
410
+ */
411
+ const CODEX_HOOKS_DETAIL_FOOTER_PATTERN = /press\s+t\s+to\s+trust\s*;/i;
412
+ /**
413
+ * How much of the active region {@link getCodexLifecycleDialog} judges, in
414
+ * non-blank lines counted from the bottom (Issue #1829).
415
+ *
416
+ * `getCodexActiveDialog` searches the whole active region, which is right for
417
+ * its caller: `waitForReady` only ever runs during `startSession`, when nothing
418
+ * else can be on screen. This classifier runs on every Auto-Yes poll for the
419
+ * life of the session, where "active region" alone is not enough — a codex
420
+ * approval request renders no `› ` composer line, so an approval that comes up
421
+ * while a dismissed hooks screen is still inside the capture window would have
422
+ * the whole frame as its active region and would be mistaken for the dialog.
423
+ * Requiring the dialog to be in the TAIL is what separates the screen the user
424
+ * is looking at from the one they have already left.
425
+ *
426
+ * 12 lines fits the tallest screen this has to recognise (the review dialog's
427
+ * two anchors sit 6 lines apart) and none of the shorter frames below it.
428
+ */
429
+ const CODEX_LIFECYCLE_TAIL_LINES = 12;
430
+ /**
431
+ * The interactive update dialog, by its option-3 label or its option-1 line.
432
+ *
433
+ * Deliberately stricter than `getCodexActiveDialog`'s `Update` AND `Skip`
434
+ * fallback: that pair can occur in ordinary agent output, and here a false
435
+ * positive silently stops Auto-Yes answering a real prompt. Both anchors below
436
+ * are dialog chrome that agent output does not produce.
437
+ */
438
+ const CODEX_UPDATE_DIALOG_ANCHORS = [
439
+ /skip until next version/i,
440
+ /^\s*[›❯]?\s*\d+\.\s*Update now/im,
441
+ ];
442
+ /** The directory-trust dialog's question line. */
443
+ const CODEX_TRUST_DIALOG_ANCHOR = /Do you trust/;
444
+ /**
445
+ * Classify the bottom-most ACTIVE codex lifecycle screen (Issue #1829).
446
+ *
447
+ * Position-based, via {@link codexActiveRegionLines}: a dialog left in
448
+ * scrollback above a live prompt is not active and returns `null`. That is not
449
+ * a detail — the auto-answer guard in the Auto-Yes poller is built on this
450
+ * function, and a whole-frame version of it would switch Auto-Yes off for the
451
+ * rest of a codex session the moment any launch dialog scrolled past.
452
+ *
453
+ * The two hooks screens are matched FIRST and bottom-up, because a stuck pane
454
+ * holds screen 2 above screen 3 and the way out of each differs. The remaining
455
+ * three are region-level substring tests, which is all their anchors allow:
456
+ * the review dialog's are on two different lines.
457
+ *
458
+ * Deliberately NOT used to decide whether a prompt exists. `detectPrompt` still
459
+ * reports these screens, so a human still sees them; what this function gates is
460
+ * only whether a machine may answer on their behalf.
461
+ *
462
+ * @param output - ANSI-stripped pane capture
463
+ * @returns The active lifecycle screen, or null when none is
464
+ */
465
+ function getCodexLifecycleDialog(output) {
466
+ const activeLines = codexActiveRegionLines(output);
467
+ const window = [];
468
+ for (let i = activeLines.length - 1; i >= 0 && window.length < CODEX_LIFECYCLE_TAIL_LINES; i--) {
469
+ if (activeLines[i].trim() === '')
470
+ continue;
471
+ window.unshift(activeLines[i]);
472
+ }
473
+ if (window.length === 0)
474
+ return null;
475
+ const text = window.join('\n');
476
+ // One bottom-up pass, returning on the first line that decides the question --
477
+ // including the lines that decide it NEGATIVELY. A stuck pane holds screen 2
478
+ // above screen 3, and an approval request can come up with a hooks screen
479
+ // still inside the capture window; in both cases the screen the user is
480
+ // looking at is the lower one.
481
+ for (let i = window.length - 1; i >= 0; i--) {
482
+ const line = window[i];
483
+ if (CODEX_HOOKS_LIST_FOOTER_PATTERN.test(line))
484
+ return 'hooks-list';
485
+ if (CODEX_HOOKS_DETAIL_FOOTER_PATTERN.test(line))
486
+ return 'hooks-detail';
487
+ // The agent asking the human for permission mid-turn (Issue #1628's
488
+ // "esc to cancel" footer, which no lifecycle screen wears). This is exactly
489
+ // the prompt Auto-Yes exists to answer, so whatever lifecycle text is still
490
+ // above it has been left behind and must not withhold the answer.
491
+ if (exports.CODEX_APPROVAL_FOOTER_PATTERN.test(line))
492
+ return null;
493
+ if (CODEX_UPDATE_DIALOG_ANCHORS.some((pattern) => pattern.test(line)))
494
+ return 'update';
495
+ if (CODEX_TRUST_DIALOG_ANCHOR.test(line))
496
+ return 'trust';
497
+ // Both anchors required, so a stray "hooks" mention cannot claim the screen.
498
+ if (line.includes(exports.CODEX_HOOKS_REVIEW_ANCHORS[1]) && text.includes(exports.CODEX_HOOKS_REVIEW_ANCHORS[0])) {
499
+ return 'hooks-review';
500
+ }
501
+ }
502
+ return null;
503
+ }
362
504
  /**
363
505
  * Codex separator pattern
364
506
  */