commandmate 0.1.5 → 0.1.6

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 (330) hide show
  1. package/.next/BUILD_ID +1 -0
  2. package/.next/app-build-manifest.json +72 -0
  3. package/.next/app-path-routes-manifest.json +1 -0
  4. package/.next/build-manifest.json +32 -0
  5. package/.next/cache/.tsbuildinfo +1 -0
  6. package/.next/cache/config.json +7 -0
  7. package/.next/cache/webpack/client-production/0.pack +0 -0
  8. package/.next/cache/webpack/client-production/1.pack +0 -0
  9. package/.next/cache/webpack/client-production/2.pack +0 -0
  10. package/.next/cache/webpack/client-production/index.pack +0 -0
  11. package/.next/cache/webpack/client-production/index.pack.old +0 -0
  12. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  13. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  14. package/.next/cache/webpack/server-production/0.pack +0 -0
  15. package/.next/cache/webpack/server-production/index.pack +0 -0
  16. package/.next/export-marker.json +1 -0
  17. package/.next/images-manifest.json +1 -0
  18. package/.next/next-minimal-server.js.nft.json +1 -0
  19. package/.next/next-server.js.nft.json +1 -0
  20. package/.next/package.json +1 -0
  21. package/.next/prerender-manifest.json +1 -0
  22. package/.next/react-loadable-manifest.json +249 -0
  23. package/.next/required-server-files.json +1 -0
  24. package/.next/routes-manifest.json +1 -0
  25. package/.next/server/app/_not-found/page.js +1 -0
  26. package/.next/server/app/_not-found/page.js.nft.json +1 -0
  27. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  28. package/.next/server/app/_not-found.html +1 -0
  29. package/.next/server/app/_not-found.meta +6 -0
  30. package/.next/server/app/_not-found.rsc +10 -0
  31. package/.next/server/app/api/external-apps/[id]/health/route.js +45 -0
  32. package/.next/server/app/api/external-apps/[id]/health/route.js.nft.json +1 -0
  33. package/.next/server/app/api/external-apps/[id]/route.js +45 -0
  34. package/.next/server/app/api/external-apps/[id]/route.js.nft.json +1 -0
  35. package/.next/server/app/api/external-apps/route.js +45 -0
  36. package/.next/server/app/api/external-apps/route.js.nft.json +1 -0
  37. package/.next/server/app/api/hooks/claude-done/route.js +19 -0
  38. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -0
  39. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -0
  40. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -0
  41. package/.next/server/app/api/repositories/clone/route.js +1 -0
  42. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -0
  43. package/.next/server/app/api/repositories/route.js +1 -0
  44. package/.next/server/app/api/repositories/route.js.nft.json +1 -0
  45. package/.next/server/app/api/repositories/scan/route.js +1 -0
  46. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -0
  47. package/.next/server/app/api/repositories/sync/route.js +1 -0
  48. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -0
  49. package/.next/server/app/api/slash-commands/route.js +1 -0
  50. package/.next/server/app/api/slash-commands/route.js.nft.json +1 -0
  51. package/.next/server/app/api/slash-commands.body +1 -0
  52. package/.next/server/app/api/slash-commands.meta +1 -0
  53. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -0
  54. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -0
  55. package/.next/server/app/api/worktrees/[id]/capture/route.js +2 -0
  56. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -0
  57. package/.next/server/app/api/worktrees/[id]/cli-tool/route.js +1 -0
  58. package/.next/server/app/api/worktrees/[id]/cli-tool/route.js.nft.json +1 -0
  59. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -0
  60. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -0
  61. package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -0
  62. package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js.nft.json +1 -0
  63. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -0
  64. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -0
  65. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -0
  66. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -0
  67. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js +1 -0
  68. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js.nft.json +1 -0
  69. package/.next/server/app/api/worktrees/[id]/logs/route.js +19 -0
  70. package/.next/server/app/api/worktrees/[id]/logs/route.js.nft.json +1 -0
  71. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js +1 -0
  72. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js.nft.json +1 -0
  73. package/.next/server/app/api/worktrees/[id]/memos/route.js +1 -0
  74. package/.next/server/app/api/worktrees/[id]/memos/route.js.nft.json +1 -0
  75. package/.next/server/app/api/worktrees/[id]/messages/route.js +1 -0
  76. package/.next/server/app/api/worktrees/[id]/messages/route.js.nft.json +1 -0
  77. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -0
  78. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -0
  79. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -0
  80. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -0
  81. package/.next/server/app/api/worktrees/[id]/route.js +1 -0
  82. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -0
  83. package/.next/server/app/api/worktrees/[id]/search/route.js +1 -0
  84. package/.next/server/app/api/worktrees/[id]/search/route.js.nft.json +1 -0
  85. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -0
  86. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -0
  87. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -0
  88. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js.nft.json +1 -0
  89. package/.next/server/app/api/worktrees/[id]/start-polling/route.js +1 -0
  90. package/.next/server/app/api/worktrees/[id]/start-polling/route.js.nft.json +1 -0
  91. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -0
  92. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -0
  93. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js +1 -0
  94. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js.nft.json +1 -0
  95. package/.next/server/app/api/worktrees/[id]/tree/route.js +1 -0
  96. package/.next/server/app/api/worktrees/[id]/tree/route.js.nft.json +1 -0
  97. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route.js +1 -0
  98. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route.js.nft.json +1 -0
  99. package/.next/server/app/api/worktrees/[id]/viewed/route.js +1 -0
  100. package/.next/server/app/api/worktrees/[id]/viewed/route.js.nft.json +1 -0
  101. package/.next/server/app/api/worktrees/route.js +1 -0
  102. package/.next/server/app/api/worktrees/route.js.nft.json +1 -0
  103. package/.next/server/app/apple-icon.png/route.js +1 -0
  104. package/.next/server/app/apple-icon.png/route.js.nft.json +1 -0
  105. package/.next/server/app/apple-icon.png.body +0 -0
  106. package/.next/server/app/apple-icon.png.meta +1 -0
  107. package/.next/server/app/icon.png/route.js +1 -0
  108. package/.next/server/app/icon.png/route.js.nft.json +1 -0
  109. package/.next/server/app/icon.png.body +0 -0
  110. package/.next/server/app/icon.png.meta +1 -0
  111. package/.next/server/app/index.html +9 -0
  112. package/.next/server/app/index.meta +5 -0
  113. package/.next/server/app/index.rsc +8 -0
  114. package/.next/server/app/page.js +16 -0
  115. package/.next/server/app/page.js.nft.json +1 -0
  116. package/.next/server/app/page_client-reference-manifest.js +1 -0
  117. package/.next/server/app/proxy/[...path]/route.js +45 -0
  118. package/.next/server/app/proxy/[...path]/route.js.nft.json +1 -0
  119. package/.next/server/app/worktrees/[id]/files/[...path]/page.js +1 -0
  120. package/.next/server/app/worktrees/[id]/files/[...path]/page.js.nft.json +1 -0
  121. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -0
  122. package/.next/server/app/worktrees/[id]/page.js +21 -0
  123. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -0
  124. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -0
  125. package/.next/server/app/worktrees/[id]/simple-terminal/page.js +4 -0
  126. package/.next/server/app/worktrees/[id]/simple-terminal/page.js.nft.json +1 -0
  127. package/.next/server/app/worktrees/[id]/simple-terminal/page_client-reference-manifest.js +1 -0
  128. package/.next/server/app/worktrees/[id]/terminal/page.js +6 -0
  129. package/.next/server/app/worktrees/[id]/terminal/page.js.nft.json +1 -0
  130. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -0
  131. package/.next/server/app-paths-manifest.json +46 -0
  132. package/.next/server/chunks/1318.js +29 -0
  133. package/.next/server/chunks/1528.js +1 -0
  134. package/.next/server/chunks/1682.js +6 -0
  135. package/.next/server/chunks/2518.js +12 -0
  136. package/.next/server/chunks/3053.js +1 -0
  137. package/.next/server/chunks/3673.js +1 -0
  138. package/.next/server/chunks/3853.js +1 -0
  139. package/.next/server/chunks/434.js +1 -0
  140. package/.next/server/chunks/4471.js +2 -0
  141. package/.next/server/chunks/4893.js +2 -0
  142. package/.next/server/chunks/5972.js +12 -0
  143. package/.next/server/chunks/6550.js +1 -0
  144. package/.next/server/chunks/6621.js +1 -0
  145. package/.next/server/chunks/7213.js +1 -0
  146. package/.next/server/chunks/7425.js +500 -0
  147. package/.next/server/chunks/8585.js +1 -0
  148. package/.next/server/chunks/8887.js +1 -0
  149. package/.next/server/chunks/8948.js +2 -0
  150. package/.next/server/chunks/9703.js +31 -0
  151. package/.next/server/chunks/9723.js +19 -0
  152. package/.next/server/chunks/font-manifest.json +1 -0
  153. package/.next/server/edge-runtime-webpack.js +2 -0
  154. package/.next/server/edge-runtime-webpack.js.map +1 -0
  155. package/.next/server/font-manifest.json +1 -0
  156. package/.next/server/functions-config-manifest.json +1 -0
  157. package/.next/server/interception-route-rewrite-manifest.js +1 -0
  158. package/.next/server/middleware-build-manifest.js +1 -0
  159. package/.next/server/middleware-manifest.json +32 -0
  160. package/.next/server/middleware-react-loadable-manifest.js +1 -0
  161. package/.next/server/next-font-manifest.js +1 -0
  162. package/.next/server/next-font-manifest.json +1 -0
  163. package/.next/server/pages/404.html +1 -0
  164. package/.next/server/pages/500.html +1 -0
  165. package/.next/server/pages/_app.js +1 -0
  166. package/.next/server/pages/_app.js.nft.json +1 -0
  167. package/.next/server/pages/_document.js +1 -0
  168. package/.next/server/pages/_document.js.nft.json +1 -0
  169. package/.next/server/pages/_error.js +1 -0
  170. package/.next/server/pages/_error.js.nft.json +1 -0
  171. package/.next/server/pages-manifest.json +1 -0
  172. package/.next/server/server-reference-manifest.js +1 -0
  173. package/.next/server/server-reference-manifest.json +1 -0
  174. package/.next/server/src/middleware.js +14 -0
  175. package/.next/server/src/middleware.js.map +1 -0
  176. package/.next/server/webpack-runtime.js +1 -0
  177. package/.next/static/chunks/0dbeb660.3e800dfbd28be3bd.js +53 -0
  178. package/.next/static/chunks/1015.0eaa4da7f61149bc.js +59 -0
  179. package/.next/static/chunks/1098.49268c9fe1b028fa.js +1 -0
  180. package/.next/static/chunks/13.feeafc7cc620f8c4.js +1 -0
  181. package/.next/static/chunks/1423.7b1e8bf760d28078.js +1 -0
  182. package/.next/static/chunks/1582.9f8590f71ff798ca.js +55 -0
  183. package/.next/static/chunks/1817.a66d96cedb761daa.js +262 -0
  184. package/.next/static/chunks/2117-d845c2cd62e344a6.js +2 -0
  185. package/.next/static/chunks/2398.0b21e4eb7006a230.js +93 -0
  186. package/.next/static/chunks/2526.8ac62b527c9ab703.js +43 -0
  187. package/.next/static/chunks/2626.2125083a1ff3b80a.js +29 -0
  188. package/.next/static/chunks/2689.720a4874b02d4211.js +174 -0
  189. package/.next/static/chunks/2853-d11a80b03c9a1640.js +1 -0
  190. package/.next/static/chunks/2957-327e43ef4c12808f.js +1 -0
  191. package/.next/static/chunks/2cdb6380.35626fc6e41bbba4.js +136 -0
  192. package/.next/static/chunks/30d07d85-393352a92199f695.js +3 -0
  193. package/.next/static/chunks/3559.f073f72c4466ce0e.js +1 -0
  194. package/.next/static/chunks/3574.7a94c27e6a496a56.js +63 -0
  195. package/.next/static/chunks/383.20683891c9a5f2c4.js +4 -0
  196. package/.next/static/chunks/3843.3fdda732987f7bb8.js +1 -0
  197. package/.next/static/chunks/3852.822389f445c9b427.js +1 -0
  198. package/.next/static/chunks/3991.4bc063cb5be3a86c.js +1 -0
  199. package/.next/static/chunks/4212.52c1bb34fc97d0d0.js +131 -0
  200. package/.next/static/chunks/4327.3b84aa049900fdeb.js +60 -0
  201. package/.next/static/chunks/4362.7bd6f0282e49d79b.js +1 -0
  202. package/.next/static/chunks/4721.40615a5f4f32b5fb.js +1 -0
  203. package/.next/static/chunks/4851-45df4d388db5623f.js +1 -0
  204. package/.next/static/chunks/5112.17318d1c6b28044b.js +1 -0
  205. package/.next/static/chunks/5126.93fa4e797d609286.js +56 -0
  206. package/.next/static/chunks/5387.47590ac4ef66c864.js +5 -0
  207. package/.next/static/chunks/5813.4483664ba482beb1.js +1 -0
  208. package/.next/static/chunks/6143.1450875bd03a2366.js +36 -0
  209. package/.next/static/chunks/6406.9653f0d41ab85059.js +1 -0
  210. package/.next/static/chunks/656.d72f25ce819bd77e.js +149 -0
  211. package/.next/static/chunks/6678.492e73ca42b2a273.js +62 -0
  212. package/.next/static/chunks/6725-f7607851b7d57eb1.js +1 -0
  213. package/.next/static/chunks/6792.3c01ac4dda4b5c6d.js +1 -0
  214. package/.next/static/chunks/7004.808cbf327ef5955e.js +1 -0
  215. package/.next/static/chunks/7290.09ef84cf94f90c4d.js +1 -0
  216. package/.next/static/chunks/7415.6b481c2baf363262.js +148 -0
  217. package/.next/static/chunks/7648-325564a6e12a3257.js +1 -0
  218. package/.next/static/chunks/7665.47fccad04449a8f9.js +215 -0
  219. package/.next/static/chunks/7753.6bdce86b7fde3d10.js +166 -0
  220. package/.next/static/chunks/8125.245a9df052d274fb.js +1 -0
  221. package/.next/static/chunks/816-7e340dad784be28c.js +1 -0
  222. package/.next/static/chunks/8288.4883743fa40672e2.js +24 -0
  223. package/.next/static/chunks/8522.1607e96011c66877.js +1 -0
  224. package/.next/static/chunks/8772.863c564498d88487.js +1 -0
  225. package/.next/static/chunks/8841.dadeb1ece8e46004.js +1 -0
  226. package/.next/static/chunks/8885.f8d9912b40d74811.js +1 -0
  227. package/.next/static/chunks/90542734.c1553d0fe7fc14fc.js +1 -0
  228. package/.next/static/chunks/9365-733d8c05712d2888.js +1 -0
  229. package/.next/static/chunks/9552.b7dfb7903ead934b.js +1 -0
  230. package/.next/static/chunks/9834.295b45635ce04f5e.js +24 -0
  231. package/.next/static/chunks/app/_not-found/page-a9d04e58c81115ec.js +1 -0
  232. package/.next/static/chunks/app/layout-37e55f11dcc8b1bf.js +1 -0
  233. package/.next/static/chunks/app/page-9cd00de9cc0abc43.js +1 -0
  234. package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-9e5adf57cbbbdf05.js +1 -0
  235. package/.next/static/chunks/app/worktrees/[id]/page-8c6676303b63fdaf.js +1 -0
  236. package/.next/static/chunks/app/worktrees/[id]/simple-terminal/page-16feb3e86e42f4d1.js +1 -0
  237. package/.next/static/chunks/app/worktrees/[id]/terminal/page-be802baffc84dbd2.js +1 -0
  238. package/.next/static/chunks/d3ac728e.6c9c508274d4d2d5.js +1 -0
  239. package/.next/static/chunks/fd9d1056-bbe86e4ae099d5cd.js +1 -0
  240. package/.next/static/chunks/framework-8e0e0f4a6b83a956.js +1 -0
  241. package/.next/static/chunks/main-a960f4a5e1a2f598.js +1 -0
  242. package/.next/static/chunks/main-app-420d93e43682fee5.js +1 -0
  243. package/.next/static/chunks/pages/_app-3c9ca398d360b709.js +1 -0
  244. package/.next/static/chunks/pages/_error-cf5ca766ac8f493f.js +1 -0
  245. package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  246. package/.next/static/chunks/webpack-3fc79fab9bb738d7.js +1 -0
  247. package/.next/static/css/5eacd01f773eed7f.css +11 -0
  248. package/.next/static/css/85fa6dafca566008.css +1 -0
  249. package/.next/static/css/e174aa24f94ce607.css +3 -0
  250. package/.next/static/pQTquVjewvoJa7BML07ip/_buildManifest.js +1 -0
  251. package/.next/static/pQTquVjewvoJa7BML07ip/_ssgManifest.js +1 -0
  252. package/.next/trace +5 -0
  253. package/.next/types/app/api/external-apps/[id]/health/route.ts +343 -0
  254. package/.next/types/app/api/external-apps/[id]/route.ts +343 -0
  255. package/.next/types/app/api/external-apps/route.ts +343 -0
  256. package/.next/types/app/api/hooks/claude-done/route.ts +343 -0
  257. package/.next/types/app/api/repositories/clone/[jobId]/route.ts +343 -0
  258. package/.next/types/app/api/repositories/clone/route.ts +343 -0
  259. package/.next/types/app/api/repositories/route.ts +343 -0
  260. package/.next/types/app/api/repositories/scan/route.ts +343 -0
  261. package/.next/types/app/api/repositories/sync/route.ts +343 -0
  262. package/.next/types/app/api/slash-commands/route.ts +343 -0
  263. package/.next/types/app/api/worktrees/[id]/auto-yes/route.ts +343 -0
  264. package/.next/types/app/api/worktrees/[id]/capture/route.ts +343 -0
  265. package/.next/types/app/api/worktrees/[id]/cli-tool/route.ts +343 -0
  266. package/.next/types/app/api/worktrees/[id]/current-output/route.ts +343 -0
  267. package/.next/types/app/api/worktrees/[id]/files/[...path]/route.ts +343 -0
  268. package/.next/types/app/api/worktrees/[id]/interrupt/route.ts +343 -0
  269. package/.next/types/app/api/worktrees/[id]/kill-session/route.ts +343 -0
  270. package/.next/types/app/api/worktrees/[id]/logs/[filename]/route.ts +343 -0
  271. package/.next/types/app/api/worktrees/[id]/logs/route.ts +343 -0
  272. package/.next/types/app/api/worktrees/[id]/memos/[memoId]/route.ts +343 -0
  273. package/.next/types/app/api/worktrees/[id]/memos/route.ts +343 -0
  274. package/.next/types/app/api/worktrees/[id]/messages/route.ts +343 -0
  275. package/.next/types/app/api/worktrees/[id]/prompt-response/route.ts +343 -0
  276. package/.next/types/app/api/worktrees/[id]/respond/route.ts +343 -0
  277. package/.next/types/app/api/worktrees/[id]/route.ts +343 -0
  278. package/.next/types/app/api/worktrees/[id]/search/route.ts +343 -0
  279. package/.next/types/app/api/worktrees/[id]/send/route.ts +343 -0
  280. package/.next/types/app/api/worktrees/[id]/slash-commands/route.ts +343 -0
  281. package/.next/types/app/api/worktrees/[id]/start-polling/route.ts +343 -0
  282. package/.next/types/app/api/worktrees/[id]/terminal/route.ts +343 -0
  283. package/.next/types/app/api/worktrees/[id]/tree/[...path]/route.ts +343 -0
  284. package/.next/types/app/api/worktrees/[id]/tree/route.ts +343 -0
  285. package/.next/types/app/api/worktrees/[id]/upload/[...path]/route.ts +343 -0
  286. package/.next/types/app/api/worktrees/[id]/viewed/route.ts +343 -0
  287. package/.next/types/app/api/worktrees/route.ts +343 -0
  288. package/.next/types/app/page.ts +79 -0
  289. package/.next/types/app/proxy/[...path]/route.ts +343 -0
  290. package/.next/types/app/worktrees/[id]/files/[...path]/page.ts +79 -0
  291. package/.next/types/app/worktrees/[id]/page.ts +79 -0
  292. package/.next/types/app/worktrees/[id]/simple-terminal/page.ts +79 -0
  293. package/.next/types/app/worktrees/[id]/terminal/page.ts +79 -0
  294. package/.next/types/package.json +1 -0
  295. package/README.md +39 -8
  296. package/dist/server/server.js +123 -0
  297. package/dist/server/src/lib/claude-output.js +33 -0
  298. package/dist/server/src/lib/claude-session.js +312 -0
  299. package/dist/server/src/lib/cli-patterns.js +137 -0
  300. package/dist/server/src/lib/cli-session.js +73 -0
  301. package/dist/server/src/lib/cli-tools/base.js +51 -0
  302. package/dist/server/src/lib/cli-tools/claude.js +65 -0
  303. package/dist/server/src/lib/cli-tools/codex.js +132 -0
  304. package/dist/server/src/lib/cli-tools/gemini.js +122 -0
  305. package/dist/server/src/lib/cli-tools/index.js +22 -0
  306. package/dist/server/src/lib/cli-tools/manager.js +143 -0
  307. package/dist/server/src/lib/cli-tools/types.js +5 -0
  308. package/dist/server/src/lib/conversation-logger.js +25 -0
  309. package/dist/server/src/lib/db-instance.js +51 -0
  310. package/dist/server/src/lib/db-migrations.js +777 -0
  311. package/dist/server/src/lib/db.js +835 -0
  312. package/dist/server/src/lib/env.js +179 -0
  313. package/dist/server/src/lib/log-manager.js +234 -0
  314. package/dist/server/src/lib/logger.js +232 -0
  315. package/dist/server/src/lib/prompt-detector.js +285 -0
  316. package/dist/server/src/lib/response-poller.js +638 -0
  317. package/dist/server/src/lib/tmux.js +299 -0
  318. package/dist/server/src/lib/worktrees.js +231 -0
  319. package/dist/server/src/lib/ws-server.js +323 -0
  320. package/dist/server/src/types/clone.js +39 -0
  321. package/dist/server/src/types/conversation.js +9 -0
  322. package/dist/server/src/types/external-apps.js +6 -0
  323. package/dist/server/src/types/infinite-messages.js +65 -0
  324. package/dist/server/src/types/markdown-editor.js +94 -0
  325. package/dist/server/src/types/models.js +5 -0
  326. package/dist/server/src/types/sidebar.js +89 -0
  327. package/dist/server/src/types/slash-commands.js +47 -0
  328. package/dist/server/src/types/ui-actions.js +8 -0
  329. package/dist/server/src/types/ui-state.js +62 -0
  330. package/package.json +8 -4
