tmux-ide 2.1.4 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (805) hide show
  1. package/README.md +115 -101
  2. package/bin/cli.js +13678 -4
  3. package/bin/cli.ts +1143 -260
  4. package/package.json +27 -17
  5. package/packages/daemon/dist/__tests__/support.d.ts +7 -0
  6. package/packages/daemon/dist/__tests__/support.js +33 -0
  7. package/packages/daemon/dist/agent-explain.d.ts +45 -0
  8. package/packages/daemon/dist/agent-explain.js +210 -0
  9. package/packages/daemon/dist/attach.d.ts +3 -0
  10. package/packages/daemon/dist/attach.js +14 -0
  11. package/packages/daemon/dist/bin.d.ts +2 -0
  12. package/packages/daemon/dist/bin.js +3 -0
  13. package/packages/daemon/dist/canonical.d.ts +2 -0
  14. package/packages/daemon/dist/canonical.js +1 -0
  15. package/packages/daemon/dist/cli.d.ts +1 -0
  16. package/packages/daemon/dist/cli.js +425 -0
  17. package/packages/daemon/dist/command-center/actions/contract.d.ts +1 -0
  18. package/packages/daemon/dist/command-center/actions/contract.js +2 -0
  19. package/packages/daemon/dist/command-center/actions/dispatcher.d.ts +27 -0
  20. package/packages/daemon/dist/command-center/actions/dispatcher.js +109 -0
  21. package/packages/daemon/dist/command-center/actions/errors.d.ts +38 -0
  22. package/packages/daemon/dist/command-center/actions/errors.js +56 -0
  23. package/packages/daemon/dist/command-center/actions/handlers/_project-context.d.ts +12 -0
  24. package/packages/daemon/dist/command-center/actions/handlers/_project-context.js +12 -0
  25. package/packages/daemon/dist/command-center/actions/handlers/_resolve-project.d.ts +42 -0
  26. package/packages/daemon/dist/command-center/actions/handlers/_resolve-project.js +48 -0
  27. package/packages/daemon/dist/command-center/actions/handlers/app-set-remote-access.d.ts +23 -0
  28. package/packages/daemon/dist/command-center/actions/handlers/app-set-remote-access.js +67 -0
  29. package/packages/daemon/dist/command-center/actions/handlers/config-actions.d.ts +12 -0
  30. package/packages/daemon/dist/command-center/actions/handlers/config-actions.js +69 -0
  31. package/packages/daemon/dist/command-center/actions/handlers/daemon-shutdown.d.ts +6 -0
  32. package/packages/daemon/dist/command-center/actions/handlers/daemon-shutdown.js +24 -0
  33. package/packages/daemon/dist/command-center/actions/handlers/project-activate.d.ts +7 -0
  34. package/packages/daemon/dist/command-center/actions/handlers/project-activate.js +19 -0
  35. package/packages/daemon/dist/command-center/actions/handlers/project-launch.d.ts +18 -0
  36. package/packages/daemon/dist/command-center/actions/handlers/project-launch.js +58 -0
  37. package/packages/daemon/dist/command-center/actions/handlers/project-open-terminal.d.ts +32 -0
  38. package/packages/daemon/dist/command-center/actions/handlers/project-open-terminal.js +69 -0
  39. package/packages/daemon/dist/command-center/actions/handlers/project-restart.d.ts +17 -0
  40. package/packages/daemon/dist/command-center/actions/handlers/project-restart.js +27 -0
  41. package/packages/daemon/dist/command-center/actions/handlers/project-stop.d.ts +24 -0
  42. package/packages/daemon/dist/command-center/actions/handlers/project-stop.js +38 -0
  43. package/packages/daemon/dist/command-center/actions/handlers/terminal-respawn.d.ts +24 -0
  44. package/packages/daemon/dist/command-center/actions/handlers/terminal-respawn.js +88 -0
  45. package/packages/daemon/dist/command-center/actions/handlers/terminal-stop.d.ts +14 -0
  46. package/packages/daemon/dist/command-center/actions/handlers/terminal-stop.js +22 -0
  47. package/packages/daemon/dist/command-center/actions/registry.d.ts +35 -0
  48. package/packages/daemon/dist/command-center/actions/registry.js +109 -0
  49. package/packages/daemon/dist/command-center/discovery.d.ts +23 -0
  50. package/packages/daemon/dist/command-center/discovery.js +67 -0
  51. package/packages/daemon/dist/command-center/index.d.ts +10 -0
  52. package/packages/daemon/dist/command-center/index.js +21 -0
  53. package/packages/daemon/dist/command-center/schemas.d.ts +76 -0
  54. package/packages/daemon/dist/command-center/schemas.js +68 -0
  55. package/packages/daemon/dist/command-center/server.d.ts +26 -0
  56. package/packages/daemon/dist/command-center/server.js +1103 -0
  57. package/packages/daemon/dist/command-center/ws-events.d.ts +59 -0
  58. package/packages/daemon/dist/command-center/ws-events.js +277 -0
  59. package/packages/daemon/dist/config.d.ts +19 -0
  60. package/packages/daemon/dist/config.js +494 -0
  61. package/packages/daemon/dist/detect.d.ts +15 -0
  62. package/packages/daemon/dist/detect.js +228 -0
  63. package/packages/daemon/dist/doctor.d.ts +21 -0
  64. package/packages/daemon/dist/doctor.js +154 -0
  65. package/packages/daemon/dist/embed.d.ts +1 -0
  66. package/packages/daemon/dist/embed.js +1 -0
  67. package/packages/daemon/dist/index.d.ts +3 -0
  68. package/packages/daemon/dist/index.js +2 -0
  69. package/packages/daemon/dist/init.d.ts +4 -0
  70. package/packages/daemon/dist/init.js +174 -0
  71. package/packages/daemon/dist/inspect.d.ts +54 -0
  72. package/packages/daemon/dist/inspect.js +118 -0
  73. package/packages/daemon/dist/launch.d.ts +23 -0
  74. package/packages/daemon/dist/launch.js +250 -0
  75. package/packages/daemon/dist/lib/active-projects.d.ts +12 -0
  76. package/packages/daemon/dist/lib/active-projects.js +35 -0
  77. package/packages/daemon/dist/lib/agent-discovery.d.ts +43 -0
  78. package/packages/daemon/dist/lib/agent-discovery.js +85 -0
  79. package/packages/daemon/dist/lib/app-config.d.ts +147 -0
  80. package/packages/daemon/dist/lib/app-config.js +191 -0
  81. package/packages/daemon/dist/lib/app-settings.d.ts +9 -0
  82. package/packages/daemon/dist/lib/app-settings.js +44 -0
  83. package/packages/daemon/dist/lib/auth/auth-service.d.ts +33 -0
  84. package/packages/daemon/dist/lib/auth/auth-service.js +172 -0
  85. package/packages/daemon/dist/lib/auth/middleware.d.ts +16 -0
  86. package/packages/daemon/dist/lib/auth/middleware.js +43 -0
  87. package/packages/daemon/dist/lib/auth/types.d.ts +1 -0
  88. package/packages/daemon/dist/lib/auth/types.js +2 -0
  89. package/packages/daemon/dist/lib/auth-token.d.ts +1 -0
  90. package/packages/daemon/dist/lib/auth-token.js +4 -0
  91. package/packages/daemon/dist/lib/authorship.d.ts +62 -0
  92. package/packages/daemon/dist/lib/authorship.js +209 -0
  93. package/packages/daemon/dist/lib/canonical-daemon.d.ts +21 -0
  94. package/packages/daemon/dist/lib/canonical-daemon.js +111 -0
  95. package/packages/daemon/dist/lib/cli-action-bridge.d.ts +27 -0
  96. package/packages/daemon/dist/lib/cli-action-bridge.js +161 -0
  97. package/packages/daemon/dist/lib/daemon-embed.d.ts +31 -0
  98. package/packages/daemon/dist/lib/daemon-embed.js +643 -0
  99. package/packages/daemon/dist/lib/daemon-watchdog.d.ts +16 -0
  100. package/packages/daemon/dist/lib/daemon-watchdog.js +98 -0
  101. package/packages/daemon/dist/lib/daemon.d.ts +8 -0
  102. package/packages/daemon/dist/lib/daemon.js +79 -0
  103. package/packages/daemon/dist/lib/dot-path.d.ts +2 -0
  104. package/packages/daemon/dist/lib/dot-path.js +17 -0
  105. package/packages/daemon/dist/lib/errors.d.ts +37 -0
  106. package/packages/daemon/dist/lib/errors.js +50 -0
  107. package/packages/daemon/dist/lib/filesystem-browser.d.ts +85 -0
  108. package/packages/daemon/dist/lib/filesystem-browser.js +257 -0
  109. package/packages/daemon/dist/lib/launch-plan.d.ts +6 -0
  110. package/packages/daemon/dist/lib/launch-plan.js +76 -0
  111. package/packages/daemon/dist/lib/log.d.ts +40 -0
  112. package/packages/daemon/dist/lib/log.js +86 -0
  113. package/packages/daemon/dist/lib/output.d.ts +9 -0
  114. package/packages/daemon/dist/lib/output.js +65 -0
  115. package/packages/daemon/dist/lib/project-init-runner.d.ts +46 -0
  116. package/packages/daemon/dist/lib/project-init-runner.js +117 -0
  117. package/packages/daemon/dist/lib/project-inspect.d.ts +28 -0
  118. package/packages/daemon/dist/lib/project-inspect.js +67 -0
  119. package/packages/daemon/dist/lib/project-onboard.d.ts +58 -0
  120. package/packages/daemon/dist/lib/project-onboard.js +108 -0
  121. package/packages/daemon/dist/lib/project-probe.d.ts +35 -0
  122. package/packages/daemon/dist/lib/project-probe.js +61 -0
  123. package/packages/daemon/dist/lib/project-registry.d.ts +76 -0
  124. package/packages/daemon/dist/lib/project-registry.js +230 -0
  125. package/packages/daemon/dist/lib/session-monitor.d.ts +15 -0
  126. package/packages/daemon/dist/lib/session-monitor.js +103 -0
  127. package/packages/daemon/dist/lib/session-options.d.ts +13 -0
  128. package/packages/daemon/dist/lib/session-options.js +85 -0
  129. package/packages/daemon/dist/lib/shell.d.ts +5 -0
  130. package/{src/lib/shell.ts → packages/daemon/dist/lib/shell.js} +3 -3
  131. package/packages/daemon/dist/lib/sizes.d.ts +16 -0
  132. package/packages/daemon/dist/lib/sizes.js +36 -0
  133. package/packages/daemon/dist/lib/skill-sync.d.ts +60 -0
  134. package/packages/daemon/dist/lib/skill-sync.js +128 -0
  135. package/packages/daemon/dist/lib/slugify.d.ts +4 -0
  136. package/packages/daemon/dist/lib/slugify.js +10 -0
  137. package/packages/daemon/dist/lib/terminals-store.d.ts +27 -0
  138. package/packages/daemon/dist/lib/terminals-store.js +111 -0
  139. package/packages/daemon/dist/lib/update-check.d.ts +118 -0
  140. package/packages/daemon/dist/lib/update-check.js +261 -0
  141. package/packages/daemon/dist/lib/update.d.ts +65 -0
  142. package/packages/daemon/dist/lib/update.js +141 -0
  143. package/packages/daemon/dist/lib/workspace-registry.d.ts +84 -0
  144. package/packages/daemon/dist/lib/workspace-registry.js +176 -0
  145. package/packages/daemon/dist/lib/worktree.d.ts +76 -0
  146. package/packages/daemon/dist/lib/worktree.js +207 -0
  147. package/packages/daemon/dist/lib/yaml-io.d.ts +10 -0
  148. package/packages/daemon/dist/lib/yaml-io.js +24 -0
  149. package/packages/daemon/dist/ls.d.ts +3 -0
  150. package/packages/daemon/dist/ls.js +35 -0
  151. package/packages/daemon/dist/restart.d.ts +4 -0
  152. package/packages/daemon/dist/restart.js +16 -0
  153. package/packages/daemon/dist/restore.d.ts +86 -0
  154. package/packages/daemon/dist/restore.js +406 -0
  155. package/packages/daemon/dist/schemas/domain.d.ts +1 -0
  156. package/packages/daemon/dist/schemas/domain.js +2 -0
  157. package/packages/daemon/dist/schemas/filesystem.d.ts +29 -0
  158. package/packages/daemon/dist/schemas/filesystem.js +29 -0
  159. package/packages/daemon/dist/schemas/ide-config.d.ts +1 -0
  160. package/packages/daemon/dist/schemas/ide-config.js +2 -0
  161. package/packages/daemon/dist/schemas/index.d.ts +12 -0
  162. package/packages/daemon/dist/schemas/index.js +6 -0
  163. package/packages/daemon/dist/schemas/inspect.d.ts +53 -0
  164. package/packages/daemon/dist/schemas/inspect.js +57 -0
  165. package/packages/daemon/dist/schemas/registry.d.ts +35 -0
  166. package/packages/daemon/dist/schemas/registry.js +43 -0
  167. package/packages/daemon/dist/schemas/ws-events.d.ts +72 -0
  168. package/packages/daemon/dist/schemas/ws-events.js +110 -0
  169. package/packages/daemon/dist/send.d.ts +27 -0
  170. package/packages/daemon/dist/send.js +141 -0
  171. package/packages/daemon/dist/server/index.d.ts +10 -0
  172. package/packages/daemon/dist/server/index.js +55 -0
  173. package/packages/daemon/dist/server/pty-bridge.d.ts +174 -0
  174. package/packages/daemon/dist/server/pty-bridge.js +422 -0
  175. package/packages/daemon/dist/server/standalone.d.ts +1 -0
  176. package/packages/daemon/dist/server/standalone.js +14 -0
  177. package/packages/daemon/dist/server/ws-route.d.ts +74 -0
  178. package/packages/daemon/dist/server/ws-route.js +379 -0
  179. package/packages/daemon/dist/status.d.ts +3 -0
  180. package/packages/daemon/dist/status.js +46 -0
  181. package/packages/daemon/dist/stop.d.ts +3 -0
  182. package/packages/daemon/dist/stop.js +21 -0
  183. package/packages/daemon/dist/terminal/NodePtyAdapter.d.ts +44 -0
  184. package/packages/daemon/dist/terminal/NodePtyAdapter.js +253 -0
  185. package/packages/daemon/dist/terminal/PtyAdapter.d.ts +124 -0
  186. package/packages/daemon/dist/terminal/PtyAdapter.js +43 -0
  187. package/packages/daemon/dist/terminal/__tests__/MockPtyAdapter.d.ts +77 -0
  188. package/packages/daemon/dist/terminal/__tests__/MockPtyAdapter.js +155 -0
  189. package/packages/daemon/dist/types.d.ts +2 -0
  190. package/packages/daemon/dist/types.js +1 -0
  191. package/packages/daemon/dist/validate.d.ts +4 -0
  192. package/packages/daemon/dist/validate.js +184 -0
  193. package/packages/daemon/dist/widgets/changes/index.d.ts +1 -0
  194. package/packages/daemon/dist/widgets/changes/index.jsx +575 -0
  195. package/packages/daemon/dist/widgets/config/index.d.ts +1 -0
  196. package/packages/daemon/dist/widgets/config/index.jsx +395 -0
  197. package/packages/daemon/dist/widgets/explorer/breadcrumbs.d.ts +10 -0
  198. package/packages/daemon/dist/widgets/explorer/breadcrumbs.jsx +51 -0
  199. package/packages/daemon/dist/widgets/explorer/footer.d.ts +6 -0
  200. package/packages/daemon/dist/widgets/explorer/footer.jsx +11 -0
  201. package/packages/daemon/dist/widgets/explorer/index.d.ts +1 -0
  202. package/packages/daemon/dist/widgets/explorer/index.jsx +393 -0
  203. package/packages/daemon/dist/widgets/explorer/tree-model.d.ts +13 -0
  204. package/packages/daemon/dist/widgets/explorer/tree-model.js +69 -0
  205. package/packages/daemon/dist/widgets/explorer/tree.d.ts +13 -0
  206. package/packages/daemon/dist/widgets/explorer/tree.jsx +108 -0
  207. package/packages/daemon/dist/widgets/lib/config-model.d.ts +22 -0
  208. package/packages/daemon/dist/widgets/lib/config-model.js +99 -0
  209. package/packages/daemon/dist/widgets/lib/files.d.ts +11 -0
  210. package/packages/daemon/dist/widgets/lib/files.js +76 -0
  211. package/packages/daemon/dist/widgets/lib/git.d.ts +11 -0
  212. package/packages/daemon/dist/widgets/lib/git.js +70 -0
  213. package/packages/daemon/dist/widgets/lib/grammar.d.ts +79 -0
  214. package/packages/daemon/dist/widgets/lib/grammar.js +95 -0
  215. package/packages/daemon/dist/widgets/lib/help-overlay.d.ts +19 -0
  216. package/packages/daemon/dist/widgets/lib/help-overlay.jsx +69 -0
  217. package/packages/daemon/dist/widgets/lib/pane-comms.d.ts +28 -0
  218. package/packages/daemon/dist/widgets/lib/pane-comms.js +189 -0
  219. package/packages/daemon/dist/widgets/lib/theme.d.ts +44 -0
  220. package/packages/daemon/dist/widgets/lib/theme.js +153 -0
  221. package/packages/daemon/dist/widgets/lib/watcher.d.ts +9 -0
  222. package/packages/daemon/dist/widgets/lib/watcher.js +92 -0
  223. package/packages/daemon/dist/widgets/preview/index.d.ts +1 -0
  224. package/packages/daemon/dist/widgets/preview/index.jsx +371 -0
  225. package/packages/daemon/dist/widgets/resolve.d.ts +20 -0
  226. package/packages/daemon/dist/widgets/resolve.js +100 -0
  227. package/packages/daemon/dist/widgets/setup/agent-naming.d.ts +9 -0
  228. package/packages/daemon/dist/widgets/setup/agent-naming.jsx +81 -0
  229. package/packages/daemon/dist/widgets/setup/config-tree.d.ts +13 -0
  230. package/packages/daemon/dist/widgets/setup/config-tree.jsx +203 -0
  231. package/packages/daemon/dist/widgets/setup/detect-panel.d.ts +14 -0
  232. package/{src/widgets/setup/detect-panel.tsx → packages/daemon/dist/widgets/setup/detect-panel.jsx} +16 -40
  233. package/packages/daemon/dist/widgets/setup/field-editor.d.ts +12 -0
  234. package/packages/daemon/dist/widgets/setup/field-editor.jsx +163 -0
  235. package/packages/daemon/dist/widgets/setup/footer.d.ts +17 -0
  236. package/packages/daemon/dist/widgets/setup/footer.jsx +64 -0
  237. package/packages/daemon/dist/widgets/setup/index.d.ts +1 -0
  238. package/packages/daemon/dist/widgets/setup/index.jsx +261 -0
  239. package/packages/daemon/dist/widgets/setup/layout-picker.d.ts +9 -0
  240. package/packages/daemon/dist/widgets/setup/layout-picker.jsx +69 -0
  241. package/packages/daemon/dist/widgets/setup/setup-model.d.ts +15 -0
  242. package/packages/daemon/dist/widgets/setup/setup-model.js +157 -0
  243. package/packages/daemon/dist/widgets/sidebar/index.d.ts +1 -0
  244. package/packages/daemon/dist/widgets/sidebar/index.jsx +462 -0
  245. package/scripts/build-cli.mjs +101 -0
  246. package/scripts/build-tui.mjs +58 -0
  247. package/scripts/capture-codex-traffic.mjs +195 -0
  248. package/scripts/check-src-additions.sh +74 -0
  249. package/scripts/coverage-summary.mjs +68 -0
  250. package/scripts/install-git-hooks.js +53 -0
  251. package/scripts/merge-update-manifests.mjs +58 -0
  252. package/scripts/merge-update-manifests.test.mjs +82 -0
  253. package/scripts/pack-check-run.mjs +83 -0
  254. package/scripts/postinstall.js +28 -6
  255. package/scripts/prepublish-check.mjs +44 -0
  256. package/scripts/stress-test.ts +141 -0
  257. package/scripts/verify-endpoints.sh +90 -0
  258. package/skill/SKILL.md +203 -236
  259. package/dashboard/out/404/index.html +0 -1
  260. package/dashboard/out/404.html +0 -1
  261. package/dashboard/out/__next.__PAGE__.txt +0 -9
  262. package/dashboard/out/__next._full.txt +0 -21
  263. package/dashboard/out/__next._head.txt +0 -5
  264. package/dashboard/out/__next._index.txt +0 -7
  265. package/dashboard/out/__next._tree.txt +0 -4
  266. package/dashboard/out/_next/static/Tl1KoIH7mHCyjo5KtXqQ0/_buildManifest.js +0 -11
  267. package/dashboard/out/_next/static/Tl1KoIH7mHCyjo5KtXqQ0/_clientMiddlewareManifest.json +0 -1
  268. package/dashboard/out/_next/static/Tl1KoIH7mHCyjo5KtXqQ0/_ssgManifest.js +0 -1
  269. package/dashboard/out/_next/static/chunks/048e2449530877e2.js +0 -1
  270. package/dashboard/out/_next/static/chunks/053c57bda6abb959.js +0 -1
  271. package/dashboard/out/_next/static/chunks/056760c6c2dd9172.js +0 -1
  272. package/dashboard/out/_next/static/chunks/06ab47357b6d3e35.js +0 -1
  273. package/dashboard/out/_next/static/chunks/0921cbe5dfd6738e.js +0 -1
  274. package/dashboard/out/_next/static/chunks/0b2599bf468cf5ea.js +0 -1
  275. package/dashboard/out/_next/static/chunks/0c012eac08ef2c4f.js +0 -1
  276. package/dashboard/out/_next/static/chunks/0c29e87fcdcffac3.js +0 -1
  277. package/dashboard/out/_next/static/chunks/0e1e98854430c693.js +0 -1
  278. package/dashboard/out/_next/static/chunks/0e24498976a88976.js +0 -1
  279. package/dashboard/out/_next/static/chunks/0e5bf11ff0b9ab90.js +0 -1
  280. package/dashboard/out/_next/static/chunks/0eae0a45ab8416c8.js +0 -1
  281. package/dashboard/out/_next/static/chunks/104797400d9d38ad.js +0 -1
  282. package/dashboard/out/_next/static/chunks/10cfcfce475f9d2d.js +0 -1
  283. package/dashboard/out/_next/static/chunks/11bac38e7cfb4ecc.js +0 -1
  284. package/dashboard/out/_next/static/chunks/120c5f6501ec3529.js +0 -1
  285. package/dashboard/out/_next/static/chunks/121fceb2b1dcd79f.js +0 -1
  286. package/dashboard/out/_next/static/chunks/13726b63e1be6b98.js +0 -1
  287. package/dashboard/out/_next/static/chunks/140c6ce631514660.js +0 -1
  288. package/dashboard/out/_next/static/chunks/1435ee3a51174c97.js +0 -1
  289. package/dashboard/out/_next/static/chunks/14dc927d2e2cca91.js +0 -1
  290. package/dashboard/out/_next/static/chunks/179c3031b292d98e.js +0 -1
  291. package/dashboard/out/_next/static/chunks/181e88957c47e5c1.js +0 -1
  292. package/dashboard/out/_next/static/chunks/18f70ba23873c432.js +0 -1
  293. package/dashboard/out/_next/static/chunks/1b58303b027fd135.js +0 -1
  294. package/dashboard/out/_next/static/chunks/1b5f49a358dcc71e.js +0 -1
  295. package/dashboard/out/_next/static/chunks/1bba44b81585099a.js +0 -1
  296. package/dashboard/out/_next/static/chunks/1bea8dee19a3e9ae.js +0 -1
  297. package/dashboard/out/_next/static/chunks/1cfad21646fc250e.js +0 -1
  298. package/dashboard/out/_next/static/chunks/1d053dc9e1e428ef.js +0 -1
  299. package/dashboard/out/_next/static/chunks/1e7d7639c6f0ee5e.js +0 -1
  300. package/dashboard/out/_next/static/chunks/1f42504ca81463f1.js +0 -1
  301. package/dashboard/out/_next/static/chunks/20c92047399305b4.js +0 -1
  302. package/dashboard/out/_next/static/chunks/214560e9514a9a4d.js +0 -1
  303. package/dashboard/out/_next/static/chunks/21d4ef106914e997.js +0 -1
  304. package/dashboard/out/_next/static/chunks/2586e83fc3dc2588.js +0 -1
  305. package/dashboard/out/_next/static/chunks/267136a09e94f5c2.js +0 -1
  306. package/dashboard/out/_next/static/chunks/271c50b329917c10.js +0 -1
  307. package/dashboard/out/_next/static/chunks/27fccecefffd88b5.js +0 -1
  308. package/dashboard/out/_next/static/chunks/28f058ed331315b6.js +0 -1
  309. package/dashboard/out/_next/static/chunks/28f704f2cc5713eb.js +0 -1
  310. package/dashboard/out/_next/static/chunks/290f67a6cd150a98.js +0 -1
  311. package/dashboard/out/_next/static/chunks/2ad12f4dcc30d30a.js +0 -1
  312. package/dashboard/out/_next/static/chunks/2b650b172078ab92.js +0 -1
  313. package/dashboard/out/_next/static/chunks/2bd91076019a6453.js +0 -1
  314. package/dashboard/out/_next/static/chunks/2e1278563a8e26be.js +0 -1
  315. package/dashboard/out/_next/static/chunks/309eb70780a3d67d.js +0 -1
  316. package/dashboard/out/_next/static/chunks/30f71950992e2307.js +0 -1
  317. package/dashboard/out/_next/static/chunks/31191873c2075784.js +0 -1
  318. package/dashboard/out/_next/static/chunks/31a790921a0c035e.js +0 -1
  319. package/dashboard/out/_next/static/chunks/34f8d7a5a06e8e32.js +0 -1
  320. package/dashboard/out/_next/static/chunks/36b3716436d9bc9d.js +0 -1
  321. package/dashboard/out/_next/static/chunks/3770b7d0ff004de3.js +0 -1
  322. package/dashboard/out/_next/static/chunks/381ab3bd4cffbf4d.js +0 -1
  323. package/dashboard/out/_next/static/chunks/38aa4eada5dcd1a4.js +0 -1
  324. package/dashboard/out/_next/static/chunks/39723132b78cb77e.js +0 -1
  325. package/dashboard/out/_next/static/chunks/399efdcc3fe56e09.js +0 -1
  326. package/dashboard/out/_next/static/chunks/3a8431a9221b0706.js +0 -1
  327. package/dashboard/out/_next/static/chunks/3a9b40810ce88cbf.js +0 -1
  328. package/dashboard/out/_next/static/chunks/3b322e3e9476ecdf.js +0 -1
  329. package/dashboard/out/_next/static/chunks/3bb14befeeb08c28.js +0 -1
  330. package/dashboard/out/_next/static/chunks/3c99637ebd462b20.js +0 -1
  331. package/dashboard/out/_next/static/chunks/3cbb9217d56459d8.js +0 -1
  332. package/dashboard/out/_next/static/chunks/3d438e0929a762f7.js +0 -1
  333. package/dashboard/out/_next/static/chunks/3e6d4834e0752f76.js +0 -2
  334. package/dashboard/out/_next/static/chunks/3e6f8cedaad4e89b.js +0 -1
  335. package/dashboard/out/_next/static/chunks/3e701259ce1b53e3.js +0 -1
  336. package/dashboard/out/_next/static/chunks/41562f7ab7c033eb.js +0 -1
  337. package/dashboard/out/_next/static/chunks/418fadd8a94e2fd7.js +0 -1
  338. package/dashboard/out/_next/static/chunks/42345437bb922e9c.js +0 -1
  339. package/dashboard/out/_next/static/chunks/434b6bd78c97b668.js +0 -1
  340. package/dashboard/out/_next/static/chunks/434febe897d33e2d.js +0 -1
  341. package/dashboard/out/_next/static/chunks/45d28707dd8ce1c1.js +0 -1
  342. package/dashboard/out/_next/static/chunks/4620a640e88cb1b7.js +0 -1
  343. package/dashboard/out/_next/static/chunks/468f8eb604502ea4.js +0 -1
  344. package/dashboard/out/_next/static/chunks/495f5cedf8afe823.js +0 -1
  345. package/dashboard/out/_next/static/chunks/49a89d1704d27740.js +0 -1
  346. package/dashboard/out/_next/static/chunks/49e5c37d15f63def.js +0 -1
  347. package/dashboard/out/_next/static/chunks/4a46ad186a8587ee.css +0 -2
  348. package/dashboard/out/_next/static/chunks/4a5c728574935d50.js +0 -1
  349. package/dashboard/out/_next/static/chunks/4b27ebd4d9304d8f.js +0 -1
  350. package/dashboard/out/_next/static/chunks/4b965aa320a9b358.js +0 -1
  351. package/dashboard/out/_next/static/chunks/4bb2da90bbe5794f.js +0 -1
  352. package/dashboard/out/_next/static/chunks/4d2f1c6f631e4b85.js +0 -1
  353. package/dashboard/out/_next/static/chunks/4d696d5a64dab42e.js +0 -1
  354. package/dashboard/out/_next/static/chunks/4f660dadb3f1e9e2.js +0 -1
  355. package/dashboard/out/_next/static/chunks/507b50d47f949333.js +0 -1
  356. package/dashboard/out/_next/static/chunks/50b1b7063bb044e2.js +0 -1
  357. package/dashboard/out/_next/static/chunks/50c0c2e3c4f02508.js +0 -1
  358. package/dashboard/out/_next/static/chunks/50d7ba9803e65b02.js +0 -1
  359. package/dashboard/out/_next/static/chunks/51535a6d4c98c7a4.js +0 -1
  360. package/dashboard/out/_next/static/chunks/526de6cc16c7dd2f.js +0 -1
  361. package/dashboard/out/_next/static/chunks/5307604f8632b3fd.js +0 -1
  362. package/dashboard/out/_next/static/chunks/5480bd722260f231.js +0 -1
  363. package/dashboard/out/_next/static/chunks/54c61c82e5f1dca5.js +0 -1
  364. package/dashboard/out/_next/static/chunks/555de6ac6bb9034c.js +0 -1
  365. package/dashboard/out/_next/static/chunks/562b89ee76a4b90c.js +0 -1
  366. package/dashboard/out/_next/static/chunks/5747f9a32edff429.js +0 -1
  367. package/dashboard/out/_next/static/chunks/57ee141430b4c05c.js +0 -1
  368. package/dashboard/out/_next/static/chunks/584c066a0837dd9a.js +0 -1
  369. package/dashboard/out/_next/static/chunks/5856aed4670a6253.js +0 -1
  370. package/dashboard/out/_next/static/chunks/58fe563414726511.js +0 -1
  371. package/dashboard/out/_next/static/chunks/5948196b2729b18c.js +0 -1
  372. package/dashboard/out/_next/static/chunks/5ab77c69e7306f97.js +0 -1
  373. package/dashboard/out/_next/static/chunks/5b3fa4c99d61611c.js +0 -1
  374. package/dashboard/out/_next/static/chunks/5cc87abaef616661.js +0 -1
  375. package/dashboard/out/_next/static/chunks/5dfa7913f99bb966.js +0 -1
  376. package/dashboard/out/_next/static/chunks/5e49b008432770f1.js +0 -1
  377. package/dashboard/out/_next/static/chunks/5e5a33dd81c45c47.js +0 -1
  378. package/dashboard/out/_next/static/chunks/5ee61bed638eb8a8.js +0 -1
  379. package/dashboard/out/_next/static/chunks/5eed557b9f45ae4a.js +0 -1
  380. package/dashboard/out/_next/static/chunks/60446823a7d30c1b.js +0 -1
  381. package/dashboard/out/_next/static/chunks/605150c490861442.js +0 -1
  382. package/dashboard/out/_next/static/chunks/609056d51c0bf332.js +0 -1
  383. package/dashboard/out/_next/static/chunks/60ec91dfeb50071b.js +0 -1
  384. package/dashboard/out/_next/static/chunks/61bc7be0bba6a33f.js +0 -1
  385. package/dashboard/out/_next/static/chunks/61f4a5c9ce23e55e.js +0 -1
  386. package/dashboard/out/_next/static/chunks/63aae3585be04e65.js +0 -1
  387. package/dashboard/out/_next/static/chunks/64e0e1ee7ef4f01b.js +0 -1
  388. package/dashboard/out/_next/static/chunks/66e9b4c26ff1aaaf.js +0 -1
  389. package/dashboard/out/_next/static/chunks/67068847aa1b5e98.js +0 -1
  390. package/dashboard/out/_next/static/chunks/68d7de1f2e202c26.js +0 -1
  391. package/dashboard/out/_next/static/chunks/698ca3ea1937ba4f.js +0 -1
  392. package/dashboard/out/_next/static/chunks/69eb97c24b5b6b9d.js +0 -1
  393. package/dashboard/out/_next/static/chunks/6b1ac098c228a479.js +0 -1
  394. package/dashboard/out/_next/static/chunks/6bb8020cb796bcc1.js +0 -1
  395. package/dashboard/out/_next/static/chunks/6cf8b1db17f2a155.js +0 -1
  396. package/dashboard/out/_next/static/chunks/6e7613643906ea88.js +0 -1
  397. package/dashboard/out/_next/static/chunks/6ea27ceb2e6feae5.js +0 -1
  398. package/dashboard/out/_next/static/chunks/6f95a8dbcf23dded.js +0 -1
  399. package/dashboard/out/_next/static/chunks/6fd44e759d82f64e.js +0 -1
  400. package/dashboard/out/_next/static/chunks/716ec29c268c38f6.js +0 -1
  401. package/dashboard/out/_next/static/chunks/717b399dfcf7c02c.js +0 -1
  402. package/dashboard/out/_next/static/chunks/72badd90e1c91348.js +0 -1
  403. package/dashboard/out/_next/static/chunks/72f9296dbb7ae3c4.js +0 -1
  404. package/dashboard/out/_next/static/chunks/73aa31e1144d8191.js +0 -1
  405. package/dashboard/out/_next/static/chunks/73f98ded8fe2e879.js +0 -1
  406. package/dashboard/out/_next/static/chunks/740a2e8ace15e13b.js +0 -1
  407. package/dashboard/out/_next/static/chunks/74e57c16e7304b6b.js +0 -1
  408. package/dashboard/out/_next/static/chunks/7628dead4d113df2.js +0 -1
  409. package/dashboard/out/_next/static/chunks/7717c88c07ed96e6.js +0 -1
  410. package/dashboard/out/_next/static/chunks/775581f7956d9a27.js +0 -1
  411. package/dashboard/out/_next/static/chunks/77d3b6661befdb98.js +0 -1
  412. package/dashboard/out/_next/static/chunks/78435c0e1c77fea7.js +0 -1
  413. package/dashboard/out/_next/static/chunks/791336748b9c9393.js +0 -1
  414. package/dashboard/out/_next/static/chunks/79ea68dfae65ef2f.js +0 -1
  415. package/dashboard/out/_next/static/chunks/7bae777a472eb13c.js +0 -1
  416. package/dashboard/out/_next/static/chunks/7fd847f47237a35c.js +0 -1
  417. package/dashboard/out/_next/static/chunks/804d718be0370058.css +0 -1
  418. package/dashboard/out/_next/static/chunks/807cb3c1923995ab.js +0 -1
  419. package/dashboard/out/_next/static/chunks/8286b39407d94447.js +0 -1
  420. package/dashboard/out/_next/static/chunks/84e4305b8dc830ed.js +0 -1
  421. package/dashboard/out/_next/static/chunks/850f99dbfabb53e0.js +0 -1
  422. package/dashboard/out/_next/static/chunks/85594127e66b6b7f.js +0 -1
  423. package/dashboard/out/_next/static/chunks/858c11169c183c9c.js +0 -1
  424. package/dashboard/out/_next/static/chunks/85e27005dfe4c3e3.js +0 -1
  425. package/dashboard/out/_next/static/chunks/8707bd3d8ddc1f1c.js +0 -1
  426. package/dashboard/out/_next/static/chunks/8851e5d7ef894973.js +0 -1
  427. package/dashboard/out/_next/static/chunks/88ba3782cc614989.js +0 -1
  428. package/dashboard/out/_next/static/chunks/8a0c9a181784c2ef.js +0 -1
  429. package/dashboard/out/_next/static/chunks/8ad01ae355a6e7f6.js +0 -1
  430. package/dashboard/out/_next/static/chunks/8d2ed93b0d0a4b4f.js +0 -1
  431. package/dashboard/out/_next/static/chunks/8dc352ebd5310d3c.js +0 -1
  432. package/dashboard/out/_next/static/chunks/8dd1d722c8c1a22c.js +0 -1
  433. package/dashboard/out/_next/static/chunks/8e60fe307e3e4986.js +0 -1
  434. package/dashboard/out/_next/static/chunks/8eea4dd71e25f32a.js +0 -1
  435. package/dashboard/out/_next/static/chunks/8f468a65bac34eaa.js +0 -1
  436. package/dashboard/out/_next/static/chunks/9057e5382d6a5059.js +0 -1
  437. package/dashboard/out/_next/static/chunks/931d056437805ecb.js +0 -1
  438. package/dashboard/out/_next/static/chunks/954eb11648dd8cff.js +0 -1
  439. package/dashboard/out/_next/static/chunks/955034d876d14bb3.js +0 -1
  440. package/dashboard/out/_next/static/chunks/966c4895773249f6.js +0 -1
  441. package/dashboard/out/_next/static/chunks/96aff410a6ab106c.js +0 -1
  442. package/dashboard/out/_next/static/chunks/99b396c821c1dd2d.js +0 -1
  443. package/dashboard/out/_next/static/chunks/9a255fd2cf4922ae.js +0 -1
  444. package/dashboard/out/_next/static/chunks/9b1f6aa73bc864b2.js +0 -1
  445. package/dashboard/out/_next/static/chunks/9b9ce582c533aa79.js +0 -1
  446. package/dashboard/out/_next/static/chunks/9c19bd3c773c6611.js +0 -1
  447. package/dashboard/out/_next/static/chunks/9ceeaa847eb15ca2.js +0 -1
  448. package/dashboard/out/_next/static/chunks/9d2e6e7b8b65f845.js +0 -1
  449. package/dashboard/out/_next/static/chunks/9de23802066128ff.js +0 -1
  450. package/dashboard/out/_next/static/chunks/9e327f94b3701170.js +0 -1
  451. package/dashboard/out/_next/static/chunks/9e7818421c2d455a.js +0 -1
  452. package/dashboard/out/_next/static/chunks/9e935acbcf2fb519.js +0 -1
  453. package/dashboard/out/_next/static/chunks/9ed9f68340343b51.js +0 -1
  454. package/dashboard/out/_next/static/chunks/9f94a0242455fc20.js +0 -1
  455. package/dashboard/out/_next/static/chunks/9fff46b5aaecf47e.js +0 -1
  456. package/dashboard/out/_next/static/chunks/a06d267a5c557657.js +0 -1
  457. package/dashboard/out/_next/static/chunks/a0eb8c81c54722fe.js +0 -1
  458. package/dashboard/out/_next/static/chunks/a16808e83106427d.js +0 -1
  459. package/dashboard/out/_next/static/chunks/a2215e2bc72739ef.js +0 -1
  460. package/dashboard/out/_next/static/chunks/a2de9e6696eb9c17.js +0 -1
  461. package/dashboard/out/_next/static/chunks/a33420b8c14090d6.js +0 -1
  462. package/dashboard/out/_next/static/chunks/a360bffef39d818b.js +0 -1
  463. package/dashboard/out/_next/static/chunks/a42852fdf5287cf5.js +0 -1
  464. package/dashboard/out/_next/static/chunks/a4efc88488322b67.js +0 -1
  465. package/dashboard/out/_next/static/chunks/a696a91d14101bdb.js +0 -1
  466. package/dashboard/out/_next/static/chunks/a6dad97d9634a72d.js +0 -1
  467. package/dashboard/out/_next/static/chunks/a6dad97d9634a72d.js.map +0 -1
  468. package/dashboard/out/_next/static/chunks/a705c7261712bd8e.js +0 -1
  469. package/dashboard/out/_next/static/chunks/a7d1e4b067ace180.js +0 -1
  470. package/dashboard/out/_next/static/chunks/a8590c121a7efaa5.js +0 -1
  471. package/dashboard/out/_next/static/chunks/a95953a83a6df6cf.js +0 -1
  472. package/dashboard/out/_next/static/chunks/a9d0a757d3b4afed.js +0 -1
  473. package/dashboard/out/_next/static/chunks/a9dc35514619c872.js +0 -1
  474. package/dashboard/out/_next/static/chunks/aae0253c73fba984.js +0 -193
  475. package/dashboard/out/_next/static/chunks/ab1821552066a74d.js +0 -1
  476. package/dashboard/out/_next/static/chunks/ac96bc0eccebe15a.js +0 -1
  477. package/dashboard/out/_next/static/chunks/acc03cfaaf6bb30f.js +0 -1
  478. package/dashboard/out/_next/static/chunks/acc298ae059b9fe4.js +0 -1
  479. package/dashboard/out/_next/static/chunks/ad076b6e996d250c.js +0 -1
  480. package/dashboard/out/_next/static/chunks/ae53b64af7ba16d5.js +0 -1
  481. package/dashboard/out/_next/static/chunks/ae5da7fa4bc5fa95.js +0 -1
  482. package/dashboard/out/_next/static/chunks/aefcf0eb033a155e.js +0 -1
  483. package/dashboard/out/_next/static/chunks/b12d43100ee10526.js +0 -1
  484. package/dashboard/out/_next/static/chunks/b137952dd5566a41.js +0 -1
  485. package/dashboard/out/_next/static/chunks/b2832d8a2d332a47.js +0 -1
  486. package/dashboard/out/_next/static/chunks/b417aa09c15f63c6.js +0 -1
  487. package/dashboard/out/_next/static/chunks/b48e152ba7bf6caf.js +0 -1
  488. package/dashboard/out/_next/static/chunks/b4cbef8e4714bf92.js +0 -1
  489. package/dashboard/out/_next/static/chunks/b568ff8383a37f53.js +0 -1
  490. package/dashboard/out/_next/static/chunks/b6e1495dd89a39e3.js +0 -1
  491. package/dashboard/out/_next/static/chunks/b73a21bd67528440.js +0 -1
  492. package/dashboard/out/_next/static/chunks/b77ee62bc71dcec7.js +0 -1
  493. package/dashboard/out/_next/static/chunks/b7f454615c11d4eb.js +0 -1
  494. package/dashboard/out/_next/static/chunks/b818ea32a839590f.js +0 -1
  495. package/dashboard/out/_next/static/chunks/b901ce78c1c65d66.js +0 -1
  496. package/dashboard/out/_next/static/chunks/b93d647b803be9fa.js +0 -1
  497. package/dashboard/out/_next/static/chunks/b960b09ff1ecd6bb.js +0 -1
  498. package/dashboard/out/_next/static/chunks/ba717c7779a778fc.js +0 -1
  499. package/dashboard/out/_next/static/chunks/bacb0ae7458d18b6.js +0 -1
  500. package/dashboard/out/_next/static/chunks/bb51f68b27346852.js +0 -1
  501. package/dashboard/out/_next/static/chunks/bb67f22e1ab632ae.js +0 -1
  502. package/dashboard/out/_next/static/chunks/bbae97ec58d1bb9d.js +0 -1
  503. package/dashboard/out/_next/static/chunks/bbaf38ee90307765.js +0 -1
  504. package/dashboard/out/_next/static/chunks/be01598fe1fce5db.js +0 -1
  505. package/dashboard/out/_next/static/chunks/bf4cbbc095987fec.js +0 -1
  506. package/dashboard/out/_next/static/chunks/c18f823797d57446.js +0 -1
  507. package/dashboard/out/_next/static/chunks/c1bcece34ec5b295.js +0 -1
  508. package/dashboard/out/_next/static/chunks/c1ccbc3a51adaf0a.js +0 -1
  509. package/dashboard/out/_next/static/chunks/c1f54a628f27791c.js +0 -1
  510. package/dashboard/out/_next/static/chunks/c21916bf5d232151.js +0 -1
  511. package/dashboard/out/_next/static/chunks/c27e570f0fc2f78b.js +0 -1
  512. package/dashboard/out/_next/static/chunks/c322b8005eebc0d8.js +0 -1
  513. package/dashboard/out/_next/static/chunks/c3900ac2b009b764.js +0 -1
  514. package/dashboard/out/_next/static/chunks/c3c597c8eb77ad6b.js +0 -1
  515. package/dashboard/out/_next/static/chunks/c58d45c1d88e208c.js +0 -1
  516. package/dashboard/out/_next/static/chunks/c63875998d7a655f.js +0 -1
  517. package/dashboard/out/_next/static/chunks/c6eaa7c8e7209c8e.js +0 -1
  518. package/dashboard/out/_next/static/chunks/c6f820f71162a59a.js +0 -1
  519. package/dashboard/out/_next/static/chunks/c7ce0941d1dfe7ed.js +0 -1
  520. package/dashboard/out/_next/static/chunks/c877259f784ec8e5.js +0 -1
  521. package/dashboard/out/_next/static/chunks/cb8057e86aaa1c68.js +0 -1
  522. package/dashboard/out/_next/static/chunks/ccb4e306ee4859b1.js +0 -1
  523. package/dashboard/out/_next/static/chunks/ccde62b0fa8112eb.js +0 -1
  524. package/dashboard/out/_next/static/chunks/cd421f0971c63c31.js +0 -1
  525. package/dashboard/out/_next/static/chunks/cde0317494d4adb7.js +0 -1
  526. package/dashboard/out/_next/static/chunks/cfae64434b92b8b6.js +0 -1
  527. package/dashboard/out/_next/static/chunks/cfc0e19310ec0a36.js +0 -1
  528. package/dashboard/out/_next/static/chunks/d0f344c7d0bcb59a.js +0 -1
  529. package/dashboard/out/_next/static/chunks/d1871c73e74e1f50.js +0 -1
  530. package/dashboard/out/_next/static/chunks/d18f658850711061.js +0 -1
  531. package/dashboard/out/_next/static/chunks/d25d9c48880697f6.js +0 -1
  532. package/dashboard/out/_next/static/chunks/d3f0a72bbc3060b0.js +0 -1
  533. package/dashboard/out/_next/static/chunks/d5fca429bc89060b.js +0 -1
  534. package/dashboard/out/_next/static/chunks/d6a6c75c9a4bef49.js +0 -1
  535. package/dashboard/out/_next/static/chunks/d6a8f93aa8f1e345.js +0 -1
  536. package/dashboard/out/_next/static/chunks/d7deab676b19ba0e.js +0 -1
  537. package/dashboard/out/_next/static/chunks/d80030dde88cec85.js +0 -1
  538. package/dashboard/out/_next/static/chunks/da84f9774c076ff1.js +0 -1
  539. package/dashboard/out/_next/static/chunks/da98ecc6b9b0ceb2.js +0 -1
  540. package/dashboard/out/_next/static/chunks/db550aabce60b912.js +0 -4
  541. package/dashboard/out/_next/static/chunks/dc87f77fcc029482.js +0 -1
  542. package/dashboard/out/_next/static/chunks/dd05f30acdb63a53.js +0 -1
  543. package/dashboard/out/_next/static/chunks/dea150155499b903.js +0 -1
  544. package/dashboard/out/_next/static/chunks/df4358754ff1d5e8.js +0 -1
  545. package/dashboard/out/_next/static/chunks/df8b21ff12d23b0e.js +0 -1
  546. package/dashboard/out/_next/static/chunks/df8fc68d77debf2c.js +0 -1
  547. package/dashboard/out/_next/static/chunks/df9ed1ffec90589f.js +0 -1
  548. package/dashboard/out/_next/static/chunks/dfa65ece1598f934.js +0 -1
  549. package/dashboard/out/_next/static/chunks/dfaab5cdd41a20d9.js +0 -1
  550. package/dashboard/out/_next/static/chunks/e00c03c942b5ae3e.js +0 -1
  551. package/dashboard/out/_next/static/chunks/e02d27cf679bece1.js +0 -1
  552. package/dashboard/out/_next/static/chunks/e0b747585f78513a.js +0 -1
  553. package/dashboard/out/_next/static/chunks/e19b71ca23fd7df0.js +0 -1
  554. package/dashboard/out/_next/static/chunks/e21cbe89d0cda120.js +0 -1
  555. package/dashboard/out/_next/static/chunks/e2a0386930edd34f.js +0 -1
  556. package/dashboard/out/_next/static/chunks/e375de19a36e2f38.js +0 -1
  557. package/dashboard/out/_next/static/chunks/e5241b4a6496a9e0.js +0 -1
  558. package/dashboard/out/_next/static/chunks/e569dd07c96eb4dd.js +0 -1
  559. package/dashboard/out/_next/static/chunks/e61c3ea91233f948.js +0 -1
  560. package/dashboard/out/_next/static/chunks/e73b42c5d34c4c28.js +0 -1
  561. package/dashboard/out/_next/static/chunks/e7c5b2105f651e87.js +0 -1
  562. package/dashboard/out/_next/static/chunks/e878e58a69bb01b6.js +0 -1
  563. package/dashboard/out/_next/static/chunks/e8f090a4dc571062.js +0 -1
  564. package/dashboard/out/_next/static/chunks/e98dc34dac91cdad.js +0 -1
  565. package/dashboard/out/_next/static/chunks/ea67cf7a0c5e7233.js +0 -1
  566. package/dashboard/out/_next/static/chunks/eacc98a1e3512fa9.js +0 -1
  567. package/dashboard/out/_next/static/chunks/eae9cd74d9bbed8b.js +0 -1
  568. package/dashboard/out/_next/static/chunks/eb187fd345852b34.js +0 -1
  569. package/dashboard/out/_next/static/chunks/ecea46df7a40b427.js +0 -1
  570. package/dashboard/out/_next/static/chunks/ecf48b83f4245d9c.js +0 -1
  571. package/dashboard/out/_next/static/chunks/eda41732bf966c6d.js +0 -1
  572. package/dashboard/out/_next/static/chunks/ee174a433049f43a.js +0 -1
  573. package/dashboard/out/_next/static/chunks/ee66b2d3b76de72e.js +0 -1
  574. package/dashboard/out/_next/static/chunks/ef058d3041c3d8ab.js +0 -1
  575. package/dashboard/out/_next/static/chunks/f3544b800b0d4969.js +0 -1
  576. package/dashboard/out/_next/static/chunks/f3b280e604b97509.js +0 -1
  577. package/dashboard/out/_next/static/chunks/f42e1d3693232993.js +0 -1
  578. package/dashboard/out/_next/static/chunks/f5a5fdd80166d304.js +0 -1
  579. package/dashboard/out/_next/static/chunks/f60adc5dd6169316.js +0 -1
  580. package/dashboard/out/_next/static/chunks/f6255bc2e6c68ce8.js +0 -1
  581. package/dashboard/out/_next/static/chunks/f6bb677d2d8840db.js +0 -1
  582. package/dashboard/out/_next/static/chunks/f6f3bf016239c33a.js +0 -1
  583. package/dashboard/out/_next/static/chunks/f6f57a46cd074bfe.js +0 -1
  584. package/dashboard/out/_next/static/chunks/f7feb9c1199e8cf6.js +0 -1
  585. package/dashboard/out/_next/static/chunks/f831087bf964cc3d.js +0 -1
  586. package/dashboard/out/_next/static/chunks/fa5a2f7244935aa2.js +0 -1
  587. package/dashboard/out/_next/static/chunks/fa73f36df4c38fa0.js +0 -1
  588. package/dashboard/out/_next/static/chunks/faa1461722d6a88d.js +0 -1
  589. package/dashboard/out/_next/static/chunks/fbf706b9a0edb7e6.js +0 -1
  590. package/dashboard/out/_next/static/chunks/fc2b8c8b7446bbc2.js +0 -1
  591. package/dashboard/out/_next/static/chunks/fd516f3930c128c1.js +0 -1
  592. package/dashboard/out/_next/static/chunks/fd663e7ff8de4887.js +0 -1
  593. package/dashboard/out/_next/static/chunks/fe5b656cc9bdd60e.js +0 -1
  594. package/dashboard/out/_next/static/chunks/turbopack-2f5dec4a537c0ee7.js +0 -4
  595. package/dashboard/out/_next/static/media/02263ebadd758ea4-s.8da66e7f.woff2 +0 -0
  596. package/dashboard/out/_next/static/media/2fe89d53234c61d4-s.cb53f04b.woff2 +0 -0
  597. package/dashboard/out/_next/static/media/59b15b4bcd7b1eb5-s.afa48be3.woff2 +0 -0
  598. package/dashboard/out/_next/static/media/5e05ae5b48faa55e-s.6b5ea6af.woff2 +0 -0
  599. package/dashboard/out/_next/static/media/68757d6cddeff913-s.e6cd1753.woff2 +0 -0
  600. package/dashboard/out/_next/static/media/99e609270109b47d-s.p.64b9304e.woff2 +0 -0
  601. package/dashboard/out/_next/static/media/a7afbb44bec2bb18-s.1dcddae6.woff2 +0 -0
  602. package/dashboard/out/_next/static/media/e390973e931a41c5-s.a82ecf4e.woff2 +0 -0
  603. package/dashboard/out/_next/static/media/e532fa1b9921e1cd-s.764b43eb.woff2 +0 -0
  604. package/dashboard/out/_next/static/media/effe91970fc4db64-s.p.19510058.woff2 +0 -0
  605. package/dashboard/out/_not-found/__next._full.txt +0 -15
  606. package/dashboard/out/_not-found/__next._head.txt +0 -5
  607. package/dashboard/out/_not-found/__next._index.txt +0 -7
  608. package/dashboard/out/_not-found/__next._not-found.__PAGE__.txt +0 -5
  609. package/dashboard/out/_not-found/__next._not-found.txt +0 -4
  610. package/dashboard/out/_not-found/__next._tree.txt +0 -2
  611. package/dashboard/out/_not-found/index.html +0 -1
  612. package/dashboard/out/_not-found/index.txt +0 -15
  613. package/dashboard/out/index.html +0 -1
  614. package/dashboard/out/index.txt +0 -21
  615. package/dashboard/out/project/__fallback/__next._full.txt +0 -19
  616. package/dashboard/out/project/__fallback/__next._head.txt +0 -5
  617. package/dashboard/out/project/__fallback/__next._index.txt +0 -7
  618. package/dashboard/out/project/__fallback/__next._tree.txt +0 -5
  619. package/dashboard/out/project/__fallback/__next.project.$d$name.__PAGE__.txt +0 -7
  620. package/dashboard/out/project/__fallback/__next.project.$d$name.txt +0 -4
  621. package/dashboard/out/project/__fallback/__next.project.txt +0 -4
  622. package/dashboard/out/project/__fallback/index.html +0 -1
  623. package/dashboard/out/project/__fallback/index.txt +0 -19
  624. package/src/__tests__/support.ts +0 -186
  625. package/src/attach.ts +0 -20
  626. package/src/cli.test.ts +0 -314
  627. package/src/command-center/discovery.test.ts +0 -265
  628. package/src/command-center/discovery.ts +0 -296
  629. package/src/command-center/index.ts +0 -31
  630. package/src/command-center/schemas.ts +0 -57
  631. package/src/command-center/server.test.ts +0 -814
  632. package/src/command-center/server.ts +0 -1427
  633. package/src/command-center/static.test.ts +0 -105
  634. package/src/command-center/static.ts +0 -122
  635. package/src/config-cli.test.ts +0 -86
  636. package/src/config.test.ts +0 -205
  637. package/src/config.ts +0 -313
  638. package/src/detect.test.ts +0 -142
  639. package/src/detect.ts +0 -248
  640. package/src/dispatch.ts +0 -102
  641. package/src/doctor.test.ts +0 -119
  642. package/src/doctor.ts +0 -167
  643. package/src/init.test.ts +0 -101
  644. package/src/init.ts +0 -211
  645. package/src/inspect.test.ts +0 -67
  646. package/src/inspect.ts +0 -212
  647. package/src/integration.test.ts.skip +0 -276
  648. package/src/js-yaml.d.ts +0 -10
  649. package/src/launch.test.ts +0 -149
  650. package/src/launch.ts +0 -583
  651. package/src/lib/auth/auth-service.test.ts +0 -178
  652. package/src/lib/auth/auth-service.ts +0 -227
  653. package/src/lib/auth/middleware.test.ts +0 -119
  654. package/src/lib/auth/middleware.ts +0 -56
  655. package/src/lib/auth/types.ts +0 -13
  656. package/src/lib/authorship.test.ts +0 -242
  657. package/src/lib/authorship.ts +0 -280
  658. package/src/lib/cast/recorder.test.ts +0 -127
  659. package/src/lib/cast/recorder.ts +0 -148
  660. package/src/lib/daemon-watchdog.ts +0 -102
  661. package/src/lib/daemon.ts +0 -431
  662. package/src/lib/dot-path.test.ts +0 -66
  663. package/src/lib/dot-path.ts +0 -17
  664. package/src/lib/errors.ts +0 -44
  665. package/src/lib/event-log.test.ts +0 -189
  666. package/src/lib/event-log.ts +0 -237
  667. package/src/lib/github-pr.ts +0 -182
  668. package/src/lib/hq/client.test.ts +0 -154
  669. package/src/lib/hq/client.ts +0 -142
  670. package/src/lib/hq/mdns.test.ts +0 -54
  671. package/src/lib/hq/mdns.ts +0 -88
  672. package/src/lib/hq/registry.test.ts +0 -237
  673. package/src/lib/hq/registry.ts +0 -145
  674. package/src/lib/hq/types.ts +0 -44
  675. package/src/lib/ipc/socket-protocol.test.ts +0 -126
  676. package/src/lib/ipc/socket-protocol.ts +0 -324
  677. package/src/lib/launch-plan.test.ts +0 -119
  678. package/src/lib/launch-plan.ts +0 -90
  679. package/src/lib/log.test.ts +0 -39
  680. package/src/lib/log.ts +0 -71
  681. package/src/lib/metrics.test.ts +0 -213
  682. package/src/lib/metrics.ts +0 -345
  683. package/src/lib/orchestrator.test.ts +0 -2358
  684. package/src/lib/orchestrator.ts +0 -1799
  685. package/src/lib/output.ts +0 -76
  686. package/src/lib/plan-store.test.ts +0 -148
  687. package/src/lib/plan-store.ts +0 -131
  688. package/src/lib/research.test.ts +0 -208
  689. package/src/lib/research.ts +0 -475
  690. package/src/lib/round-trip.test.ts +0 -341
  691. package/src/lib/session-monitor.test.ts +0 -152
  692. package/src/lib/session-monitor.ts +0 -282
  693. package/src/lib/session-options.test.ts +0 -146
  694. package/src/lib/session-options.ts +0 -100
  695. package/src/lib/shell.test.ts +0 -20
  696. package/src/lib/sizes.test.ts +0 -73
  697. package/src/lib/sizes.ts +0 -36
  698. package/src/lib/skill-registry.test.ts +0 -134
  699. package/src/lib/skill-registry.ts +0 -86
  700. package/src/lib/slugify.test.ts +0 -35
  701. package/src/lib/slugify.ts +0 -10
  702. package/src/lib/task-store.ts +0 -352
  703. package/src/lib/tmux.test.ts +0 -500
  704. package/src/lib/tmux.ts +0 -372
  705. package/src/lib/token-tracker.test.ts +0 -102
  706. package/src/lib/token-tracker.ts +0 -70
  707. package/src/lib/tunnels/cloudflare.test.ts +0 -73
  708. package/src/lib/tunnels/cloudflare.ts +0 -254
  709. package/src/lib/tunnels/manager.test.ts +0 -63
  710. package/src/lib/tunnels/manager.ts +0 -132
  711. package/src/lib/tunnels/ngrok.test.ts +0 -94
  712. package/src/lib/tunnels/ngrok.ts +0 -261
  713. package/src/lib/tunnels/tailscale.test.ts +0 -103
  714. package/src/lib/tunnels/tailscale.ts +0 -1048
  715. package/src/lib/tunnels/types.ts +0 -44
  716. package/src/lib/validation.test.ts +0 -289
  717. package/src/lib/validation.ts +0 -123
  718. package/src/lib/webhook.ts +0 -51
  719. package/src/lib/workflow-store.ts +0 -209
  720. package/src/lib/ws-v3/protocol.test.ts +0 -127
  721. package/src/lib/ws-v3/protocol.ts +0 -160
  722. package/src/lib/yaml-io.test.ts +0 -125
  723. package/src/lib/yaml-io.ts +0 -27
  724. package/src/ls.test.ts +0 -76
  725. package/src/ls.ts +0 -40
  726. package/src/metrics-cli.ts +0 -177
  727. package/src/notify.ts +0 -85
  728. package/src/orchestrator-status.ts +0 -228
  729. package/src/plan.ts +0 -117
  730. package/src/postinstall.test.ts +0 -79
  731. package/src/remote.test.ts +0 -115
  732. package/src/remote.ts +0 -148
  733. package/src/restart.ts +0 -24
  734. package/src/schemas/domain.ts +0 -422
  735. package/src/schemas/ide-config.ts +0 -148
  736. package/src/schemas/index.ts +0 -53
  737. package/src/send.test.ts +0 -70
  738. package/src/send.ts +0 -181
  739. package/src/skill.test.ts +0 -114
  740. package/src/skill.ts +0 -138
  741. package/src/status.ts +0 -66
  742. package/src/stop.test.ts +0 -151
  743. package/src/stop.ts +0 -37
  744. package/src/task.test.ts +0 -1466
  745. package/src/task.ts +0 -1143
  746. package/src/tunnel.test.ts +0 -80
  747. package/src/tunnel.ts +0 -133
  748. package/src/types.ts +0 -15
  749. package/src/ui/index.ts +0 -32
  750. package/src/ui/terminal/index.ts +0 -9
  751. package/src/ui/types.ts +0 -91
  752. package/src/ui/web/base.css +0 -80
  753. package/src/ui/web/components/Box.tsx +0 -59
  754. package/src/ui/web/components/Input.tsx +0 -32
  755. package/src/ui/web/components/ScrollBox.tsx +0 -60
  756. package/src/ui/web/components/Text.tsx +0 -28
  757. package/src/ui/web/hooks.ts +0 -106
  758. package/src/ui/web/index.ts +0 -27
  759. package/src/ui/web/render.ts +0 -77
  760. package/src/ui/web/utils/color.test.ts +0 -93
  761. package/src/ui/web/utils/color.ts +0 -27
  762. package/src/validate.test.ts +0 -385
  763. package/src/validate.ts +0 -217
  764. package/src/widgets/changes/index.tsx +0 -576
  765. package/src/widgets/config/index.tsx +0 -440
  766. package/src/widgets/costs/index.tsx +0 -216
  767. package/src/widgets/explorer/breadcrumbs.tsx +0 -77
  768. package/src/widgets/explorer/footer.tsx +0 -20
  769. package/src/widgets/explorer/header.tsx +0 -23
  770. package/src/widgets/explorer/index.tsx +0 -408
  771. package/src/widgets/explorer/tree-model.test.ts +0 -214
  772. package/src/widgets/explorer/tree-model.ts +0 -103
  773. package/src/widgets/explorer/tree.tsx +0 -156
  774. package/src/widgets/lib/config-model.ts +0 -116
  775. package/src/widgets/lib/files.test.ts +0 -103
  776. package/src/widgets/lib/files.ts +0 -88
  777. package/src/widgets/lib/git.test.ts +0 -151
  778. package/src/widgets/lib/git.ts +0 -88
  779. package/src/widgets/lib/pane-comms.test.ts +0 -178
  780. package/src/widgets/lib/pane-comms.ts +0 -207
  781. package/src/widgets/lib/theme.ts +0 -151
  782. package/src/widgets/lib/watcher.ts +0 -50
  783. package/src/widgets/mission-control/activity-feed.tsx +0 -59
  784. package/src/widgets/mission-control/agent-panel.tsx +0 -132
  785. package/src/widgets/mission-control/command-bar.tsx +0 -63
  786. package/src/widgets/mission-control/index.tsx +0 -751
  787. package/src/widgets/mission-control/task-panel.tsx +0 -238
  788. package/src/widgets/preview/index.tsx +0 -415
  789. package/src/widgets/resolve.ts +0 -40
  790. package/src/widgets/setup/agent-naming.tsx +0 -112
  791. package/src/widgets/setup/config-tree.tsx +0 -238
  792. package/src/widgets/setup/field-editor.tsx +0 -265
  793. package/src/widgets/setup/footer.tsx +0 -107
  794. package/src/widgets/setup/index.tsx +0 -340
  795. package/src/widgets/setup/layout-picker.tsx +0 -96
  796. package/src/widgets/setup/orchestrator-panel.tsx +0 -200
  797. package/src/widgets/setup/review-panel.tsx +0 -140
  798. package/src/widgets/setup/setup-model.test.ts +0 -303
  799. package/src/widgets/setup/setup-model.ts +0 -188
  800. package/src/widgets/tasks/index.tsx +0 -129
  801. package/src/widgets/tasks/task-detail.tsx +0 -309
  802. package/src/widgets/tasks/task-form.tsx +0 -193
  803. package/src/widgets/tasks/task-list.tsx +0 -205
  804. package/src/widgets/tasks/task-model.test.ts +0 -473
  805. package/src/widgets/tasks/task-model.ts +0 -157
