commandmate 0.1.5 → 0.1.7

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 (341) 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/3jNZMmFnQhc5G7met-OU4/_buildManifest.js +1 -0
  178. package/.next/static/3jNZMmFnQhc5G7met-OU4/_ssgManifest.js +1 -0
  179. package/.next/static/chunks/0dbeb660.3e800dfbd28be3bd.js +53 -0
  180. package/.next/static/chunks/1015.0eaa4da7f61149bc.js +59 -0
  181. package/.next/static/chunks/1098.49268c9fe1b028fa.js +1 -0
  182. package/.next/static/chunks/13.feeafc7cc620f8c4.js +1 -0
  183. package/.next/static/chunks/1423.7b1e8bf760d28078.js +1 -0
  184. package/.next/static/chunks/1582.9f8590f71ff798ca.js +55 -0
  185. package/.next/static/chunks/1817.a66d96cedb761daa.js +262 -0
  186. package/.next/static/chunks/2117-d845c2cd62e344a6.js +2 -0
  187. package/.next/static/chunks/2398.0b21e4eb7006a230.js +93 -0
  188. package/.next/static/chunks/2526.8ac62b527c9ab703.js +43 -0
  189. package/.next/static/chunks/2626.2125083a1ff3b80a.js +29 -0
  190. package/.next/static/chunks/2689.720a4874b02d4211.js +174 -0
  191. package/.next/static/chunks/2853-d11a80b03c9a1640.js +1 -0
  192. package/.next/static/chunks/2957-327e43ef4c12808f.js +1 -0
  193. package/.next/static/chunks/2cdb6380.35626fc6e41bbba4.js +136 -0
  194. package/.next/static/chunks/30d07d85-393352a92199f695.js +3 -0
  195. package/.next/static/chunks/3559.f073f72c4466ce0e.js +1 -0
  196. package/.next/static/chunks/3574.7a94c27e6a496a56.js +63 -0
  197. package/.next/static/chunks/383.20683891c9a5f2c4.js +4 -0
  198. package/.next/static/chunks/3843.3fdda732987f7bb8.js +1 -0
  199. package/.next/static/chunks/3852.822389f445c9b427.js +1 -0
  200. package/.next/static/chunks/3991.4bc063cb5be3a86c.js +1 -0
  201. package/.next/static/chunks/4212.52c1bb34fc97d0d0.js +131 -0
  202. package/.next/static/chunks/4327.3b84aa049900fdeb.js +60 -0
  203. package/.next/static/chunks/4362.7bd6f0282e49d79b.js +1 -0
  204. package/.next/static/chunks/4721.40615a5f4f32b5fb.js +1 -0
  205. package/.next/static/chunks/4851-45df4d388db5623f.js +1 -0
  206. package/.next/static/chunks/5112.17318d1c6b28044b.js +1 -0
  207. package/.next/static/chunks/5126.93fa4e797d609286.js +56 -0
  208. package/.next/static/chunks/5387.47590ac4ef66c864.js +5 -0
  209. package/.next/static/chunks/5813.4483664ba482beb1.js +1 -0
  210. package/.next/static/chunks/6143.1450875bd03a2366.js +36 -0
  211. package/.next/static/chunks/6406.9653f0d41ab85059.js +1 -0
  212. package/.next/static/chunks/656.d72f25ce819bd77e.js +149 -0
  213. package/.next/static/chunks/6678.492e73ca42b2a273.js +62 -0
  214. package/.next/static/chunks/6725-f7607851b7d57eb1.js +1 -0
  215. package/.next/static/chunks/6792.3c01ac4dda4b5c6d.js +1 -0
  216. package/.next/static/chunks/7004.808cbf327ef5955e.js +1 -0
  217. package/.next/static/chunks/7290.09ef84cf94f90c4d.js +1 -0
  218. package/.next/static/chunks/7415.6b481c2baf363262.js +148 -0
  219. package/.next/static/chunks/7648-325564a6e12a3257.js +1 -0
  220. package/.next/static/chunks/7665.47fccad04449a8f9.js +215 -0
  221. package/.next/static/chunks/7753.6bdce86b7fde3d10.js +166 -0
  222. package/.next/static/chunks/8125.245a9df052d274fb.js +1 -0
  223. package/.next/static/chunks/816-7e340dad784be28c.js +1 -0
  224. package/.next/static/chunks/8288.4883743fa40672e2.js +24 -0
  225. package/.next/static/chunks/8522.1607e96011c66877.js +1 -0
  226. package/.next/static/chunks/8772.863c564498d88487.js +1 -0
  227. package/.next/static/chunks/8841.dadeb1ece8e46004.js +1 -0
  228. package/.next/static/chunks/8885.f8d9912b40d74811.js +1 -0
  229. package/.next/static/chunks/90542734.c1553d0fe7fc14fc.js +1 -0
  230. package/.next/static/chunks/9365-733d8c05712d2888.js +1 -0
  231. package/.next/static/chunks/9552.b7dfb7903ead934b.js +1 -0
  232. package/.next/static/chunks/9834.295b45635ce04f5e.js +24 -0
  233. package/.next/static/chunks/app/_not-found/page-a9d04e58c81115ec.js +1 -0
  234. package/.next/static/chunks/app/layout-37e55f11dcc8b1bf.js +1 -0
  235. package/.next/static/chunks/app/page-9cd00de9cc0abc43.js +1 -0
  236. package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-9e5adf57cbbbdf05.js +1 -0
  237. package/.next/static/chunks/app/worktrees/[id]/page-8c6676303b63fdaf.js +1 -0
  238. package/.next/static/chunks/app/worktrees/[id]/simple-terminal/page-16feb3e86e42f4d1.js +1 -0
  239. package/.next/static/chunks/app/worktrees/[id]/terminal/page-be802baffc84dbd2.js +1 -0
  240. package/.next/static/chunks/d3ac728e.6c9c508274d4d2d5.js +1 -0
  241. package/.next/static/chunks/fd9d1056-bbe86e4ae099d5cd.js +1 -0
  242. package/.next/static/chunks/framework-8e0e0f4a6b83a956.js +1 -0
  243. package/.next/static/chunks/main-a960f4a5e1a2f598.js +1 -0
  244. package/.next/static/chunks/main-app-420d93e43682fee5.js +1 -0
  245. package/.next/static/chunks/pages/_app-3c9ca398d360b709.js +1 -0
  246. package/.next/static/chunks/pages/_error-cf5ca766ac8f493f.js +1 -0
  247. package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  248. package/.next/static/chunks/webpack-3fc79fab9bb738d7.js +1 -0
  249. package/.next/static/css/5eacd01f773eed7f.css +11 -0
  250. package/.next/static/css/85fa6dafca566008.css +1 -0
  251. package/.next/static/css/e174aa24f94ce607.css +3 -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/cli/commands/init.d.ts +1 -0
  297. package/dist/cli/commands/init.d.ts.map +1 -1
  298. package/dist/cli/commands/init.js +143 -27
  299. package/dist/cli/types/index.d.ts +18 -0
  300. package/dist/cli/types/index.d.ts.map +1 -1
  301. package/dist/cli/utils/env-setup.d.ts +25 -0
  302. package/dist/cli/utils/env-setup.d.ts.map +1 -1
  303. package/dist/cli/utils/env-setup.js +56 -1
  304. package/dist/cli/utils/prompt.d.ts +68 -0
  305. package/dist/cli/utils/prompt.d.ts.map +1 -0
  306. package/dist/cli/utils/prompt.js +208 -0
  307. package/dist/server/server.js +123 -0
  308. package/dist/server/src/lib/claude-output.js +33 -0
  309. package/dist/server/src/lib/claude-session.js +312 -0
  310. package/dist/server/src/lib/cli-patterns.js +137 -0
  311. package/dist/server/src/lib/cli-session.js +73 -0
  312. package/dist/server/src/lib/cli-tools/base.js +51 -0
  313. package/dist/server/src/lib/cli-tools/claude.js +65 -0
  314. package/dist/server/src/lib/cli-tools/codex.js +132 -0
  315. package/dist/server/src/lib/cli-tools/gemini.js +122 -0
  316. package/dist/server/src/lib/cli-tools/index.js +22 -0
  317. package/dist/server/src/lib/cli-tools/manager.js +143 -0
  318. package/dist/server/src/lib/cli-tools/types.js +5 -0
  319. package/dist/server/src/lib/conversation-logger.js +25 -0
  320. package/dist/server/src/lib/db-instance.js +51 -0
  321. package/dist/server/src/lib/db-migrations.js +777 -0
  322. package/dist/server/src/lib/db.js +835 -0
  323. package/dist/server/src/lib/env.js +179 -0
  324. package/dist/server/src/lib/log-manager.js +234 -0
  325. package/dist/server/src/lib/logger.js +232 -0
  326. package/dist/server/src/lib/prompt-detector.js +285 -0
  327. package/dist/server/src/lib/response-poller.js +638 -0
  328. package/dist/server/src/lib/tmux.js +299 -0
  329. package/dist/server/src/lib/worktrees.js +231 -0
  330. package/dist/server/src/lib/ws-server.js +323 -0
  331. package/dist/server/src/types/clone.js +39 -0
  332. package/dist/server/src/types/conversation.js +9 -0
  333. package/dist/server/src/types/external-apps.js +6 -0
  334. package/dist/server/src/types/infinite-messages.js +65 -0
  335. package/dist/server/src/types/markdown-editor.js +94 -0
  336. package/dist/server/src/types/models.js +5 -0
  337. package/dist/server/src/types/sidebar.js +89 -0
  338. package/dist/server/src/types/slash-commands.js +47 -0
  339. package/dist/server/src/types/ui-actions.js +8 -0
  340. package/dist/server/src/types/ui-state.js +62 -0
  341. package/package.json +8 -4
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+ /**
3
+ * Interactive Prompt Utilities
4
+ * Issue #119: Interactive init support
5
+ *
6
+ * Provides readline-based prompts for CLI commands.
7
+ * Reference implementation: scripts/setup-env.sh
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.closeReadline = closeReadline;
44
+ exports.expandTilde = expandTilde;
45
+ exports.resolvePath = resolvePath;
46
+ exports.validatePort = validatePort;
47
+ exports.prompt = prompt;
48
+ exports.confirm = confirm;
49
+ exports.isInteractive = isInteractive;
50
+ const readline = __importStar(require("readline"));
51
+ const os_1 = require("os");
52
+ const path_1 = require("path");
53
+ /**
54
+ * Readline interface singleton
55
+ * Reused across prompts to avoid creating multiple interfaces
56
+ */
57
+ let rlInstance = null;
58
+ /**
59
+ * Get or create readline interface
60
+ */
61
+ function getReadlineInterface() {
62
+ if (!rlInstance) {
63
+ rlInstance = readline.createInterface({
64
+ input: process.stdin,
65
+ output: process.stdout,
66
+ });
67
+ }
68
+ return rlInstance;
69
+ }
70
+ /**
71
+ * Close readline interface
72
+ * Should be called when all prompts are done
73
+ */
74
+ function closeReadline() {
75
+ if (rlInstance) {
76
+ rlInstance.close();
77
+ rlInstance = null;
78
+ }
79
+ }
80
+ /**
81
+ * Expand tilde (~) to home directory
82
+ *
83
+ * @param path - Path that may contain tilde
84
+ * @returns Path with tilde expanded to home directory
85
+ *
86
+ * @example
87
+ * expandTilde('~/repos') // '/Users/xxx/repos'
88
+ * expandTilde('/absolute/path') // '/absolute/path'
89
+ */
90
+ function expandTilde(path) {
91
+ if (path.startsWith('~/')) {
92
+ return path.replace(/^~/, (0, os_1.homedir)());
93
+ }
94
+ if (path === '~') {
95
+ return (0, os_1.homedir)();
96
+ }
97
+ return path;
98
+ }
99
+ /**
100
+ * Resolve path to absolute path
101
+ * Handles tilde expansion and relative paths
102
+ *
103
+ * @param path - Path to resolve
104
+ * @returns Absolute path
105
+ */
106
+ function resolvePath(path) {
107
+ const expanded = expandTilde(path);
108
+ return (0, path_1.resolve)(expanded);
109
+ }
110
+ /**
111
+ * Validate port number
112
+ *
113
+ * @param input - Port number as string
114
+ * @returns Error message or true if valid
115
+ */
116
+ function validatePort(input) {
117
+ const port = parseInt(input, 10);
118
+ if (isNaN(port)) {
119
+ return 'Port must be a number';
120
+ }
121
+ if (port < 1 || port > 65535) {
122
+ return 'Port must be between 1 and 65535';
123
+ }
124
+ return true;
125
+ }
126
+ /**
127
+ * Interactive prompt with default value and validation
128
+ *
129
+ * @param question - Question to display
130
+ * @param options - Prompt options (default, validate)
131
+ * @returns User input or default value
132
+ *
133
+ * @example
134
+ * const port = await prompt('Server port', { default: '3000', validate: validatePort });
135
+ */
136
+ async function prompt(question, options = {}) {
137
+ const rl = getReadlineInterface();
138
+ const { default: defaultValue, validate } = options;
139
+ const displayQuestion = defaultValue
140
+ ? `? ${question} [${defaultValue}]: `
141
+ : `? ${question}: `;
142
+ return new Promise((resolvePromise) => {
143
+ const askQuestion = () => {
144
+ rl.question(displayQuestion, (answer) => {
145
+ const trimmedAnswer = answer.trim();
146
+ const result = trimmedAnswer || defaultValue || '';
147
+ // Validate if validator provided
148
+ if (validate && result) {
149
+ const validationResult = validate(result);
150
+ if (validationResult !== true) {
151
+ console.log(` Error: ${validationResult}`);
152
+ askQuestion(); // Re-ask
153
+ return;
154
+ }
155
+ }
156
+ resolvePromise(result);
157
+ });
158
+ };
159
+ askQuestion();
160
+ });
161
+ }
162
+ /**
163
+ * Interactive Yes/No confirmation
164
+ *
165
+ * @param question - Question to display
166
+ * @param options - Confirm options (default)
167
+ * @returns true for Yes, false for No
168
+ *
169
+ * @example
170
+ * const enableExternal = await confirm('Enable external access?', { default: false });
171
+ */
172
+ async function confirm(question, options = {}) {
173
+ const rl = getReadlineInterface();
174
+ const defaultValue = options.default ?? false;
175
+ const hint = defaultValue ? '(Y/n)' : '(y/N)';
176
+ const displayQuestion = `? ${question} ${hint}: `;
177
+ return new Promise((resolvePromise) => {
178
+ const askQuestion = () => {
179
+ rl.question(displayQuestion, (answer) => {
180
+ const trimmedAnswer = answer.trim().toLowerCase();
181
+ if (trimmedAnswer === '') {
182
+ resolvePromise(defaultValue);
183
+ return;
184
+ }
185
+ if (trimmedAnswer === 'y' || trimmedAnswer === 'yes') {
186
+ resolvePromise(true);
187
+ return;
188
+ }
189
+ if (trimmedAnswer === 'n' || trimmedAnswer === 'no') {
190
+ resolvePromise(false);
191
+ return;
192
+ }
193
+ // Invalid input - re-ask
194
+ console.log(' Please answer with y/n or yes/no');
195
+ askQuestion();
196
+ });
197
+ };
198
+ askQuestion();
199
+ });
200
+ }
201
+ /**
202
+ * Check if running in interactive mode (TTY)
203
+ *
204
+ * @returns true if stdin is a TTY (interactive terminal)
205
+ */
206
+ function isInteractive() {
207
+ return process.stdin.isTTY === true;
208
+ }
@@ -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
+ }