package/README.md CHANGED
@@ -49,11 +49,43 @@ Claude Code での開発経験があり、本業の傍らで個人開発を続
49
49
 
50
50
  - macOS / Linux(tmux 依存のため Windows は非対応)
51
51
  - Node.js v20+、npm、git、tmux、openssl
52
- - Claude CLI(CLAUDE_HOOKS_STOP 対応)
52
+ - Claude CLI(オプション)
53
53
 
54
- > **Tip**: `./scripts/preflight-check.sh` で依存関係を確認できます。
54
+ ### インストール
55
55
 
56
- ### セットアップ
56
+ ```bash
57
+ npm install -g commandmate
58
+ ```
59
+
60
+ ### セットアップと起動
61
+
62
+ ```bash
63
+ commandmate init # 依存チェック、環境設定、DB初期化
64
+ commandmate start --daemon # バックグラウンドで起動
65
+ ```
66
+
67
+ ブラウザで http://localhost:3000 にアクセスしてください。
68
+
69
+ ### CLI コマンド
70
+
71
+ | コマンド | 説明 |
72
+ |---------|------|
73
+ | `commandmate init` | 初期設定(対話形式) |
74
+ | `commandmate init --defaults` | 初期設定(デフォルト値) |
75
+ | `commandmate start --daemon` | バックグラウンド起動 |
76
+ | `commandmate start -p 3001` | ポート指定で起動 |
77
+ | `commandmate stop` | サーバー停止 |
78
+ | `commandmate status` | 状態確認 |
79
+
80
+ 詳しくは [CLI セットアップガイド](./docs/user-guide/cli-setup-guide.md) を参照してください。
81
+
82
+ ### モバイルからのアクセス
83
+
84
+ `commandmate init` で外部アクセスを有効にすると、`CM_BIND=0.0.0.0` と `CM_AUTH_TOKEN` が自動設定されます。同一LAN内から `http://<PCのIP>:3000` にアクセスします。
85
+
86
+ ## 開発者向けセットアップ
87
+
88
+ コントリビューターや開発環境を構築する場合は、git clone を使用してください。
57
89
 