package/bin/cli.ts CHANGED
@@ -1,26 +1,36 @@
1
- #!/usr/bin/env bun
1
+ // No shebang in source. The published bin is the compiled `bin/cli.js`
2
+ // (see scripts/build-cli.mjs) which adds `#!/usr/bin/env node` via the
3
+ // esbuild banner. Dev iteration uses `bun bin/cli.ts` directly, which
4
+ // doesn't need a shebang.
2
5
  import { parseArgs } from "node:util";
3
- import { resolve, dirname } from "node:path";
6
+ import { resolve, dirname, join } from "node:path";
4
7
  import { execFileSync } from "node:child_process";
8
+ import { existsSync } from "node:fs";
5
9
  import { fileURLToPath } from "node:url";
6
10
 
7
11
  const __dirname = dirname(fileURLToPath(import.meta.url));
8
- import { launch } from "../src/launch.ts";
9
- import { init } from "../src/init.ts";
10
- import { stop } from "../src/stop.ts";
11
- import { attach } from "../src/attach.ts";
12
- import { ls } from "../src/ls.ts";
13
- import { doctor } from "../src/doctor.ts";
14
- import { status } from "../src/status.ts";
15
- import { inspect } from "../src/inspect.ts";
16
- import { validate } from "../src/validate.ts";
17
- import { detect } from "../src/detect.ts";
18
- import { config } from "../src/config.ts";
19
- import { restart } from "../src/restart.ts";
20
- import { taskCommand } from "../src/task.ts";
21
- import { send } from "../src/send.ts";
22
- import { IdeError } from "../src/lib/errors.ts";
23
- import { printCommandError } from "../src/lib/output.ts";
12
+ import { launch } from "../packages/daemon/src/launch.ts";
13
+ import { shouldOpenCockpit } from "../packages/daemon/src/tui/team/entry.ts";
14
+ import {
15
+ resolveTuiLaunch,
16
+ findCompiledTui,
17
+ isBunAvailable,
18
+ } from "../packages/daemon/src/tui/compiled.ts";
19
+ import { init } from "../packages/daemon/src/init.ts";
20
+ import { stop } from "../packages/daemon/src/stop.ts";
21
+ import { attach } from "../packages/daemon/src/attach.ts";
22
+ import { ls } from "../packages/daemon/src/ls.ts";
23
+ import { doctor } from "../packages/daemon/src/doctor.ts";
24
+ import { status } from "../packages/daemon/src/status.ts";
25
+ import { inspect } from "../packages/daemon/src/inspect.ts";
26
+ import { validate } from "../packages/daemon/src/validate.ts";
27
+ import { detect } from "../packages/daemon/src/detect.ts";
28
+ import { config } from "../packages/daemon/src/config.ts";
29
+ import { restart } from "../packages/daemon/src/restart.ts";
30
+ import { restore } from "../packages/daemon/src/restore.ts";
31
+ import { send } from "../packages/daemon/src/send.ts";
32
+ import { IdeError } from "../packages/daemon/src/lib/errors.ts";
33
+ import { printCommandError } from "../packages/daemon/src/lib/output.ts";
24
34
 