58
90
  ```bash
59
91
  git clone https://github.com/Kewton/CommandMate.git
@@ -61,8 +93,6 @@ cd CommandMate
61
93
  ./scripts/setup.sh # 依存チェック、環境設定、ビルド、起動まで自動実行
62
94
  ```
63
95
 
64
- ブラウザで http://localhost:3000 にアクセスしてください。
65
-
66
96
  ### 手動セットアップ(カスタマイズしたい場合)
67
97
 
68
98
  ```bash
@@ -76,7 +106,7 @@ npm run build
76
106
  npm start
77
107
  ```
78
108
 
79
- スマホから利用する場合は `./scripts/setup-env.sh` で外部アクセスを有効にすると、`CM_BIND=0.0.0.0` `CM_AUTH_TOKEN` が自動設定されます。同一LAN内から `http://<PCのIP>:3000` にアクセスします。
109
+ > **Note**: `./scripts/*` スクリプトは開発環境でのみ使用可能です。グローバルインストール(`npm install -g`)では `commandmate` CLI を使用してください。
80
110
 
81
111
  > **Note**: 旧名称の環境変数(`MCBD_*`)も後方互換性のためサポートされていますが、新名称(`CM_*`)の使用を推奨します。
82
112
 
@@ -104,13 +134,14 @@ A: 現時点では個人利用を想定しています。複数人での同時
104
134
 
105
135
  | ドキュメント | 説明 |
106
136
  |-------------|------|
137
+ | [CLI セットアップガイド](./docs/user-guide/cli-setup-guide.md) | インストールと初期設定 |
138
+ | [Webアプリ操作ガイド](./docs/user-guide/webapp-guide.md) | Webアプリの基本操作 |
139
+ | [クイックスタート](./docs/user-guide/quick-start.md) | Claude Codeコマンドの使い方 |
107
140
  | [コンセプト](./docs/concept.md) | ビジョンと解決する課題 |
108
141
  | [アーキテクチャ](./docs/architecture.md) | システム設計 |
109
142
  | [デプロイガイド](./docs/DEPLOYMENT.md) | 本番環境構築手順 |
110
143
  | [移行ガイド](./docs/migration-to-commandmate.md) | MyCodeBranchDesk からの移行手順 |
111
144
  | [UI/UXガイド](./docs/UI_UX_GUIDE.md) | UI実装の詳細 |
112
- | [Webアプリ操作ガイド](./docs/user-guide/webapp-guide.md) | Webアプリの基本操作 |
113
- | [クイックスタート](./docs/user-guide/quick-start.md) | Claude Codeコマンドの使い方 |
114
145
  | [Trust & Safety](./docs/TRUST_AND_SAFETY.md) | セキュリティと権限の考え方 |