25
35
  const { positionals, values } = parseArgs({
26
36
  allowPositionals: true,
@@ -38,37 +48,47 @@ const { positionals, values } = parseArgs({
38
48
  verbose: { type: "boolean", default: false },
39
49
  help: { type: "boolean", short: "h" },
40
50
  version: { type: "boolean", short: "v" },
41
- // task command flags
42
- description: { type: "string", short: "d" },
43
- acceptance: { type: "string" },
44
- priority: { type: "string", short: "p" },
45
- status: { type: "string", short: "s" },
46
- assign: { type: "string", short: "a" },
47
- goal: { type: "string", short: "g" },
48
- tags: { type: "string", short: "t" },
49
- proof: { type: "string" },
50
- depends: { type: "string" },
51
- pr: { type: "boolean" },
52
- specialty: { type: "string" },
53
- milestone: { type: "string" },
54
- fulfills: { type: "string" },
55
- summary: { type: "string" },
56
- sequence: { type: "string" },
57
- evidence: { type: "string" },
58
51
  port: { type: "string" },
59
- // tunnel command flags
60
- provider: { type: "string" },
61
- domain: { type: "string" },
62
- authtoken: { type: "string" },
63
52
  // setup command flags
64
53
  edit: { type: "boolean" },
65
54
  wizard: { type: "boolean" },
66
- // remote command flags
67
- url: { type: "string" },
68
- "hq-url": { type: "string" },
69
55
  // send command flags
70
56
  to: { type: "string" },
71
57
  "no-enter": { type: "boolean" },
58
+ // wait command flags
59
+ status: { type: "string" },
60
+ timeout: { type: "string" },
61
+ match: { type: "string" },
62
+ // events command flag
63
+ follow: { type: "boolean" },
64
+ // force the team cockpit instead of launching a project
65
+ team: { type: "boolean" },
66
+ // adopt every live (non-internal) session at once
67
+ all: { type: "boolean" },
68
+ // restore: print the plan without touching tmux
69
+ "dry-run": { type: "boolean" },
70
+ // restore: replay recorded pane commands (off by default for safety)
71
+ "run-commands": { type: "boolean" },
72
+ // restore: revive agent conversations via `claude --resume <id>`
73
+ "resume-agents": { type: "boolean" },
74
+ // statusline: the session whose bar is being rendered
75
+ active: { type: "string" },
76
+ // switcher: the tmux client the popup was invoked on (see `switcher` case)
77
+ client: { type: "string" },
78
+ // team --popup: run the home cockpit as a popup over a tmux client (M-h)
79
+ popup: { type: "boolean" },
80
+ // sidebar-toggle: the session whose nav column is toggled (see `sidebar-toggle`)
81
+ session: { type: "string" },
82
+ // menu: the click position (mouse binds forward #{mouse_x}/#{mouse_y}) so the
83
+ // actions menu opens at the pointer instead of centered (see `menu` case)
84
+ x: { type: "string" },
85
+ y: { type: "string" },
86
+ // worktree: base ref for a new branch, the worktree checkout dir override,
87
+ // skip creating a session, and force-remove a dirty worktree (see `worktree`)
88
+ from: { type: "string" },
89
+ dir: { type: "string" },
90
+ "no-session": { type: "boolean" },
91
+ force: { type: "boolean" },
72
92
  },
73
93
  });
74
94
 
@@ -78,6 +98,7 @@ const knownCommands = new Set([
78
98
  "stop",
79
99
  "attach",
80
100
  "restart",
101
+ "restore",
81
102
  "ls",
82
103
  "doctor",
83
104
  "status",
@@ -85,23 +106,29 @@ const knownCommands = new Set([
85
106
  "validate",
86
107
  "detect",
87
108
  "config",
88
- "mission",
89
- "milestone",
90
- "goal",
91
- "task",
92
- "research",
93
- "plan",
94
- "skill",
95
- "metrics",
96
109
  "setup",
97
110
  "send",
98
- "dispatch",
99
- "notify",
100
- "orchestrator",
101
111
  "settings",
112
+ "team",
113
+ "switcher",
114
+ "wait",
115
+ "events",
116
+ "statusline",
117
+ "adopt",
118
+ "unadopt",
119
+ "agent",
120
+ "integration",
121
+ "chrome-updater",
122
+ "cheatsheet",
123
+ "welcome",
124
+ "menu",
125
+ "popup",
126
+ "sidebar-toggle",
127
+ "worktree",
128
+ "update",
129
+ "skill-sync",
102
130
  "command-center",
103
- "tunnel",
104
- "remote",
131
+ "server",
105
132
  "help",
106
133
  ]);
107
134
 
@@ -116,17 +143,8 @@ if (values.verbose) {
116
143
  globalThis.__tmuxIdeVerbose = true;
117
144
  }
118
145
 
119
- const ALIASES: Record<string, string> = {
120
- t: "task",
121
- g: "goal",
122
- m: "mission",
123
- ms: "milestone",
124
- orch: "orchestrator",
125
- o: "orchestrator",
126
- met: "metrics",
127
- };
128
146
  const firstPositional = positionals[0];
129
- const resolved = ALIASES[firstPositional] ?? firstPositional;
147
+ const resolved = firstPositional;
130
148
  const hasKnownCommand = resolved ? knownCommands.has(resolved) : false;
131
149
  const command = hasKnownCommand ? resolved : "start";
132
150
  const startTargetDir = hasKnownCommand ? positionals[1] : firstPositional;
@@ -146,19 +164,45 @@ function printHelp() {
146
164
  console.log(`${bold("tmux-ide")} — Terminal IDE powered by tmux
147
165
 
148
166
  ${bold("Usage:")}
149
- ${cyan("tmux-ide")} ${dim("Launch IDE from ide.yml")}
150
- ${cyan("tmux-ide <path>")} ${dim("Launch from a specific directory")}
167
+ ${cyan("tmux-ide")} ${dim("Launch ide.yml, or open the team cockpit if none")}
168
+ ${cyan("tmux-ide <path>")} ${dim("Launch from a specific directory (cockpit if no ide.yml)")}
151
169
  ${cyan("tmux-ide setup")} ${dim("Interactive TUI setup wizard")}
152
170
  ${cyan("tmux-ide setup --edit")} ${dim("Open config tree editor")}
153
171
  ${cyan("tmux-ide settings")} ${dim("Interactive TUI config manager")}
154
172
  ${cyan("tmux-ide init")} [--template] ${dim("Scaffold a new ide.yml (auto-detects stack)")}
155
173
  ${cyan("tmux-ide stop")} ${dim("Kill the current IDE session")}
156
174
  ${cyan("tmux-ide restart")} ${dim("Stop and relaunch the IDE session")}
175
+ ${cyan("tmux-ide restore")} [--dry-run] [--run-commands] [--resume-agents] [--json]
176
+ ${dim("Rebuild the fleet from the last snapshot after a tmux crash")}
177
+ ${dim("(--resume-agents revives claude conversations via claude --resume)")}
157
178
  ${cyan("tmux-ide attach")} ${dim("Reattach to a running session")}
179
+ ${cyan("tmux-ide team")} [--json] ${dim("TUI over all tmux sessions (--json prints fleet state)")}
180
+ ${cyan("tmux-ide switcher")} ${dim("Compact session picker (opens in the M-p popup on adopted sessions)")}
181
+ ${cyan("tmux-ide wait agent-status")} <session> --status <s> [--timeout <ms>]
182
+ ${dim("Block until a session reaches a status (exit 0 match / 1 timeout)")}
183
+ ${cyan("tmux-ide wait output")} <pane|session> --match <regex> [--timeout <ms>]
184
+ ${dim("Block until a pane's output matches a regex (exit 0 match / 1 timeout)")}
185
+ ${cyan("tmux-ide events")} [--follow] [--json] ${dim("Stream agent-status transitions (needs an adopted session)")}
186
+ ${cyan("tmux-ide adopt")} <session> ${dim("Add the live tmux-ide status bar to a session")}
187
+ ${cyan("tmux-ide adopt --all")} ${dim("Adopt every live (non-internal) session")}
188
+ ${cyan("tmux-ide unadopt")} <session> ${dim("Remove the status bar")}
189
+ ${cyan("tmux-ide integration install claude")} ${dim("Authoritative agent status via Claude Code hooks")}
190
+ ${cyan("tmux-ide agent explain")} <pane> [--json] ${dim("Debug how a pane's agent state is detected")}
191
+ ${cyan("tmux-ide cheatsheet")} ${dim("Print the key cheat sheet (⌥k / [ ? keys ] popup)")}
192
+ ${cyan("tmux-ide menu")} [--client N] ${dim("Open the right-click actions menu (⌥m / right-click any pane or the bar)")}
193
+ ${cyan("tmux-ide popup")} <widget> ${dim("Open a widget as a floating panel (explorer/changes/config; ⌥e/⌥g/⌥,)")}
194
+ ${cyan("tmux-ide sidebar-toggle")} [--session S] ${dim("Toggle the app nav column (⌥b on adopted sessions)")}
195
+ ${cyan("tmux-ide worktree create")} <branch> [--from <ref>] [--dir <path>] [--no-session]
196
+ ${dim("Add a git worktree (new branch) + open a session in it")}
197
+ ${cyan("tmux-ide worktree open")} <branch> ${dim("Open (or switch to) the session for an existing worktree")}
198
+ ${cyan("tmux-ide worktree list")} [--json] ${dim("List worktrees joined with their session status")}
199
+ ${cyan("tmux-ide worktree remove")} <branch> [--force] ${dim("Kill the worktree's session + remove the worktree")}
158
200
  ${cyan("tmux-ide ls")} ${dim("List all tmux sessions")}
159
201
  ${cyan("tmux-ide status")} [--json] ${dim("Show session status")}
160
202
  ${cyan("tmux-ide inspect")} [--json] ${dim("Show effective config and runtime state")}
161
203
  ${cyan("tmux-ide doctor")} ${dim("Check system requirements")}
204
+ ${cyan("tmux-ide update")} [--dry-run] ${dim("Update tmux-ide (detects dev checkout vs npm/pnpm/bun global)")}
205
+ ${cyan("tmux-ide skill-sync")} ${dim("Refresh the bundled Claude Code skill in ~/.claude/skills/tmux-ide")}
162
206
  ${cyan("tmux-ide validate")} [--json] ${dim("Validate ide.yml")}
163
207
  ${cyan("tmux-ide detect")} [--json] ${dim("Detect project stack")}
164
208
  ${cyan("tmux-ide detect --write")} ${dim("Detect and write ide.yml")}
@@ -175,27 +219,17 @@ ${bold("Pane Messaging:")}
175
219
  ${cyan("tmux-ide send")} --to <name> <message> ${dim("Target by name, title, role, or ID")}
176
220
  ${cyan("tmux-ide send")} <target> --no-enter msg ${dim("Send text without pressing Enter")}
177
221
 
178
- ${bold("Dispatch:")}
179
- ${cyan("tmux-ide dispatch")} <id> [--json] ${dim("Print task context to stdout")}
180
- ${cyan("tmux-ide notify")} <message> [--json] ${dim("Send notification to lead pane")}
181
-
182
- ${bold("Orchestrator:")}
183
- ${cyan("tmux-ide orchestrator")} [--json] ${dim("Show orchestrator status")}
184
- ${cyan("tmux-ide orch")} ${dim("Alias for orchestrator")}
185
-
186
- ${bold("Task Management:")}
187
- ${cyan("tmux-ide mission set")} "title" ${dim("Set the project mission")}
188
- ${cyan("tmux-ide mission show")} ${dim("Show current mission")}
189
- ${cyan("tmux-ide goal list")} ${dim("List goals")}
190
- ${cyan("tmux-ide goal create")} "title" ${dim("Create a goal")}
191
- ${cyan("tmux-ide goal show")} <id> ${dim("Show goal with tasks")}
192
- ${cyan("tmux-ide task list")} [--status X --goal Y] ${dim("List tasks")}
193
- ${cyan("tmux-ide task create")} "title" [--goal id] ${dim("Create a task")}
194
- ${cyan("tmux-ide task claim")} <id> [--assign name] ${dim("Claim a task")}
195
- ${cyan("tmux-ide task done")} <id> [--proof "..."] ${dim("Complete a task")}
196
- ${cyan("tmux-ide task show")} <id> ${dim("Show task with full context")}
197
- ${cyan("tmux-ide research status")} ${dim("Show research agent state")}
198
- ${cyan("tmux-ide research trigger")} <type> ${dim("Manually dispatch a research task")}
222
+ ${bold("Server:")}
223
+ ${cyan("tmux-ide command-center")} [--port N] ${dim("Start the command-center HTTP API")}
224
+ ${cyan("tmux-ide server")} [--port N] ${dim("Start HTTP + PTY WebSocket server")}
225
+
226
+ ${bold("Discover (in the TUI):")}
227
+ ${dim("Bare")} ${cyan("tmux-ide")} ${dim("with no ide.yml opens the HOME cockpit — the fleet home screen.")}
228
+ ${dim("Once a session is adopted, the whole UI is one keystroke away:")}
229
+ ${cyan("⌥h")} ${dim("home cockpit from anywhere ")}${cyan("⌥p")} ${dim("switch session")}
230
+ ${cyan("⌥k")} ${dim("cheat sheet (all keys) ")}${cyan("⌥m")} ${dim("actions menu (or right-click any pane / the bar)")}
231
+ ${cyan("⌥e ⌥g ⌥,")} ${dim("file / changes / config panels ")}${cyan("⌥b")} ${dim("sidebar")}
232
+ ${dim("A first-run welcome card names these keys once. Run")} ${cyan("tmux-ide cheatsheet")} ${dim("to see the full sheet.")}
199
233
 
200
234
  ${bold("Flags:")}
201
235
  ${cyan("--json")} ${dim("Output as JSON (all commands)")}
@@ -206,11 +240,110 @@ ${bold("Flags:")}
206
240
  ${cyan("-v, --version")} ${dim("Show version number")}`);
207
241
  }
208
242
 
243
+ // The TUI surfaces are OpenTUI/Solid `.tsx` that need the `bun` runtime and the
244
+ // checkout sources. On a clean `npm i -g tmux-ide` neither is present, so we
245
+ // fall back to the compiled `tmux-ide-tui` binary (see scripts/build-tui.mjs).
246
+ // `resolveTuiLaunch` encodes the "checkout first, binary second" order; when
247
+ // nothing is available it hands back an actionable reason set for an IdeError.
248
+ function execBunWidget(
249
+ surface: string,
250
+ scriptPath: string,
251
+ args: string[],
252
+ commandLabel: string,
253
+ extraEnv: Record<string, string> = {},
254
+ ): void {
255
+ const launch = resolveTuiLaunch({
256
+ surface,
257
+ scriptPath,
258
+ args,
259
+ checkoutExists: existsSync(scriptPath),
260
+ bunAvailable: isBunAvailable(),
261
+ compiledBinary: findCompiledTui(),
262
+ });
263
+
264
+ if (launch.mode === "unavailable") {
265
+ throw new IdeError(
266
+ `\`tmux-ide ${commandLabel}\` is unavailable because ${launch.reasons.join(" and ")}.\n` +
267
+ `Run it from a cloned tmux-ide checkout with bun installed, or install a release that ships the compiled binary.`,
268
+ { code: "USAGE", exitCode: 1 },
269
+ );
270
+ }
271
+
272
+ const env = { ...process.env, TMUX_IDE_CWD: process.cwd(), ...extraEnv };
273
+ if (launch.mode === "bun") {
274
+ // Spawn from the repo root so bun finds `bunfig.toml` (the @opentui/solid
275
+ // JSX preload). Without this, running from any other cwd — e.g. bare
276
+ // `tmux-ide` in a project dir — falls back to the React JSX runtime and the
277
+ // widget fails to load. The real invocation dir rides in env so in-widget
278
+ // prompts (register / new session) still default to where the user is.
279
+ execFileSync(launch.bin, launch.argv, {
280
+ stdio: "inherit",
281
+ cwd: resolve(__dirname, ".."),
282
+ env,
283
+ });
284
+ return;
285
+ }
286
+
287
+ // Compiled binary: the JSX transform and native dylib are already baked in,
288
+ // so there is no bunfig to find — run from the user's actual cwd (also avoids
289
+ // a stray repo-root bunfig.toml preload the standalone binary can't resolve).
290
+ execFileSync(launch.bin, launch.argv, { stdio: "inherit", env });
291
+ }
292
+
293
+ // The scriptable control surface for the cockpit: print the fleet state as JSON
294
+ // and exit without spawning the (bun/OpenTUI) TUI. Shared by `tmux-ide team
295
+ // --json` and bare `tmux-ide --json` when there's no ide.yml to launch. Dynamic
296
+ // imports keep the interactive path free of the data-layer modules.
297
+ async function printFleetJson(): Promise<void> {
298
+ const { createStatusTracker } = await import("../packages/daemon/src/tui/detect/classify.ts");
299
+ const { listTeamProjects } = await import("../packages/daemon/src/tui/team/projects.ts");
300
+ const { toFleetJson } = await import("../packages/daemon/src/tui/team/report.ts");
301
+ console.log(JSON.stringify(toFleetJson(listTeamProjects(createStatusTracker())), null, 2));
302
+ }
303
+
304
+ const teamScriptPath = resolve(__dirname, "../packages/daemon/src/tui/team/index.tsx");
305
+
306
+ // `tmux-ide team` runs the standalone full-screen cockpit (the OpenTUI app owns
307
+ // the whole terminal). The floating switcher popup (M-p on adopted sessions)
308
+ // supersedes the old nested `[ switcher | main ]` host shell.
309
+ function launchTeamCockpit(): void {
310
+ execBunWidget("team", teamScriptPath, [], "team");
311
+ }
312
+
209
313
  try {
210
314
  switch (command) {
211
- case "start":
315
+ case "start": {
316
+ // npm-style staleness nudge: one dim stderr line when a newer version is
317
+ // cached (never on --json, never blocking — best-effort, and stderr so it
318
+ // can't corrupt piped stdout). The dock is the primary surface; this is the
319
+ // hint for the moment you actually run the command.
320
+ if (!json) {
321
+ try {
322
+ const { getUpdateStatus } = await import("../packages/daemon/src/lib/update-check.ts");
323
+ const { latest, updateAvailable } = getUpdateStatus();
324
+ if (updateAvailable && latest) {
325
+ process.stderr.write(
326
+ dim(`⬆ tmux-ide v${latest} available — run \`tmux-ide update\`\n`),
327
+ );
328
+ }
329
+ } catch {
330
+ // never let the update hint interfere with launching
331
+ }
332
+ }
333
+ const targetDir = resolve(startTargetDir || ".");
334
+ const hasIdeYml = existsSync(join(targetDir, "ide.yml"));
335
+ if (shouldOpenCockpit(hasIdeYml, values.team === true)) {
336
+ // No project here (or --team): the cockpit is the front door.
337
+ if (json) {
338
+ await printFleetJson();
339
+ break;
340
+ }
341
+ launchTeamCockpit();
342
+ break;
343
+ }
212
344
  await launch(startTargetDir, { json });
213
345
  break;
346
+ }
214
347
 
215
348
  case "init":
216
349
  await init({ template: values.template, json });
@@ -228,6 +361,15 @@ try {
228
361
  await restart(positionals[1], { json });
229
362
  break;
230
363
 
364
+ case "restore":
365
+ await restore({
366
+ json,
367
+ dryRun: values["dry-run"] === true,
368
+ runCommands: values["run-commands"] === true,
369
+ resumeAgents: values["resume-agents"] === true,
370
+ });
371
+ break;
372
+
231
373
  case "ls":
232
374
  await ls({ json });
233
375
  break;
@@ -244,31 +386,9 @@ try {
244
386
  await inspect(positionals[1], { json });
245
387
  break;
246
388
 
247
- case "validate": {
248
- const valSub = positionals[1];
249
- if (
250
- valSub === "assert" ||
251
- valSub === "show" ||
252
- valSub === "report" ||
253
- valSub === "coverage" ||
254
- valSub === "help"
255
- ) {
256
- await taskCommand(null, {
257
- json,
258
- action: "validate",
259
- sub: valSub,
260
- args: positionals.slice(2),
261
- values: {
262
- status: values.status,
263
- evidence: values.evidence,
264
- assign: values.assign,
265
- },
266
- });
267
- } else {
268
- await validate(valSub, { json });
269
- }
389
+ case "validate":
390
+ await validate(positionals[1], { json });
270
391
  break;
271
- }
272
392
 
273
393
  case "detect":
274
394
  await detect(positionals[1], { json, write: values.write });
@@ -306,10 +426,13 @@ try {
306
426
  action = "disable-team";
307
427
  configArgs = [];
308
428
  } else if (sub === "edit") {
309
- const scriptPath = resolve(__dirname, "../src/widgets/setup/index.tsx");
310
- execFileSync("bun", [scriptPath, "--dir=" + resolve(startTargetDir || "."), "--edit"], {
311
- stdio: "inherit",
312
- });
429
+ const scriptPath = resolve(__dirname, "../packages/daemon/src/widgets/setup/index.tsx");
430
+ execBunWidget(
431
+ "setup",
432
+ scriptPath,
433
+ ["--dir=" + resolve(startTargetDir || "."), "--edit"],
434
+ "config edit",
435
+ );
313
436
  break;
314
437
  }
315
438
 
@@ -317,206 +440,966 @@ try {
317
440
  break;
318
441
  }
319
442
 
320
- case "mission": {
321
- const sub = positionals[1];
322
- await taskCommand(null, {
323
- json,
324
- action: "mission",
325
- sub,
326
- args: positionals.slice(2),
327
- values: { description: values.description },
328
- });
443
+ case "setup": {
444
+ const scriptPath = resolve(__dirname, "../packages/daemon/src/widgets/setup/index.tsx");
445
+ const setupArgs = ["--dir=" + resolve(startTargetDir || ".")];
446
+ if (positionals[1] === "--edit" || values.edit) setupArgs.push("--edit");
447
+ if (positionals[1] === "--wizard" || values.wizard) setupArgs.push("--wizard");
448
+ execBunWidget("setup", scriptPath, setupArgs, "setup");
329
449
  break;
330
450
  }
331
451
 
332
- case "milestone": {
333
- const sub = positionals[1];
334
- await taskCommand(null, {
335
- json,
336
- action: "milestone",
337
- sub,
338
- args: positionals.slice(2),
339
- values: {
340
- description: values.description,
341
- status: values.status,
342
- sequence: values.sequence,
343
- },
344
- });
452
+ case "send": {
453
+ const target = values.to ?? positionals[1];
454
+ const messageStart = values.to ? 1 : 2;
455
+ let message = positionals.slice(messageStart).join(" ");
456
+ if (!message && !process.stdin.isTTY) {
457
+ const { readFileSync } = await import("node:fs");
458
+ message = readFileSync(0, "utf-8").trim();
459
+ }
460
+ await send(null, { json, to: target, message, noEnter: values["no-enter"] });
345
461
  break;
346
462
  }
347
463
 
348
- case "goal": {
349
- const sub = positionals[1];
350
- await taskCommand(null, {
351
- json,
352
- action: "goal",
353
- sub,
354
- args: positionals.slice(2),
355
- values: {
356
- description: values.description,
357
- acceptance: values.acceptance,
358
- priority: values.priority,
359
- status: values.status,
360
- specialty: values.specialty,
361
- },
362
- });
464
+ case "settings": {
465
+ const scriptPath = resolve(__dirname, "../packages/daemon/src/widgets/config/index.tsx");
466
+ execBunWidget("config", scriptPath, ["--dir=" + resolve(startTargetDir || ".")], "settings");
363
467
  break;
364
468
  }
365
469
 
366
- case "task": {
367
- const sub = positionals[1];
368
- await taskCommand(null, {
369
- json,
370
- action: "task",
371
- sub,
372
- args: positionals.slice(2),
373
- values: {
374
- title: values.title,
375
- description: values.description,
376
- priority: values.priority,
377
- status: values.status,
378
- assign: values.assign,
379
- goal: values.goal,
380
- tags: values.tags,
381
- proof: values.proof,
382
- depends: values.depends,
383
- pr: values.pr,
384
- specialty: values.specialty,
385
- milestone: values.milestone,
386
- fulfills: values.fulfills,
387
- summary: values.summary,
388
- },
389
- });
470
+ case "team": {
471
+ // `--json` is the scriptable control surface: print the fleet state and
472
+ // exit without spawning the (bun/OpenTUI) TUI.
473
+ if (json) {
474
+ await printFleetJson();
475
+ break;
476
+ }
477
+ // `--popup` runs the FULL home cockpit inside a tmux `display-popup` (bound
478
+ // to `M-h` on adopt / the dock's `[ ⌂ home ⌥h ]` trigger). Like the
479
+ // switcher, `TMUX_IDE_POPUP_CLIENT` flips popup mode (Enter switch-clients
480
+ // the invoking client + closes) and carries an optional explicit client;
481
+ // empty means "resolve it yourself from inside the popup". Unlike the
482
+ // switcher it keeps the full two-column layout, not the compact picker.
483
+ if (values.popup === true) {
484
+ const clientArg = typeof values.client === "string" ? values.client : "";
485
+ execBunWidget("team", teamScriptPath, [], "team --popup", {
486
+ TMUX_IDE_POPUP_CLIENT: clientArg,
487
+ });
488
+ break;
489
+ }
490
+ launchTeamCockpit();
390
491
  break;
391
492
  }
392
493
 
393
- case "research": {
494
+ case "switcher": {
495
+ // Runs the team app in PICKER mode inside a tmux `display-popup` (bound to
496
+ // `M-p` on adopt). Picking a session `switch-client`s the invoking client
497
+ // there and the app exits, closing the popup. `TMUX_IDE_PICKER_CLIENT`
498
+ // both flips the app into picker mode and carries an optional explicit
499
+ // client name; empty means "resolve it yourself from inside the popup".
500
+ const clientArg = typeof values.client === "string" ? values.client : "";
501
+ execBunWidget("team", teamScriptPath, [], "switcher", { TMUX_IDE_PICKER_CLIENT: clientArg });
502
+ break;
503
+ }
504
+
505
+ case "wait": {
394
506
  const sub = positionals[1];
395
- await taskCommand(null, {
396
- json,
397
- action: "research",
398
- sub,
399
- args: positionals.slice(2),
400
- values: {},
507
+
508
+ // `wait output <pane|session> --match <regex>` — block until a pane's
509
+ // captured text matches. The target may be a pane id (%N) or a session
510
+ // name; tmux resolves both (a session targets its active pane).
511
+ if (sub === "output") {
512
+ const target = positionals[2];
513
+ const pattern = values.match;
514
+ if (!target || typeof pattern !== "string" || pattern.length === 0) {
515
+ console.error(
516
+ "Usage: tmux-ide wait output <pane|session> --match <regex> [--timeout <ms>]",
517
+ );
518
+ process.exit(1);
519
+ }
520
+ try {
521
+ new RegExp(pattern!); // validate up front; a bad pattern is a usage error
522
+ } catch (err) {
523
+ console.error(`Invalid --match regex: ${(err as Error).message}`);
524
+ process.exit(1);
525
+ }
526
+ const { capturePane } = await import("../packages/tmux-bridge/src/index.ts");
527
+ const outTimeout = Number(values.timeout ?? "60000");
528
+ const outStart = Date.now();
529
+ const nap = (ms: number) => new Promise((r) => setTimeout(r, ms));
530
+ while (true) {
531
+ let text = "";
532
+ try {
533
+ text = capturePane(target!, { lines: 200 });
534
+ } catch {
535
+ // pane/session not (yet) available — keep polling until timeout
536
+ }
537
+ const lines = text.split("\n");
538
+ // Fresh regex per test so a user-supplied /g flag can't carry lastIndex
539
+ // between calls. Report the specific matching line when we can.
540
+ let hit: string | null = null;
541
+ for (const line of lines) {
542
+ if (new RegExp(pattern!).test(line)) {
543
+ hit = line;
544
+ break;
545
+ }
546
+ }
547
+ if (hit === null && new RegExp(pattern!).test(text)) hit = lines[lines.length - 1] ?? "";
548
+ if (hit !== null) {
549
+ if (json) console.log(JSON.stringify({ matched: hit }));
550
+ else console.log(hit);
551
+ process.exit(0);
552
+ }
553
+ if (Date.now() - outStart >= outTimeout) {
554
+ console.error(
555
+ `Timed out after ${outTimeout}ms waiting for ${target} output to match /${pattern}/`,
556
+ );
557
+ process.exit(1);
558
+ }
559
+ await nap(500);
560
+ }
561
+ }
562
+
563
+ const { createStatusTracker } = await import("../packages/daemon/src/tui/detect/classify.ts");
564
+ const { listTeamSessions } = await import("../packages/daemon/src/tui/team/sessions.ts");
565
+ const { findSessionStatus } = await import("../packages/daemon/src/tui/team/report.ts");
566
+
567
+ const VALID = new Set(["blocked", "working", "done", "idle", "unknown"]);
568
+ const sessionName = positionals[2];
569
+ const want = values.status;
570
+
571
+ if (sub !== "agent-status" || !sessionName || typeof want !== "string" || !VALID.has(want)) {
572
+ console.error(
573
+ "Usage: tmux-ide wait agent-status <session> --status <blocked|working|done|idle|unknown> [--timeout <ms>]",
574
+ );
575
+ process.exit(1);
576
+ }
577
+
578
+ const timeout = Number(values.timeout ?? "60000");
579
+ const started = Date.now();
580
+ const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
581
+ // One tracker persists across polls so the working→idle `done` transition
582
+ // can be observed (it's inherently cross-tick).
583
+ const tracker = createStatusTracker();
584
+
585
+ while (true) {
586
+ const sessions = listTeamSessions(tracker);
587
+ const status = findSessionStatus(sessions, sessionName!);
588
+ if (status === want) {
589
+ if (json) {
590
+ console.log(JSON.stringify({ session: sessionName, status, ok: true }));
591
+ } else {
592
+ console.log(`${sessionName} reached status: ${status}`);
593
+ }
594
+ process.exit(0);
595
+ }
596
+ if (Date.now() - started >= timeout) {
597
+ console.error(
598
+ `Timed out after ${timeout}ms waiting for ${sessionName} to reach status "${want}" (last: ${status ?? "absent"})`,
599
+ );
600
+ process.exit(1);
601
+ }
602
+ await sleep(750);
603
+ }
604
+ }
605
+
606
+ case "events": {
607
+ // Stream agent-status transitions from the log the chrome updater writes.
608
+ const { readFileSync, existsSync, statSync, openSync, readSync, closeSync } =
609
+ await import("node:fs");
610
+ const { eventsPath, formatEventLine } =
611
+ await import("../packages/daemon/src/tui/chrome/events.ts");
612
+ type Status = "blocked" | "working" | "done" | "idle" | "unknown";
613
+ type EventLike = { ts: string; session: string; from: Status | null; to: Status };
614
+
615
+ const path = eventsPath();
616
+ if (!existsSync(path)) {
617
+ console.log("no events yet — is a session adopted? (the chrome updater writes events)");
618
+ break;
619
+ }
620
+
621
+ // Status → ANSI color, matching the chrome bar's palette in spirit.
622
+ const paintStatus = (status: Status | null, text: string): string => {
623
+ if (noColor || status === null) return text;
624
+ const code =
625
+ status === "blocked"
626
+ ? "203"
627
+ : status === "working"
628
+ ? "221"
629
+ : status === "done"
630
+ ? "111"
631
+ : status === "idle"
632
+ ? "114"
633
+ : "244";
634
+ return `\x1b[38;5;${code}m${text}\x1b[39m`;
635
+ };
636
+ const printLine = (raw: string): void => {
637
+ if (json) {
638
+ console.log(raw);
639
+ return;
640
+ }
641
+ try {
642
+ const ev = JSON.parse(raw) as EventLike;
643
+ console.log(formatEventLine(ev, paintStatus));
644
+ } catch {
645
+ // skip malformed line
646
+ }
647
+ };
648
+
649
+ const allLines = readFileSync(path, "utf8")
650
+ .split("\n")
651
+ .filter((l) => l.trim().length > 0);
652
+ for (const line of allLines.slice(-50)) printLine(line);
653
+
654
+ if (!values.follow) break;
655
+
656
+ // Follow: poll the file for appended bytes and stream complete new lines.
657
+ let offset = statSync(path).size;
658
+ let leftover = "";
659
+ const timer = setInterval(() => {
660
+ let size: number;
661
+ try {
662
+ size = statSync(path).size;
663
+ } catch {
664
+ return;
665
+ }
666
+ if (size < offset) {
667
+ // rotated/truncated — restart from the top of the new file
668
+ offset = 0;
669
+ leftover = "";
670
+ }
671
+ if (size <= offset) return;
672
+ const fd = openSync(path, "r");
673
+ try {
674
+ const buf = Buffer.alloc(size - offset);
675
+ readSync(fd, buf, 0, buf.length, offset);
676
+ offset = size;
677
+ const parts = (leftover + buf.toString("utf8")).split("\n");
678
+ leftover = parts.pop() ?? "";
679
+ for (const line of parts) if (line.trim().length > 0) printLine(line);
680
+ } finally {
681
+ closeSync(fd);
682
+ }
683
+ }, 500);
684
+ process.on("SIGINT", () => {
685
+ clearInterval(timer);
686
+ process.exit(0);
401
687
  });
688
+ // Keep the process alive; the interval + SIGINT handler own the lifecycle.
689
+ await new Promise(() => {});
402
690
  break;
403
691
  }
404
692
 
405
- case "plan": {
406
- const { planCommand } = await import("../src/plan.ts");
407
- await planCommand(null, {
408
- json,
409
- sub: positionals[1],
410
- args: positionals.slice(2),
411
- values: { status: values.status },
412
- });
693
+ case "statusline": {
694
+ // Called by tmux via #() every status-interval — keep it lean and never
695
+ // let an error corrupt the bar (print a minimal brand instead).
696
+ try {
697
+ const { createStatusTracker } =
698
+ await import("../packages/daemon/src/tui/detect/classify.ts");
699
+ const { listTeamProjects } = await import("../packages/daemon/src/tui/team/projects.ts");
700
+ const { buildStatusline } = await import("../packages/daemon/src/tui/chrome/statusline.ts");
701
+ const { getAppConfig } = await import("../packages/daemon/src/lib/app-config.ts");
702
+ const projects = listTeamProjects(createStatusTracker());
703
+ console.log(buildStatusline(projects, values.active ?? null, 12, getAppConfig().theme));
704
+ } catch {
705
+ console.log("#[fg=colour75,bold] tmux-ide #[default]");
706
+ }
413
707
  break;
414
708
  }
415
709
 
416
- case "skill": {
417
- const { skillCommand } = await import("../src/skill.ts");
418
- await skillCommand(null, {
419
- json,
420
- sub: positionals[1],
421
- args: positionals.slice(2),
422
- });
710
+ case "adopt": {
711
+ const { adoptSession, adoptableSessionNames } =
712
+ await import("../packages/daemon/src/tui/chrome/statusline.ts");
713
+ if (values.all) {
714
+ // Adopt every live session that isn't internal (`_`-prefixed plumbing).
715
+ const raw = execFileSync("tmux", ["list-sessions", "-F", "#{session_name}"], {
716
+ encoding: "utf8",
717
+ stdio: ["ignore", "pipe", "ignore"],
718
+ }).trim();
719
+ const targets = raw ? adoptableSessionNames(raw.split("\n")) : [];
720
+ if (targets.length === 0) {
721
+ console.log("no adoptable sessions");
722
+ break;
723
+ }
724
+ for (const name of targets) {
725
+ adoptSession(name);
726
+ console.log(`adopted ${name}`);
727
+ }
728
+ break;
729
+ }
730
+ const target = positionals[1];
731
+ if (!target) {
732
+ console.error("Usage: tmux-ide adopt <session> | tmux-ide adopt --all");
733
+ process.exit(1);
734
+ }
735
+ adoptSession(target);
736
+ console.log(`adopted ${target} — chrome row active (unadopt to remove)`);
423
737
  break;
424
738
  }
425
739
 
426
- case "metrics": {
427
- const { metricsCommand } = await import("../src/metrics-cli.ts");
428
- await metricsCommand(null, {
429
- json,
430
- sub: positionals[1],
431
- });
740
+ case "unadopt": {
741
+ const { unadoptSession } = await import("../packages/daemon/src/tui/chrome/statusline.ts");
742
+ const target = positionals[1];
743
+ if (!target) {
744
+ console.error("Usage: tmux-ide unadopt <session>");
745
+ process.exit(1);
746
+ }
747
+ unadoptSession(target);
748
+ console.log(`unadopted ${target}`);
432
749
  break;
433
750
  }
434
751
 
435
- case "setup": {
436
- const scriptPath = resolve(__dirname, "../src/widgets/setup/index.tsx");
437
- const setupArgs = [scriptPath, "--dir=" + resolve(startTargetDir || ".")];
438
- if (positionals[1] === "--edit" || values.edit) setupArgs.push("--edit");
439
- if (positionals[1] === "--wizard" || values.wizard) setupArgs.push("--wizard");
440
- execFileSync("bun", setupArgs, { stdio: "inherit" });
752
+ case "agent": {
753
+ const sub = positionals[1];
754
+ const target = positionals[2];
755
+ if (sub !== "explain" || !target) {
756
+ console.error(
757
+ "Usage: tmux-ide agent explain <pane> [--json]\n" +
758
+ " <pane> a pane id (%N) or a session name (uses its active pane)\n" +
759
+ " Prints how the fleet detector classifies the pane: authority,\n" +
760
+ " hint, resolved manifest, per-state rule results, and the snapshot.",
761
+ );
762
+ process.exit(1);
763
+ }
764
+ const { agentExplain } = await import("../packages/daemon/src/agent-explain.ts");
765
+ agentExplain(target, { json });
441
766
  break;
442
767
  }
443
768
 
444
- case "send": {
445
- const target = values.to ?? positionals[1];
446
- const messageStart = values.to ? 1 : 2;
447
- let message = positionals.slice(messageStart).join(" ");
448
- if (!message && !process.stdin.isTTY) {
449
- const { readFileSync } = await import("node:fs");
450
- message = readFileSync(0, "utf-8").trim();
769
+ case "integration": {
770
+ const sub = positionals[1];
771
+ const agent = positionals[2];
772
+ // `status` and `offer` need no agent arg; install/uninstall are claude-only.
773
+ const needsClaude = sub === "install" || sub === "uninstall";
774
+ if (!sub || (needsClaude && agent !== "claude")) {
775
+ console.error(
776
+ "Usage: tmux-ide integration <install|uninstall|status|offer> [claude]\n" +
777
+ " install hook Claude Code lifecycle events into tmux pane state\n" +
778
+ " uninstall remove exactly the tmux-ide hook entries\n" +
779
+ " status list discovered agents + integration state\n" +
780
+ " offer one-time first-adopt install prompt (used by the popup)",
781
+ );
782
+ process.exit(1);
783
+ }
784
+ const mod = await import("../packages/daemon/src/tui/integrations/claude.ts");
785
+ if (sub === "install") {
786
+ const { scriptPath, settingsPath } = mod.installClaudeIntegration();
787
+ // Hooks + skill = the complete agent setup, so one command does both:
788
+ // the lifecycle hooks (authoritative status) AND a fresh copy of the
789
+ // skill that tells the agent how to drive tmux-ide.
790
+ const { syncSkill } = await import("../packages/daemon/src/lib/skill-sync.ts");
791
+ const skill = syncSkill();
792
+ console.log(`hook script: ${scriptPath}`);
793
+ console.log(`settings: ${settingsPath} (backup written once as .tmux-ide.bak)`);
794
+ console.log(`skill: ${skill.action} → ${skill.path} (v${skill.to})`);
795
+ console.log(
796
+ "installed — NEW Claude Code sessions now report working/blocked/done " +
797
+ "authoritatively into the tmux-ide chrome.",
798
+ );
799
+ } else if (sub === "uninstall") {
800
+ const { wasInstalled } = mod.uninstallClaudeIntegration();
801
+ console.log(wasInstalled ? "uninstalled — hook entries removed" : "was not installed");
802
+ } else if (sub === "offer") {
803
+ // The one-time first-adopt prompt, run inside a `display-popup` by
804
+ // adoptSession (see ../packages/daemon/src/tui/integrations/offer.ts). It
805
+ // reads ONE key: `y` installs, anything else skips — and writes the
806
+ // marker either way so it never asks twice. Must never throw or hang.
807
+ const offerMod = await import("../packages/daemon/src/tui/integrations/offer.ts");
808
+ try {
809
+ console.log(offerMod.buildOfferText());
810
+ } catch {
811
+ console.log("Claude Code detected — install the tmux-ide integration? [y/N]");
812
+ }
813
+ const act = (key: string): void => {
814
+ offerMod.markIntegrationOffered();
815
+ if (key === "y" || key === "Y") {
816
+ try {
817
+ mod.installClaudeIntegration();
818
+ console.log("\ninstalled — new Claude Code sessions now report state to tmux-ide.");
819
+ } catch (e) {
820
+ console.log(`\ninstall failed: ${(e as Error).message}`);
821
+ }
822
+ } else {
823
+ console.log("\nskipped — run `tmux-ide integration install claude` anytime.");
824
+ }
825
+ };
826
+ // Test/automation hook: a forced key exits immediately, no stdin — lets
827
+ // the offer flow be exercised deterministically without a live keypress.
828
+ const forced = process.env.TMUX_IDE_OFFER_KEY;
829
+ if (forced !== undefined) {
830
+ act(forced);
831
+ process.exit(0);
832
+ }
833
+ const closeOffer = () => process.exit(0);
834
+ const offerTimer = setTimeout(closeOffer, 60_000);
835
+ offerTimer.unref?.();
836
+ try {
837
+ process.stdin.setRawMode?.(true);
838
+ process.stdin.resume();
839
+ process.stdin.once("data", (data) => {
840
+ act(data.toString());
841
+ console.log("\n[ press any key to close ]");
842
+ process.stdin.once("data", closeOffer);
843
+ process.stdin.once("end", closeOffer);
844
+ });
845
+ process.stdin.once("end", closeOffer);
846
+ } catch {
847
+ closeOffer();
848
+ }
849
+ } else {
850
+ // status — the discovery table: every known agent, whether it's on PATH,
851
+ // and (for agents we integrate) whether the integration is installed.
852
+ const { discoverAgents } = await import("../packages/daemon/src/lib/agent-discovery.ts");
853
+ const agents = discoverAgents();
854
+ if (json) {
855
+ console.log(JSON.stringify({ agents }, null, 2));
856
+ break;
857
+ }
858
+ for (const a of agents) {
859
+ let state: string;
860
+ if (a.path === null) state = "not found";
861
+ else if (a.integration)
862
+ state = a.installed ? "integration installed ✓" : "on PATH — integration not installed";
863
+ else state = "detected (no integration)";
864
+ console.log(` ${a.id.padEnd(10)} ${state}`);
865
+ }
451
866
  }
452
- await send(null, { json, to: target, message, noEnter: values["no-enter"] });
453
867
  break;
454
868
  }
455
869
 
456
- case "dispatch": {
457
- const { dispatch: dispatchCmd } = await import("../src/dispatch.ts");
458
- const taskId = positionals[1];
459
- await dispatchCmd(null, { taskId, json });
870
+ case "chrome-updater": {
871
+ // The background loop that keeps every adopted session's status var fresh.
872
+ // Hosted in the hidden `_tmux-ide-chrome` tmux session (started on adopt);
873
+ // blocks forever. Never let a boot error crash it — a dead updater just
874
+ // means stale bars, not broken sessions.
875
+ try {
876
+ const { runUpdaterLoop } = await import("../packages/daemon/src/tui/chrome/updater.ts");
877
+ runUpdaterLoop();
878
+ } catch {
879
+ process.exit(0);
880
+ }
460
881
  break;
461
882
  }
462
883
 
463
- case "notify": {
464
- const { notify: notifyCmd } = await import("../src/notify.ts");
465
- const notifyMessage = positionals.slice(1).join(" ");
466
- await notifyCmd(null, { message: notifyMessage || undefined, json });
884
+ case "cheatsheet": {
885
+ // Renders the static key cheat sheet, then blocks until ANY key closes it
886
+ // (the popup exits). Runs inside a tmux `display-popup` (bound to M-k on
887
+ // adopt / the `[ ? keys ]` bar trigger), so it must never throw — a broken
888
+ // render should still print something and still close on a keypress.
889
+ try {
890
+ const { buildCheatsheet } = await import("../packages/daemon/src/tui/chrome/cheatsheet.ts");
891
+ const { getAppConfig } = await import("../packages/daemon/src/lib/app-config.ts");
892
+ const cfg = getAppConfig();
893
+ console.log(
894
+ buildCheatsheet({
895
+ width: process.stdout.columns ?? 100,
896
+ keys: cfg.keys,
897
+ theme: cfg.theme,
898
+ }),
899
+ );
900
+ } catch {
901
+ console.log("tmux-ide — press ⌥p for the switcher, ⌥k for this sheet. Any key closes.");
902
+ }
903
+ // Wait for a single keypress, then exit 0 so the popup closes. Fall back to
904
+ // an auto-close after 60s if stdin never delivers (e.g. no raw mode).
905
+ const close = () => process.exit(0);
906
+ const timer = setTimeout(close, 60_000);
907
+ timer.unref?.();
908
+ try {
909
+ process.stdin.setRawMode?.(true);
910
+ process.stdin.resume();
911
+ process.stdin.once("data", close);
912
+ // A closed/redirected stdin (`</dev/null`, piped) hits EOF instead of
913
+ // ever delivering a key — close on that too so the command can't hang.
914
+ process.stdin.once("end", close);
915
+ } catch {
916
+ close();
917
+ }
467
918
  break;
468
919
  }
469
920
 
470
- case "orchestrator": {
471
- const { orchestratorStatus } = await import("../src/orchestrator-status.ts");
472
- await orchestratorStatus(positionals[1], { json });
921
+ case "welcome": {
922
+ // Prints the one-time first-run welcome card, then blocks until ANY key
923
+ // closes it (the popup exits). Floated by `adoptSession` via a
924
+ // `display-popup -E "tmux-ide welcome"` on first adopt (see
925
+ // ./chrome/welcome.ts). Mirrors the cheatsheet case — must never throw, and
926
+ // must close on a key / EOF / a 60s fallback so the popup can't hang.
927
+ try {
928
+ const { buildWelcomeText } = await import("../packages/daemon/src/tui/chrome/welcome.ts");
929
+ const { getAppConfig } = await import("../packages/daemon/src/lib/app-config.ts");
930
+ console.log(buildWelcomeText(getAppConfig().keys));
931
+ } catch {
932
+ console.log(
933
+ "Welcome to tmux-ide. Right-click for the menu · ⌥h home · ⌥p switch · ⌥k all keys.",
934
+ );
935
+ }
936
+ const closeWelcome = () => process.exit(0);
937
+ const welcomeTimer = setTimeout(closeWelcome, 60_000);
938
+ welcomeTimer.unref?.();
939
+ try {
940
+ process.stdin.setRawMode?.(true);
941
+ process.stdin.resume();
942
+ process.stdin.once("data", closeWelcome);
943
+ process.stdin.once("end", closeWelcome);
944
+ } catch {
945
+ closeWelcome();
946
+ }
473
947
  break;
474
948
  }
475
949
 
476
- case "settings": {
477
- const scriptPath = resolve(__dirname, "../src/widgets/config/index.tsx");
478
- execFileSync("bun", [scriptPath, "--dir=" + resolve(startTargetDir || ".")], {
479
- stdio: "inherit",
480
- });
950
+ case "menu": {
951
+ // Build the native tmux actions menu at CLICK TIME (the session list is
952
+ // live) and display it on the invoking client. Bound via `run-shell -b` so
953
+ // `#{client_name}` format-expands into `--client` (verified live on tmux
954
+ // 3.6 — it resolves to the triggering / most-recently-active client). Runs
955
+ // inside tmux's key/mouse dispatch, so it must never throw or HANG — every
956
+ // tmux call below is capped at 2s and a missing client degrades to a no-op.
957
+ try {
958
+ // Every tmux shell-out gets a hard 2s cap: the old fallback
959
+ // (`display-message -p '#{client_name}'` from outside a client) could
960
+ // block indefinitely and wedge the bind. `timeout` throws on expiry,
961
+ // caught below → silent no-op.
962
+ const tmuxCap = {
963
+ encoding: "utf8" as const,
964
+ stdio: ["ignore", "pipe", "ignore"] as const,
965
+ timeout: 2000,
966
+ };
967
+ // Resolve the target client. Prefer the `--client` the bind expanded; if
968
+ // it's empty or an unexpanded `#{…}` literal, fall back to the
969
+ // most-recently-active attached client (list-clients sorted by
970
+ // client_activity desc). No clients at all → exit 0 silently (fired from
971
+ // tmux dispatch, a no-op beats an error).
972
+ const rawClient = typeof values.client === "string" ? values.client : "";
973
+ let client = rawClient && !rawClient.includes("#{") ? rawClient : "";
974
+ if (!client) {
975
+ const raw = execFileSync(
976
+ "tmux",
977
+ ["list-clients", "-F", "#{client_activity} #{client_name}"],
978
+ tmuxCap,
979
+ ).trim();
980
+ const newest = raw
981
+ .split("\n")
982
+ .filter(Boolean)
983
+ .map((line) => {
984
+ const sp = line.indexOf(" ");
985
+ return { activity: Number(line.slice(0, sp)), name: line.slice(sp + 1) };
986
+ })
987
+ .sort((a, b) => b.activity - a.activity)[0];
988
+ client = newest?.name ?? "";
989
+ }
990
+ if (!client) break; // no attached clients — nothing to show
991
+ const { createStatusTracker } =
992
+ await import("../packages/daemon/src/tui/detect/classify.ts");
993
+ const { listTeamSessions } = await import("../packages/daemon/src/tui/team/sessions.ts");
994
+ const { buildMenu, menuPositionArgs } =
995
+ await import("../packages/daemon/src/tui/chrome/menu.ts");
996
+ const { getAppConfig } = await import("../packages/daemon/src/lib/app-config.ts");
997
+ const { getUpdateStatus } = await import("../packages/daemon/src/lib/update-check.ts");
998
+ // listTeamSessions already drops internal `_`-prefixed plumbing.
999
+ const sessions = listTeamSessions(createStatusTracker()).map((s) => ({
1000
+ name: s.name,
1001
+ status: s.status,
1002
+ }));
1003
+ // Position flags from a mouse bind's forwarded coords; empty (→ centered)
1004
+ // for the keyboard path or unexpanded #{mouse_*} literals. Must precede
1005
+ // the menu spec (buildMenu opens with -T), so they slot in right after -c.
1006
+ const position = menuPositionArgs(
1007
+ typeof values.x === "string" ? values.x : undefined,
1008
+ typeof values.y === "string" ? values.y : undefined,
1009
+ );
1010
+ const args = [
1011
+ "display-menu",
1012
+ "-c",
1013
+ client,
1014
+ ...position,
1015
+ ...buildMenu(sessions, getAppConfig().theme, getUpdateStatus()),
1016
+ ];
1017
+ execFileSync("tmux", args, { stdio: "ignore", timeout: 2000 });
1018
+ } catch {
1019
+ // no client / tmux unavailable / a call timed out — nothing to show
1020
+ }
481
1021
  break;
482
1022
  }
483
1023
 
484
- case "tunnel": {
485
- const { tunnelCommand } = await import("../src/tunnel.ts");
486
- await tunnelCommand(null, {
487
- json,
488
- sub: positionals[1],
489
- args: positionals.slice(2),
490
- values: {
491
- provider: values.provider,
492
- port: values.port,
493
- domain: values.domain,
494
- authtoken: values.authtoken,
495
- },
496
- });
1024
+ case "popup": {
1025
+ // Open a widget as a floating panel. This CLI invocation IS the popup
1026
+ // process (a root-table key or a menu row ran `display-popup -E "tmux-ide
1027
+ // popup <widget>"`), so we exec the bun widget SYNCHRONOUSLY into the
1028
+ // popup's PTY; when the widget exits (esc/q) the popup closes.
1029
+ const { POPUP_WIDGETS } = await import("../packages/daemon/src/tui/chrome/panels.ts");
1030
+ const widget = positionals[1];
1031
+ if (!widget || !POPUP_WIDGETS.includes(widget)) {
1032
+ throw new IdeError(
1033
+ `Usage: tmux-ide popup <widget>\nKnown panels: ${POPUP_WIDGETS.join(", ")}.`,
1034
+ { code: "USAGE", exitCode: 1 },
1035
+ );
1036
+ }
1037
+ // Resolve the widget entry from THIS file's dir (bin/), mirroring the
1038
+ // setup/config cases — the bundler rewrites `import.meta.url` to the bin/
1039
+ // bundle, so a `resolve.ts`-relative path would miss the sources.
1040
+ const scriptPath = resolve(__dirname, "../packages/daemon/src/widgets", widget, "index.tsx");
1041
+ // The popup opened with `-d '#{pane_current_path}'`, so our cwd IS the
1042
+ // pane's project dir — forward it as `--dir`. Resolve the session so the
1043
+ // widget's tmux side-channels (preview file, "send to claude") target it;
1044
+ // best-effort — an empty session just disables those (the widget still
1045
+ // renders and browses).
1046
+ let popupSession = "";
1047
+ try {
1048
+ popupSession = execFileSync("tmux", ["display-message", "-p", "#{session_name}"], {
1049
+ encoding: "utf8",
1050
+ stdio: ["ignore", "pipe", "ignore"],
1051
+ timeout: 2000,
1052
+ }).trim();
1053
+ } catch {
1054
+ // not inside a tmux client — leave session empty
1055
+ }
1056
+ const popupArgs = [`--dir=${process.cwd()}`];
1057
+ if (popupSession) popupArgs.push(`--session=${popupSession}`);
1058
+ execBunWidget(widget, scriptPath, popupArgs, `popup ${widget}`);
497
1059
  break;
498
1060
  }
499
1061
 
500
- case "remote": {
501
- const { remoteCommand } = await import("../src/remote.ts");
502
- await remoteCommand(null, {
503
- json,
504
- sub: positionals[1],
505
- args: positionals.slice(2),
506
- values: {
507
- url: values.url,
508
- "hq-url": values["hq-url"],
509
- },
1062
+ case "sidebar-toggle": {
1063
+ // Toggle the app nav column in a session (bound to `keys.sidebar`, default
1064
+ // M-b, via `run-shell` which expands `--session '#{session_name}'`). If a
1065
+ // sidebar pane already exists → close it; else split a full-height left
1066
+ // column running the sidebar widget. Runs inside tmux key dispatch, so it
1067
+ // stays best-effort — a failure is a silent no-op, never a wedged bind.
1068
+ try {
1069
+ const {
1070
+ findSidebarPane,
1071
+ openSidebarPane,
1072
+ closeSidebarPane,
1073
+ resolveSidebarConfig,
1074
+ DEFAULT_SIDEBAR_WIDTH,
1075
+ } = await import("../packages/daemon/src/tui/chrome/sidebar.ts");
1076
+ // Resolve the target session: the explicit --session, else the invoking
1077
+ // client's session via display-message.
1078
+ let session = typeof values.session === "string" ? values.session.trim() : "";
1079
+ if (!session || session.includes("#{")) {
1080
+ try {
1081
+ session = execFileSync("tmux", ["display-message", "-p", "#{session_name}"], {
1082
+ encoding: "utf8",
1083
+ stdio: ["ignore", "pipe", "ignore"],
1084
+ timeout: 2000,
1085
+ }).trim();
1086
+ } catch {
1087
+ session = "";
1088
+ }
1089
+ }
1090
+ if (!session) break; // no session context — nothing to toggle
1091
+ const existing = findSidebarPane(session);
1092
+ if (existing) {
1093
+ closeSidebarPane(existing);
1094
+ break;
1095
+ }
1096
+ // Opening: resolve the session's cwd + best-effort sidebar width/theme
1097
+ // from an ide.yml there (any adopted session may have none → defaults).
1098
+ const { getSessionCwd } = await import("../packages/tmux-bridge/src/index.ts");
1099
+ let dir = process.cwd();
1100
+ try {
1101
+ dir = getSessionCwd(session) ?? dir;
1102
+ } catch {
1103
+ // no cwd — fall back to the CLI's cwd
1104
+ }
1105
+ let width = DEFAULT_SIDEBAR_WIDTH;
1106
+ let theme = null;
1107
+ try {
1108
+ const { readConfig } = await import("../packages/daemon/src/lib/yaml-io.ts");
1109
+ const { config } = readConfig(dir);
1110
+ theme = config.theme ?? null;
1111
+ const sb = resolveSidebarConfig(config.sidebar);
1112
+ if (sb.enabled) width = sb.width;
1113
+ } catch {
1114
+ // no/invalid ide.yml — defaults are fine
1115
+ }
1116
+ openSidebarPane(session, dir, width, theme);
1117
+ } catch {
1118
+ // tmux unavailable / widget missing — silent no-op (fired from a bind)
1119
+ }
1120
+ break;
1121
+ }
1122
+
1123
+ case "worktree": {
1124
+ const sub = positionals[1];
1125
+ const KNOWN_SUBS = new Set(["create", "open", "list", "remove"]);
1126
+ if (!sub || !KNOWN_SUBS.has(sub)) {
1127
+ throw new IdeError(
1128
+ "Usage: tmux-ide worktree <create|open|list|remove> <branch> [flags]\n" +
1129
+ " create <branch> [--from <ref>] [--dir <path>] [--no-session]\n" +
1130
+ " open <branch>\n" +
1131
+ " list [--json]\n" +
1132
+ " remove <branch> [--force]",
1133
+ { code: "USAGE", exitCode: 1 },
1134
+ );
1135
+ }
1136
+
1137
+ const {
1138
+ worktreeSessionName,
1139
+ worktreePath,
1140
+ listWorktrees,
1141
+ createWorktree,
1142
+ removeWorktree,
1143
+ WorktreeError,
1144
+ } = await import("../packages/daemon/src/lib/worktree.ts");
1145
+ const { getSessionName } = await import("../packages/daemon/src/lib/yaml-io.ts");
1146
+ const { getSessionCwd, hasSession, killSession, createDetachedSession } =
1147
+ await import("../packages/tmux-bridge/src/index.ts");
1148
+
1149
+ // The repo the command targets: the --session's cwd when invoked from the
1150
+ // menu (run-shell's own cwd is the tmux server's, not the pane's — verified
1151
+ // live), else the CLI's cwd.
1152
+ let repoDir = process.cwd();
1153
+ const sessionArg = typeof values.session === "string" ? values.session.trim() : "";
1154
+ if (sessionArg && !sessionArg.includes("#{")) {
1155
+ try {
1156
+ const cwd = getSessionCwd(sessionArg);
1157
+ if (cwd) repoDir = cwd;
1158
+ } catch {
1159
+ // fall back to the CLI cwd
1160
+ }
1161
+ }
1162
+
1163
+ // The project identity for session names: the MAIN worktree's ide.yml name
1164
+ // (or its dir basename). `git worktree list` returns the main checkout first.
1165
+ const worktrees = listWorktrees(repoDir);
1166
+ const mainPath = worktrees[0]?.path ?? repoDir;
1167
+ const projectName = getSessionName(mainPath).name;
1168
+
1169
+ // Start a session in a worktree checkout: full IDE layout when it has an
1170
+ // ide.yml (launch under the worktree's own session name so it never
1171
+ // collides with the parent repo's session), else a plain adopted session.
1172
+ // Never auto-attaches — the caller may be inside tmux (the menu) — it prints
1173
+ // how to switch instead.
1174
+ async function openWorktreeSession(wtPath: string, name: string): Promise<void> {
1175
+ if (existsSync(join(wtPath, "ide.yml"))) {
1176
+ await launch(wtPath, { attach: false, sessionName: name });
1177
+ } else {
1178
+ if (!hasSession(name)) createDetachedSession(name, wtPath);
1179
+ const { adoptSession } = await import("../packages/daemon/src/tui/chrome/statusline.ts");
1180
+ adoptSession(name);
1181
+ }
1182
+ }
1183
+
1184
+ function printSwitchHint(name: string, wtPath: string): void {
1185
+ console.log(`Worktree ready: ${wtPath}`);
1186
+ console.log(`Session: ${name}`);
1187
+ if (process.env.TMUX) {
1188
+ console.log(`Switch to it: tmux switch-client -t '${name}'`);
1189
+ } else {
1190
+ console.log(`Attach to it: tmux attach -t '${name}'`);
1191
+ }
1192
+ }
1193
+
1194
+ if (sub === "create") {
1195
+ const branch = positionals[2];
1196
+ if (!branch) {
1197
+ throw new IdeError(
1198
+ "Usage: tmux-ide worktree create <branch> [--from <ref>] [--dir <path>] [--no-session]",
1199
+ { code: "USAGE", exitCode: 1 },
1200
+ );
1201
+ }
1202
+ const { getAppConfig } = await import("../packages/daemon/src/lib/app-config.ts");
1203
+ const dirOverride =
1204
+ typeof values.dir === "string" && values.dir.length > 0
1205
+ ? values.dir
1206
+ : getAppConfig().worktrees.dir || null;
1207
+ const wtPath = worktreePath(repoDir, branch, dirOverride);
1208
+ const from = typeof values.from === "string" ? values.from : null;
1209
+
1210
+ // Default: create a NEW branch off `from` (HEAD when absent). If the
1211
+ // branch already exists and no explicit base was given, fall back to
1212
+ // checking it out into the worktree instead of failing.
1213
+ try {
1214
+ createWorktree(repoDir, branch, wtPath, { newBranch: true, from });
1215
+ } catch (err) {
1216
+ if (err instanceof WorktreeError && err.code === "BRANCH_EXISTS" && !from) {
1217
+ createWorktree(repoDir, branch, wtPath, { newBranch: false });
1218
+ } else {
1219
+ throw err;
1220
+ }
1221
+ }
1222
+
1223
+ const sessionName = worktreeSessionName(projectName, branch);
1224
+ if (!values["no-session"]) {
1225
+ await openWorktreeSession(wtPath, sessionName);
1226
+ }
1227
+
1228
+ if (json) {
1229
+ console.log(
1230
+ JSON.stringify({
1231
+ branch,
1232
+ path: wtPath,
1233
+ session: values["no-session"] ? null : sessionName,
1234
+ }),
1235
+ );
1236
+ } else if (values["no-session"]) {
1237
+ console.log(`Worktree ready: ${wtPath}`);
1238
+ console.log(`Open a session later: tmux-ide worktree open '${branch}'`);
1239
+ } else {
1240
+ printSwitchHint(sessionName, wtPath);
1241
+ }
1242
+ break;
1243
+ }
1244
+
1245
+ if (sub === "open") {
1246
+ const branch = positionals[2];
1247
+ if (!branch) {
1248
+ throw new IdeError("Usage: tmux-ide worktree open <branch>", {
1249
+ code: "USAGE",
1250
+ exitCode: 1,
1251
+ });
1252
+ }
1253
+ const entry = worktrees.find((w) => w.branch === branch);
1254
+ if (!entry) {
1255
+ throw new IdeError(
1256
+ `No worktree for branch "${branch}". Create one with: tmux-ide worktree create '${branch}'`,
1257
+ { code: "USAGE", exitCode: 1 },
1258
+ );
1259
+ }
1260
+ const sessionName = worktreeSessionName(projectName, branch);
1261
+ const already = hasSession(sessionName);
1262
+ if (!already) await openWorktreeSession(entry.path, sessionName);
1263
+ if (json) {
1264
+ console.log(
1265
+ JSON.stringify({ branch, path: entry.path, session: sessionName, created: !already }),
1266
+ );
1267
+ } else {
1268
+ if (already) console.log(`Session already running.`);
1269
+ printSwitchHint(sessionName, entry.path);
1270
+ }
1271
+ break;
1272
+ }
1273
+
1274
+ if (sub === "remove") {
1275
+ const branch = positionals[2];
1276
+ if (!branch) {
1277
+ throw new IdeError("Usage: tmux-ide worktree remove <branch> [--force]", {
1278
+ code: "USAGE",
1279
+ exitCode: 1,
1280
+ });
1281
+ }
1282
+ const entry = worktrees.find((w) => w.branch === branch);
1283
+ if (!entry) {
1284
+ throw new IdeError(`No worktree for branch "${branch}".`, {
1285
+ code: "USAGE",
1286
+ exitCode: 1,
1287
+ });
1288
+ }
1289
+ // Remove the worktree FIRST so a failed removal (e.g. dirty without
1290
+ // --force, which throws here) never orphan-kills the still-usable
1291
+ // session. Only after a clean removal do we kill ONLY this worktree's
1292
+ // own session (never the parent repo's or a user session — the name is
1293
+ // fully derived from the worktree's branch).
1294
+ removeWorktree(repoDir, entry.path, { force: values.force === true });
1295
+ const sessionName = worktreeSessionName(projectName, branch);
1296
+ const killed = hasSession(sessionName) ? killSession(sessionName).stopped : false;
1297
+ if (json) {
1298
+ console.log(
1299
+ JSON.stringify({ branch, path: entry.path, sessionKilled: killed, removed: true }),
1300
+ );
1301
+ } else {
1302
+ console.log(`Removed worktree ${entry.path}${killed ? ` (killed ${sessionName})` : ""}.`);
1303
+ }
1304
+ break;
1305
+ }
1306
+
1307
+ // sub === "list"
1308
+ const { createStatusTracker } = await import("../packages/daemon/src/tui/detect/classify.ts");
1309
+ const { listTeamSessions } = await import("../packages/daemon/src/tui/team/sessions.ts");
1310
+ const sessions = listTeamSessions(createStatusTracker());
1311
+ const rows = worktrees.map((wt) => {
1312
+ const isPrimary = wt.path === mainPath;
1313
+ const candidates: string[] = [];
1314
+ if (isPrimary) candidates.push(projectName);
1315
+ if (wt.branch) candidates.push(worktreeSessionName(projectName, wt.branch));
1316
+ const match = sessions.find((s) => candidates.includes(s.name)) ?? null;
1317
+ return {
1318
+ path: wt.path,
1319
+ branch: wt.branch,
1320
+ primary: isPrimary,
1321
+ session: match?.name ?? null,
1322
+ running: match !== null,
1323
+ status: match?.status ?? null,
1324
+ };
510
1325
  });
1326
+ if (json) {
1327
+ console.log(JSON.stringify({ repo: mainPath, worktrees: rows }, null, 2));
1328
+ } else if (rows.length === 0) {
1329
+ console.log("No worktrees.");
1330
+ } else {
1331
+ for (const r of rows) {
1332
+ const tag = r.primary ? " (primary)" : "";
1333
+ const state = r.running ? `${r.status} · ${r.session}` : "no session";
1334
+ console.log(`${r.branch ?? "(detached)"}${tag} ${state}\n ${r.path}`);
1335
+ }
1336
+ }
1337
+ break;
1338
+ }
1339
+
1340
+ case "update": {
1341
+ // Detect how tmux-ide was installed and act on the pending update: a dev
1342
+ // checkout prints the `git pull` hint; a global install prints (with
1343
+ // --dry-run) or runs its package manager's update command. `__dirname` is
1344
+ // this CLI's own directory — the anchor for the git-checkout probe + the
1345
+ // package-manager path heuristic (see lib/update.ts).
1346
+ const { runUpdate } = await import("../packages/daemon/src/lib/update.ts");
1347
+ const dryRun = values["dry-run"] === true;
1348
+ const plan = runUpdate({ cliDir: __dirname, dryRun });
1349
+ if (!dryRun) {
1350
+ // The managed skill copy has to track the CLI. A global install refreshes
1351
+ // it via the package's own postinstall (which just ran); a dev checkout
1352
+ // has no postinstall, so `tmux-ide update` IS the checkout's refresh path
1353
+ // — sync the skill directly here.
1354
+ const { syncSkill } = await import("../packages/daemon/src/lib/skill-sync.ts");
1355
+ if (plan.method === "dev") {
1356
+ const result = syncSkill();
1357
+ console.log("");
1358
+ console.log(`skill: ${result.action} → ${result.path} (v${result.to})`);
1359
+ } else {
1360
+ console.log("");
1361
+ console.log("skill: refreshed by the package postinstall (~/.claude/skills/tmux-ide)");
1362
+ }
1363
+ }
1364
+ break;
1365
+ }
1366
+
1367
+ case "skill-sync": {
1368
+ // The universal manual refresh of the managed Claude Code skill copy.
1369
+ // Fully-managed dir: overwrite is correct; version-equal is a no-op.
1370
+ const { syncSkill } = await import("../packages/daemon/src/lib/skill-sync.ts");
1371
+ const result = syncSkill();
1372
+ if (json) {
1373
+ console.log(JSON.stringify(result, null, 2));
1374
+ } else {
1375
+ const detail =
1376
+ result.action === "updated" && result.from
1377
+ ? ` (v${result.from} → v${result.to})`
1378
+ : ` (v${result.to})`;
1379
+ console.log(`skill ${result.action}${detail}: ${result.path}`);
1380
+ }
511
1381
  break;
512
1382
  }
513
1383
 
514
1384
  case "command-center": {
515
- const { startCommandCenter } = await import("../src/command-center/index.ts");
1385
+ const { startCommandCenter } = await import("../packages/daemon/src/command-center/index.ts");
516
1386
  await startCommandCenter({ port: parseInt(values.port ?? "4000") });
517
1387
  break;
518
1388
  }
519
1389
 
1390
+ case "server": {
1391
+ if ("bun" in process.versions) {
1392
+ const scriptPath = resolve(__dirname, "../packages/daemon/src/server/standalone.ts");
1393
+ const serverArgs = ["--experimental-strip-types", scriptPath];
1394
+ if (values.port) serverArgs.push("--port", values.port);
1395
+ execFileSync("node", serverArgs, { stdio: "inherit" });
1396
+ } else {
1397
+ const { start } = await import("../packages/daemon/src/server/index.ts");
1398
+ await start(values.port ? parseInt(values.port, 10) : undefined);
1399
+ }
1400
+ break;
1401
+ }
1402
+
520
1403
  case "help":
521
1404
  printHelp();
522
1405
  break;