115
146
 
116
147
  ## Contributing
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ /**
3
+ * Custom Next.js Server with WebSocket Support
4
+ * Integrates WebSocket server for real-time communication
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ // IMPORTANT: Register uncaught exception handler FIRST, before any imports
11
+ // This ensures we catch WebSocket frame errors before other handlers
12
+ process.on('uncaughtException', (error) => {
13
+ // Check for WebSocket-related errors that are non-fatal
14
+ const isWebSocketError = error.code === 'WS_ERR_INVALID_UTF8' ||
15
+ error.code === 'WS_ERR_INVALID_CLOSE_CODE' ||
16
+ error.code === 'WS_ERR_UNEXPECTED_RSV_1' ||
17
+ error.code === 'ECONNRESET' ||
18
+ error.code === 'EPIPE' ||
19
+ (error instanceof RangeError && error.message?.includes('Invalid WebSocket frame')) ||
20
+ error.message?.includes('write after end');
21
+ if (isWebSocketError) {
22
+ // Silently ignore these non-fatal WebSocket frame errors
23
+ // They commonly occur when mobile browsers send malformed close frames
24
+ return;
25
+ }
26
+ // For other uncaught exceptions, log and exit
27
+ console.error('Uncaught exception:', error);
28
+ process.exit(1);
29
+ });
30
+ const http_1 = require("http");
31
+ const url_1 = require("url");
32
+ const next_1 = __importDefault(require("next"));
33
+ const ws_server_1 = require("./src/lib/ws-server");
34
+ const worktrees_1 = require("./src/lib/worktrees");
35
+ const db_instance_1 = require("./src/lib/db-instance");
36
+ const response_poller_1 = require("./src/lib/response-poller");
37
+ const db_migrations_1 = require("./src/lib/db-migrations");
38
+ const env_1 = require("./src/lib/env");
39
+ const dev = process.env.NODE_ENV !== 'production';
40
+ const hostname = (0, env_1.getEnvByKey)('CM_BIND') || '127.0.0.1';
41
+ const port = parseInt((0, env_1.getEnvByKey)('CM_PORT') || '3000', 10);
42
+ // Create Next.js app
43
+ const app = (0, next_1.default)({ dev, hostname, port });
44
+ const handle = app.getRequestHandler();
45
+ app.prepare().then(() => {
46
+ // Create HTTP server
47
+ const server = (0, http_1.createServer)(async (req, res) => {
48
+ try {
49
+ const parsedUrl = (0, url_1.parse)(req.url, true);
50
+ await handle(req, res, parsedUrl);
51
+ }
52
+ catch (err) {
53
+ console.error('Error handling request', err);
54
+ res.statusCode = 500;
55
+ res.end('Internal Server Error');
56
+ }
57
+ });
58
+ // Setup WebSocket server
59
+ (0, ws_server_1.setupWebSocket)(server);
60
+ // Scan and sync worktrees on startup
61
+ async function initializeWorktrees() {
62
+ try {
63
+ // Run database migrations first
64
+ console.log('Running database migrations...');
65
+ const db = (0, db_instance_1.getDbInstance)();
66
+ (0, db_migrations_1.runMigrations)(db);
67
+ // Get repository paths from environment variables
68
+ const repositoryPaths = (0, worktrees_1.getRepositoryPaths)();
69
+ if (repositoryPaths.length === 0) {
70
+ console.warn('Warning: No repository paths configured');
71
+ console.warn('Set WORKTREE_REPOS (comma-separated) or MCBD_ROOT_DIR');
72
+ return;
73
+ }
74
+ console.log(`Configured repositories: ${repositoryPaths.length}`);
75
+ repositoryPaths.forEach((path, i) => {
76
+ console.log(` ${i + 1}. ${path}`);
77
+ });
78
+ // Scan all repositories
79
+ const worktrees = await (0, worktrees_1.scanMultipleRepositories)(repositoryPaths);
80
+ // Sync to database
81
+ (0, worktrees_1.syncWorktreesToDB)(db, worktrees);
82
+ console.log(`✓ Total: ${worktrees.length} worktree(s) synced to database`);
83
+ }
84
+ catch (error) {
85
+ console.error('Error initializing worktrees:', error);
86
+ }
87
+ }
88
+ server.listen(port, async (err) => {
89
+ if (err)
90
+ throw err;
91
+ console.log(`> Ready on http://${hostname}:${port}`);
92
+ console.log(`> WebSocket server ready`);
93
+ // Initialize worktrees after server starts
94
+ await initializeWorktrees();
95
+ });
96
+ // Graceful shutdown with timeout
97
+ let isShuttingDown = false;
98
+ function gracefulShutdown(signal) {
99
+ if (isShuttingDown) {
100
+ console.log('Shutdown already in progress, forcing exit...');
101
+ process.exit(1);
102
+ }
103
+ isShuttingDown = true;
104
+ console.log(`${signal} received: shutting down...`);
105
+ // Stop polling first
106
+ (0, response_poller_1.stopAllPolling)();
107
+ // Close WebSocket connections immediately (don't wait)
108
+ (0, ws_server_1.closeWebSocket)();
109
+ // Force exit after 3 seconds if graceful shutdown fails
110
+ const forceExitTimeout = setTimeout(() => {
111
+ console.log('Graceful shutdown timeout, forcing exit...');
112
+ process.exit(1);
113
+ }, 3000);
114
+ // Try graceful HTTP server close
115
+ server.close(() => {
116
+ clearTimeout(forceExitTimeout);
117
+ console.log('Server closed gracefully');
118
+ process.exit(0);
119
+ });
120
+ }
121
+ process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
122
+ process.on('SIGINT', () => gracefulShutdown('SIGINT'));
123
+ });
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ /**
3
+ * Claude output parsing utilities
4
+ * Shared between webhook handlers and polling logic
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.parseClaudeOutput = parseClaudeOutput;
8
+ const LOG_FILE_REGEX = /📄 Session log: (.+?\/([^\/\s]+\.jsonl))/;
9
+ const REQUEST_ID_REGEX = /Request ID: ([^\s\n]+)/;
10
+ const SUMMARY_REGEX = /Summary: (.+?)(?:\n─|$)/s;
11
+ /**
12
+ * Parse Claude CLI output and extract metadata that the UI relies on.
13
+ *
14
+ * @param output Raw tmux capture string
15
+ */
16
+ function parseClaudeOutput(output) {
17
+ const result = {
18
+ content: output,
19
+ };
20
+ const logFileMatch = LOG_FILE_REGEX.exec(output);
21
+ if (logFileMatch) {
22
+ result.logFileName = logFileMatch[2];
23
+ }
24
+ const requestIdMatch = REQUEST_ID_REGEX.exec(output);
25
+ if (requestIdMatch) {
26
+ result.requestId = requestIdMatch[1];
27
+ }
28
+ const summaryMatch = SUMMARY_REGEX.exec(output);
29
+ if (summaryMatch) {
30
+ result.summary = summaryMatch[1].trim();
31
+ }
32
+ return result;
33
+ }
@@ -0,0 +1,312 @@
1
+ "use strict";
2
+ /**
3
+ * Claude CLI session management
4
+ * Manages Claude CLI sessions within tmux for each worktree
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.getSessionName = getSessionName;
8
+ exports.isClaudeInstalled = isClaudeInstalled;
9
+ exports.isClaudeRunning = isClaudeRunning;
10
+ exports.getClaudeSessionState = getClaudeSessionState;
11
+ exports.startClaudeSession = startClaudeSession;
12
+ exports.sendMessageToClaude = sendMessageToClaude;
13
+ exports.captureClaudeOutput = captureClaudeOutput;
14
+ exports.stopClaudeSession = stopClaudeSession;
15
+ exports.restartClaudeSession = restartClaudeSession;
16
+ const tmux_1 = require("./tmux");
17
+ const child_process_1 = require("child_process");
18
+ const util_1 = require("util");
19
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
20
+ /**
21
+ * Cached Claude CLI path
22
+ */
23
+ let cachedClaudePath = null;
24
+ /**
25
+ * Get Claude CLI path dynamically
26
+ * Uses CLAUDE_PATH environment variable if set, otherwise finds via 'which'
27
+ */
28
+ async function getClaudePath() {
29
+ // Return cached path if available
30
+ if (cachedClaudePath) {
31
+ return cachedClaudePath;
32
+ }
33
+ // Check environment variable first
34
+ if (process.env.CLAUDE_PATH) {
35
+ cachedClaudePath = process.env.CLAUDE_PATH;
36
+ return cachedClaudePath;
37
+ }
38
+ // Find claude via 'which' command
39
+ try {
40
+ const { stdout } = await execAsync('which claude', { timeout: 5000 });
41
+ cachedClaudePath = stdout.trim();
42
+ return cachedClaudePath;
43
+ }
44
+ catch {
45
+ // Fallback to common paths
46
+ const fallbackPaths = [
47
+ '/opt/homebrew/bin/claude', // macOS Homebrew (Apple Silicon)
48
+ '/usr/local/bin/claude', // macOS Homebrew (Intel) / Linux
49
+ '/usr/bin/claude', // Linux system install
50
+ ];
51
+ for (const path of fallbackPaths) {
52
+ try {
53
+ await execAsync(`test -x "${path}"`, { timeout: 1000 });
54
+ cachedClaudePath = path;
55
+ return cachedClaudePath;
56
+ }
57
+ catch {
58
+ // Path not found, try next
59
+ }
60
+ }
61
+ throw new Error('Claude CLI not found. Set CLAUDE_PATH environment variable or install Claude CLI.');
62
+ }
63
+ }
64
+ /**
65
+ * Get tmux session name for a worktree
66
+ *
67
+ * @param worktreeId - Worktree ID
68
+ * @returns tmux session name
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * getSessionName('feature-foo') // => 'mcbd-claude-feature-foo'
73
+ * ```
74
+ */
75
+ function getSessionName(worktreeId) {
76
+ return `mcbd-claude-${worktreeId}`;
77
+ }
78
+ /**
79
+ * Check if Claude is installed and available
80
+ *
81
+ * @returns True if Claude CLI is available
82
+ */
83
+ async function isClaudeInstalled() {
84
+ try {
85
+ await execAsync('which claude', { timeout: 5000 });
86
+ return true;
87
+ }
88
+ catch {
89
+ return false;
90
+ }
91
+ }
92
+ /**
93
+ * Check if Claude session is running
94
+ *
95
+ * @param worktreeId - Worktree ID
96
+ * @returns True if Claude session exists and is running
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * const running = await isClaudeRunning('feature-foo');
101
+ * if (running) {
102
+ * console.log('Claude is ready');
103
+ * }
104
+ * ```
105
+ */
106
+ async function isClaudeRunning(worktreeId) {
107
+ const sessionName = getSessionName(worktreeId);
108
+ return await (0, tmux_1.hasSession)(sessionName);
109
+ }
110
+ /**
111
+ * Get Claude session state
112
+ *
113
+ * @param worktreeId - Worktree ID
114
+ * @returns Session state information
115
+ */
116
+ async function getClaudeSessionState(worktreeId) {
117
+ const sessionName = getSessionName(worktreeId);
118
+ const isRunning = await (0, tmux_1.hasSession)(sessionName);
119
+ return {
120
+ sessionName,
121
+ isRunning,
122
+ lastActivity: new Date(),
123
+ };
124
+ }
125
+ /**
126
+ * Start a Claude CLI session in tmux
127
+ *
128
+ * @param options - Session options
129
+ * @throws {Error} If Claude CLI is not installed or session creation fails
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * await startClaudeSession({
134
+ * worktreeId: 'feature-foo',
135
+ * worktreePath: '/path/to/worktree',
136
+ * baseUrl: 'http://localhost:3000',
137
+ * });
138
+ * ```
139
+ */
140
+ async function startClaudeSession(options) {
141
+ const { worktreeId, worktreePath } = options;
142
+ // Check if Claude is installed
143
+ const claudeAvailable = await isClaudeInstalled();
144
+ if (!claudeAvailable) {
145
+ throw new Error('Claude CLI is not installed or not in PATH');
146
+ }
147
+ const sessionName = getSessionName(worktreeId);
148
+ // Check if session already exists
149
+ const exists = await (0, tmux_1.hasSession)(sessionName);
150
+ if (exists) {
151
+ console.log(`Claude session ${sessionName} already exists`);
152
+ return;
153
+ }
154
+ try {
155
+ // Create tmux session with large history buffer for Claude output
156
+ await (0, tmux_1.createSession)({
157
+ sessionName,
158
+ workingDirectory: worktreePath,
159
+ historyLimit: 50000,
160
+ });
161
+ // Get Claude CLI path dynamically
162
+ const claudePath = await getClaudePath();
163
+ // Start Claude CLI in interactive mode using dynamically resolved path
164
+ await (0, tmux_1.sendKeys)(sessionName, claudePath, true);
165
+ // Wait for Claude to initialize with dynamic detection
166
+ // Check for Claude prompt instead of fixed delay
167
+ const maxWaitTime = 10000; // 10 seconds max
168
+ const pollInterval = 500; // Check every 500ms
169
+ const startTime = Date.now();
170
+ while (Date.now() - startTime < maxWaitTime) {
171
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
172
+ try {
173
+ const output = await (0, tmux_1.capturePane)(sessionName, { startLine: -50 });
174
+ // Claude is ready when we see the prompt (> ) or separator line
175
+ if (/^>\s*$/m.test(output) || /^─{10,}$/m.test(output)) {
176
+ console.log(`✓ Claude initialized in ${Date.now() - startTime}ms`);
177
+ break;
178
+ }
179
+ }
180
+ catch {
181
+ // Ignore capture errors during initialization
182
+ }
183
+ }
184
+ console.log(`✓ Started Claude session: ${sessionName}`);
185
+ }
186
+ catch (error) {
187
+ const errorMessage = error instanceof Error ? error.message : String(error);
188
+ throw new Error(`Failed to start Claude session: ${errorMessage}`);
189
+ }
190
+ }
191
+ /**
192
+ * Send a message to Claude CLI
193
+ *
194
+ * @param worktreeId - Worktree ID
195
+ * @param message - Message content to send
196
+ * @throws {Error} If session doesn't exist
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * await sendMessageToClaude('feature-foo', 'Explain this code');
201
+ * ```
202
+ */
203
+ async function sendMessageToClaude(worktreeId, message) {
204
+ const sessionName = getSessionName(worktreeId);
205
+ // Check if session exists
206
+ const exists = await (0, tmux_1.hasSession)(sessionName);
207
+ if (!exists) {
208
+ throw new Error(`Claude session ${sessionName} does not exist. Start the session first.`);
209
+ }
210
+ try {
211
+ // Send message to Claude (without Enter)
212
+ await (0, tmux_1.sendKeys)(sessionName, message, false);
213
+ // Wait a moment for the text to be typed
214
+ await new Promise((resolve) => setTimeout(resolve, 100));
215
+ // Send Enter key to submit (single Enter submits in Claude Code CLI)
216
+ await execAsync(`tmux send-keys -t "${sessionName}" C-m`);
217
+ // Wait a moment for the message to be processed
218
+ await new Promise((resolve) => setTimeout(resolve, 200));
219
+ console.log(`✓ Sent message to Claude session: ${sessionName}`);
220
+ }
221
+ catch (error) {
222
+ const errorMessage = error instanceof Error ? error.message : String(error);
223
+ throw new Error(`Failed to send message to Claude: ${errorMessage}`);
224
+ }
225
+ }
226
+ /**
227
+ * Capture Claude session output
228
+ *
229
+ * @param worktreeId - Worktree ID
230
+ * @param lines - Number of lines to capture (default: 1000)
231
+ * @returns Captured output
232
+ *
233
+ * @example
234
+ * ```typescript
235
+ * const output = await captureClaudeOutput('feature-foo');
236
+ * console.log(output);
237
+ * ```
238
+ */
239
+ async function captureClaudeOutput(worktreeId, lines = 1000) {
240
+ const sessionName = getSessionName(worktreeId);
241
+ // Check if session exists
242
+ const exists = await (0, tmux_1.hasSession)(sessionName);
243
+ if (!exists) {
244
+ throw new Error(`Claude session ${sessionName} does not exist`);
245
+ }
246
+ try {
247
+ return await (0, tmux_1.capturePane)(sessionName, { startLine: -lines });
248
+ }
249
+ catch (error) {
250
+ const errorMessage = error instanceof Error ? error.message : String(error);
251
+ throw new Error(`Failed to capture Claude output: ${errorMessage}`);
252
+ }
253
+ }
254
+ /**
255
+ * Stop a Claude session
256
+ *
257
+ * @param worktreeId - Worktree ID
258
+ * @returns True if session was stopped, false if it didn't exist
259
+ *
260
+ * @example
261
+ * ```typescript
262
+ * await stopClaudeSession('feature-foo');
263
+ * ```
264
+ */
265
+ async function stopClaudeSession(worktreeId) {
266
+ const sessionName = getSessionName(worktreeId);
267
+ try {
268
+ // Send Ctrl+D to exit Claude gracefully
269
+ const exists = await (0, tmux_1.hasSession)(sessionName);
270
+ if (exists) {
271
+ await (0, tmux_1.sendKeys)(sessionName, '', false);
272
+ // Send Ctrl+D (ASCII 4)
273
+ await execAsync(`tmux send-keys -t "${sessionName}" C-d`);
274
+ // Wait a moment for Claude to exit
275
+ await new Promise((resolve) => setTimeout(resolve, 500));
276
+ }
277
+ // Kill the tmux session
278
+ const killed = await (0, tmux_1.killSession)(sessionName);
279
+ if (killed) {
280
+ console.log(`✓ Stopped Claude session: ${sessionName}`);
281
+ }
282
+ return killed;
283
+ }
284
+ catch (error) {
285
+ const errorMessage = error instanceof Error ? error.message : String(error);
286
+ console.error(`Error stopping Claude session: ${errorMessage}`);
287
+ return false;
288
+ }
289
+ }
290
+ /**
291
+ * Restart a Claude session
292
+ *
293
+ * @param options - Session options
294
+ *
295
+ * @example
296
+ * ```typescript
297
+ * await restartClaudeSession({
298
+ * worktreeId: 'feature-foo',
299
+ * worktreePath: '/path/to/worktree',
300
+ * baseUrl: 'http://localhost:3000',
301
+ * });
302
+ * ```
303
+ */
304
+ async function restartClaudeSession(options) {
305
+ const { worktreeId } = options;
306
+ // Stop existing session
307
+ await stopClaudeSession(worktreeId);
308
+ // Wait a moment before restarting
309
+ await new Promise((resolve) => setTimeout(resolve, 1000));
310
+ // Start new session
311
+ await startClaudeSession(options);
312
+ }
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ /**
3
+ * Common CLI tool patterns for response detection
4
+ * Shared between response-poller.ts and API routes
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.GEMINI_PROMPT_PATTERN = exports.CODEX_SEPARATOR_PATTERN = exports.CODEX_PROMPT_PATTERN = exports.CLAUDE_SEPARATOR_PATTERN = exports.CLAUDE_PROMPT_PATTERN = exports.CODEX_THINKING_PATTERN = exports.CLAUDE_THINKING_PATTERN = exports.CLAUDE_SPINNER_CHARS = void 0;
8
+ exports.detectThinking = detectThinking;
9
+ exports.getCliToolPatterns = getCliToolPatterns;
10
+ exports.stripAnsi = stripAnsi;
11
+ const logger_1 = require("./logger");
12
+ const logger = (0, logger_1.createLogger)('cli-patterns');
13
+ /**
14
+ * Claude CLI spinner characters (expanded set)
15
+ * These are shown when Claude is thinking/processing
16
+ */
17
+ exports.CLAUDE_SPINNER_CHARS = [
18
+ '✻', '✽', '⏺', '·', '∴', '✢', '✳', '✶',
19
+ '⦿', '◉', '●', '○', '◌', '◎', '⊙', '⊚',
20
+ '⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏', // Braille spinner
21
+ ];
22
+ /**
23
+ * Claude thinking pattern
24
+ * Matches spinner character followed by activity text ending with …
25
+ * The text can contain spaces (e.g., "Verifying implementation (dead code detection)…")
26
+ */
27
+ exports.CLAUDE_THINKING_PATTERN = new RegExp(`[${exports.CLAUDE_SPINNER_CHARS.join('')}]\\s+.+…|to interrupt\\)`, 'm');
28
+ /**
29
+ * Codex thinking pattern
30
+ * Matches activity indicators like "• Planning", "• Searching", etc.
31
+ */
32
+ exports.CODEX_THINKING_PATTERN = /•\s*(Planning|Searching|Exploring|Running|Thinking|Working|Reading|Writing|Analyzing)/m;
33
+ /**
34
+ * Claude prompt pattern (waiting for input)
35
+ * Supports both legacy '>' and new '❯' (U+276F) prompt characters
36
+ */
37
+ exports.CLAUDE_PROMPT_PATTERN = /^[>❯]\s*$/m;
38
+ /**
39
+ * Claude separator pattern
40
+ */
41
+ exports.CLAUDE_SEPARATOR_PATTERN = /^─{10,}$/m;
42
+ /**
43
+ * Codex prompt pattern
44
+ */
45
+ exports.CODEX_PROMPT_PATTERN = /^›\s+.+/m;
46
+ /**
47
+ * Codex separator pattern
48
+ */
49
+ exports.CODEX_SEPARATOR_PATTERN = /^─.*Worked for.*─+$/m;
50
+ /**
51
+ * Gemini shell prompt pattern
52
+ */
53
+ exports.GEMINI_PROMPT_PATTERN = /^(%|\$|.*@.*[%$#])\s*$/m;
54
+ /**
55
+ * Detect if CLI tool is showing "thinking" indicator
56
+ */
57
+ function detectThinking(cliToolId, content) {
58
+ const log = logger.withContext({ cliToolId });
59
+ log.debug('detectThinking:check', { contentLength: content.length });
60
+ let result;
61
+ switch (cliToolId) {
62
+ case 'claude':
63
+ result = exports.CLAUDE_THINKING_PATTERN.test(content);
64
+ break;
65
+ case 'codex':
66
+ result = exports.CODEX_THINKING_PATTERN.test(content);
67
+ break;
68
+ case 'gemini':
69
+ // Gemini doesn't have a thinking indicator in one-shot mode
70
+ result = false;
71
+ break;
72
+ default:
73
+ result = exports.CLAUDE_THINKING_PATTERN.test(content);
74
+ }
75
+ log.debug('detectThinking:result', { isThinking: result });
76
+ return result;
77
+ }
78
+ /**
79
+ * Get CLI tool patterns for response extraction
80
+ */
81
+ function getCliToolPatterns(cliToolId) {
82
+ switch (cliToolId) {
83
+ case 'claude':
84
+ return {
85
+ promptPattern: exports.CLAUDE_PROMPT_PATTERN,
86
+ separatorPattern: exports.CLAUDE_SEPARATOR_PATTERN,
87
+ thinkingPattern: exports.CLAUDE_THINKING_PATTERN,
88
+ skipPatterns: [
89
+ /^─{10,}$/, // Separator lines
90
+ /^[>❯]\s*$/, // Prompt line (legacy '>' and new '❯')
91
+ exports.CLAUDE_THINKING_PATTERN, // Thinking indicators
92
+ /^\s*[⎿⏋]\s+Tip:/, // Tip lines
93
+ /^\s*Tip:/, // Tip lines
94
+ /^\s*\?\s*for shortcuts/, // Shortcuts hint
95
+ /to interrupt\)/, // Part of "esc to interrupt" message
96
+ ],
97
+ };
98
+ case 'codex':
99
+ return {
100
+ promptPattern: exports.CODEX_PROMPT_PATTERN,
101
+ separatorPattern: exports.CODEX_SEPARATOR_PATTERN,
102
+ thinkingPattern: exports.CODEX_THINKING_PATTERN,
103
+ skipPatterns: [
104
+ /^─.*─+$/, // Separator lines
105
+ /^›\s*$/, // Empty prompt line
106
+ /^›\s+(Implement|Find and fix|Type)/, // New prompt suggestions
107
+ exports.CODEX_THINKING_PATTERN, // Activity indicators
108
+ /^\s*\d+%\s+context left/, // Context indicator
109
+ /^\s*for shortcuts$/, // Shortcuts hint
110
+ /╭─+╮/, // Box drawing (top)
111
+ /╰─+╯/, // Box drawing (bottom)
112
+ ],
113
+ };
114
+ case 'gemini':
115
+ return {
116
+ promptPattern: exports.GEMINI_PROMPT_PATTERN,
117
+ separatorPattern: /^gemini\s+--\s+/m,
118
+ thinkingPattern: /(?!)/m, // Never matches - one-shot execution
119
+ skipPatterns: [
120
+ /^gemini\s+--\s+/, // Command line itself
121
+ exports.GEMINI_PROMPT_PATTERN, // Shell prompt lines
122
+ /^\s*$/, // Empty lines
123
+ ],
124
+ };
125
+ default:
126
+ // Default to Claude patterns
127
+ return getCliToolPatterns('claude');
128
+ }
129
+ }
130
+ /**
131
+ * Strip ANSI escape codes from a string
132
+ * Optimized version at module level for performance
133
+ */
134
+ const ANSI_PATTERN = /\x1b\[[0-9;]*[a-zA-Z]|\x1b\][^\x07]*\x07|\[[0-9;]*m/g;
135
+ function stripAnsi(str) {
136
+ return str.replace(ANSI_PATTERN, '');
137
+ }