@interactive-inc/claude-funnel 0.4.1 → 0.8.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 (349) hide show
  1. package/README.md +233 -111
  2. package/dist/bin.js +1417 -0
  3. package/dist/gateway/daemon.js +513 -0
  4. package/dist/highlights-eq9cgrbb.scm +604 -0
  5. package/dist/highlights-ghv9g403.scm +205 -0
  6. package/dist/highlights-hk7bwhj4.scm +284 -0
  7. package/dist/highlights-r812a2qc.scm +150 -0
  8. package/dist/highlights-x6tmsnaa.scm +115 -0
  9. package/dist/injections-73j83es3.scm +27 -0
  10. package/dist/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
  11. package/dist/tree-sitter-markdown-411r6y9b.wasm +0 -0
  12. package/dist/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
  13. package/dist/tree-sitter-typescript-zxjzwt75.wasm +0 -0
  14. package/dist/tree-sitter-zig-e78zbjpm.wasm +0 -0
  15. package/lib/bin.ts +78 -0
  16. package/lib/{modules → cli}/router/to-request.ts +13 -20
  17. package/lib/cli/routes/channels.$channel.connectors.$connector.rename.$newName.ts +27 -0
  18. package/lib/cli/routes/channels.$channel.connectors.$connector.request.ts +40 -0
  19. package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.add.$id.ts +41 -0
  20. package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.remove.$id.ts +22 -0
  21. package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.ts +23 -0
  22. package/lib/cli/routes/channels.$channel.connectors.$connector.ts +26 -0
  23. package/lib/cli/routes/channels.$channel.connectors.add.$connector.ts +92 -0
  24. package/lib/cli/routes/channels.$channel.connectors.remove.$connector.ts +22 -0
  25. package/lib/cli/routes/channels.$channel.connectors.set.$connector.ts +63 -0
  26. package/lib/cli/routes/channels.$channel.connectors.ts +26 -0
  27. package/lib/cli/routes/channels.$channel.rename.$newName.ts +22 -0
  28. package/lib/cli/routes/channels.$channel.set.delivery.$mode.ts +34 -0
  29. package/lib/cli/routes/channels.$channel.ts +34 -0
  30. package/lib/cli/routes/channels.add.$channel.ts +33 -0
  31. package/lib/cli/routes/channels.remove.$channel.ts +20 -0
  32. package/lib/cli/routes/channels.ts +39 -0
  33. package/lib/cli/routes/claude.ts +69 -0
  34. package/lib/cli/routes/gateway.listeners.ts +41 -0
  35. package/lib/cli/routes/gateway.logs.ts +123 -0
  36. package/lib/{routes/gateway/restart.ts → cli/routes/gateway.restart.ts} +20 -5
  37. package/lib/cli/routes/gateway.run.ts +41 -0
  38. package/lib/cli/routes/gateway.start.ts +50 -0
  39. package/lib/cli/routes/gateway.status.ts +19 -0
  40. package/lib/cli/routes/gateway.stop.ts +32 -0
  41. package/lib/cli/routes/gateway.ts +55 -0
  42. package/lib/cli/routes/index.ts +202 -0
  43. package/lib/cli/routes/profiles.$profile.as-default.ts +22 -0
  44. package/lib/cli/routes/profiles.$profile.rename.$newName.ts +22 -0
  45. package/lib/cli/routes/profiles.$profile.run.ts +36 -0
  46. package/lib/cli/routes/profiles.add.$profile.ts +46 -0
  47. package/lib/cli/routes/profiles.remove.$profile.ts +20 -0
  48. package/lib/cli/routes/profiles.set.$profile.ts +46 -0
  49. package/lib/cli/routes/profiles.ts +40 -0
  50. package/lib/cli/routes/status.ts +93 -0
  51. package/lib/cli/routes/update.ts +27 -0
  52. package/lib/connectors/connector-config-schema.ts +16 -0
  53. package/lib/connectors/connector-factory.ts +94 -0
  54. package/lib/connectors/connector-listener.ts +20 -0
  55. package/lib/{modules/connectors/funnel-discord-adapter.ts → connectors/discord-adapter.ts} +6 -11
  56. package/lib/{modules/connectors → connectors}/discord-connector-schema.ts +4 -1
  57. package/lib/connectors/discord-listener.ts +111 -0
  58. package/lib/{modules/connectors/funnel-gh-adapter.ts → connectors/gh-adapter.ts} +3 -6
  59. package/lib/{modules/connectors → connectors}/gh-connector-schema.ts +4 -1
  60. package/lib/{modules/connectors/funnel-gh-listener.ts → connectors/gh-listener.ts} +57 -22
  61. package/lib/{modules/connectors → connectors}/match-cron.ts +10 -4
  62. package/lib/connectors/schedule-connector-schema.ts +33 -0
  63. package/lib/connectors/schedule-listener.ts +207 -0
  64. package/lib/connectors/schedule-state-store.ts +54 -0
  65. package/lib/connectors/slack-adapter.ts +36 -0
  66. package/lib/{modules/connectors → connectors}/slack-connector-schema.ts +4 -1
  67. package/lib/{modules/connectors/funnel-slack-event-processor.ts → connectors/slack-event-processor.ts} +15 -9
  68. package/lib/{modules/connectors/funnel-slack-listener.ts → connectors/slack-listener.ts} +39 -14
  69. package/lib/engine/channels/channels.ts +520 -0
  70. package/lib/{modules/claude/funnel-claude.ts → engine/claude/claude.ts} +47 -62
  71. package/lib/engine/claude/gateway-controller.ts +4 -0
  72. package/lib/{modules/fs/funnel-file-system.ts → engine/fs/file-system.ts} +9 -0
  73. package/lib/{modules/fs/memory-funnel-file-system.ts → engine/fs/memory-file-system.ts} +20 -3
  74. package/lib/{modules/fs/node-funnel-file-system.ts → engine/fs/node-file-system.ts} +14 -2
  75. package/lib/{modules/http/memory-funnel-http-client.ts → engine/http/memory-http-client.ts} +1 -5
  76. package/lib/{modules/http/node-funnel-http-client.ts → engine/http/node-http-client.ts} +1 -5
  77. package/lib/engine/id/id-generator.ts +7 -0
  78. package/lib/engine/id/memory-id-generator.ts +20 -0
  79. package/lib/engine/id/node-id-generator.ts +7 -0
  80. package/lib/engine/logger/logger.ts +11 -0
  81. package/lib/engine/logger/memory-logger.ts +28 -0
  82. package/lib/engine/logger/node-logger.ts +49 -0
  83. package/lib/engine/logger/noop-logger.ts +9 -0
  84. package/lib/engine/mcp/channel-server.ts +204 -0
  85. package/lib/{modules/mcp/funnel-mcp.ts → engine/mcp/mcp.ts} +29 -10
  86. package/lib/{modules/process/memory-funnel-process-runner.ts → engine/process/memory-process-runner.ts} +1 -1
  87. package/lib/{modules/process/node-funnel-process-runner.ts → engine/process/node-process-runner.ts} +12 -21
  88. package/lib/{modules/process/funnel-process-runner.ts → engine/process/process-runner.ts} +5 -0
  89. package/lib/engine/profiles/profile-channel-checker.ts +7 -0
  90. package/lib/engine/profiles/profiles.ts +126 -0
  91. package/lib/{modules/settings/mock-funnel-settings-reader.ts → engine/settings/mock-settings-reader.ts} +4 -3
  92. package/lib/{modules/settings/funnel-settings-reader.ts → engine/settings/settings-reader.ts} +1 -1
  93. package/lib/engine/settings/settings-schema.ts +46 -0
  94. package/lib/engine/settings/settings-store.ts +110 -0
  95. package/lib/engine/time/clock.ts +15 -0
  96. package/lib/engine/time/memory-clock.ts +26 -0
  97. package/lib/engine/time/node-clock.ts +7 -0
  98. package/lib/funnel.ts +148 -56
  99. package/lib/gateway/auth-middleware.ts +44 -0
  100. package/lib/gateway/broadcaster.ts +319 -0
  101. package/lib/gateway/daemon.ts +47 -0
  102. package/lib/gateway/factory.ts +10 -0
  103. package/lib/gateway/funnel-event-store.ts +155 -0
  104. package/lib/gateway/gateway-server.ts +414 -0
  105. package/lib/gateway/gateway-token.ts +79 -0
  106. package/lib/{modules/gateway/funnel-gateway.ts → gateway/gateway.ts} +70 -27
  107. package/lib/{modules/gateway → gateway}/kill-competing-slack-gateways.ts +7 -3
  108. package/lib/gateway/listener-supervisor.ts +339 -0
  109. package/lib/gateway/listeners-client.ts +128 -0
  110. package/lib/gateway/resolve-daemon-script.ts +26 -0
  111. package/lib/gateway/routes/channels.connectors.call.ts +39 -0
  112. package/lib/gateway/routes/health.ts +13 -0
  113. package/lib/gateway/routes/index.ts +24 -0
  114. package/lib/gateway/routes/listeners.list.ts +6 -0
  115. package/lib/gateway/routes/listeners.restart.ts +15 -0
  116. package/lib/gateway/routes/listeners.start.ts +15 -0
  117. package/lib/gateway/routes/listeners.stop.ts +15 -0
  118. package/lib/gateway/routes/route-deps.ts +11 -0
  119. package/lib/gateway/routes/status.ts +15 -0
  120. package/lib/gateway/routes/validator.ts +17 -0
  121. package/lib/index.ts +50 -92
  122. package/lib/logger/leuco-human-file-writer.ts +65 -0
  123. package/lib/logger/leuco-human-logger.ts +98 -0
  124. package/lib/logger/leuco-human-record.ts +16 -0
  125. package/lib/logger/leuco-human-stdout-writer.ts +26 -0
  126. package/lib/logger/leuco-human-writer.ts +14 -0
  127. package/lib/logger/leuco-logger-memory-sink.ts +67 -0
  128. package/lib/logger/leuco-logger-record.ts +13 -0
  129. package/lib/logger/leuco-logger-sink.ts +33 -0
  130. package/lib/logger/leuco-logger-sqlite-sink.ts +355 -0
  131. package/lib/logger/leuco-logger.ts +135 -0
  132. package/lib/tui/app.tsx +357 -0
  133. package/lib/tui/components/add-row.tsx +18 -0
  134. package/lib/tui/components/brand.tsx +27 -0
  135. package/lib/tui/components/card.tsx +44 -0
  136. package/lib/tui/components/detail-bar.tsx +46 -0
  137. package/lib/tui/components/editable-field.tsx +33 -0
  138. package/lib/tui/components/empty-state.tsx +11 -0
  139. package/lib/tui/components/gateway-status.tsx +66 -0
  140. package/lib/tui/components/keymap.tsx +29 -0
  141. package/lib/tui/components/menu-item.tsx +73 -0
  142. package/lib/tui/components/menu.tsx +26 -0
  143. package/lib/tui/components/panel-header.tsx +22 -0
  144. package/lib/tui/components/readonly-field.tsx +18 -0
  145. package/lib/tui/components/section-header.tsx +25 -0
  146. package/lib/tui/components/selection-accent.tsx +32 -0
  147. package/lib/tui/components/session-item.tsx +33 -0
  148. package/lib/tui/components/session-list.tsx +33 -0
  149. package/lib/tui/components/ui/hascii/accordion-item.tsx +88 -0
  150. package/lib/tui/components/ui/hascii/accordion.tsx +96 -0
  151. package/lib/tui/components/ui/hascii/alert-dialog.tsx +43 -0
  152. package/lib/tui/components/ui/hascii/badge.tsx +51 -0
  153. package/lib/tui/components/ui/hascii/breadcrumb.tsx +58 -0
  154. package/lib/tui/components/ui/hascii/button.tsx +194 -0
  155. package/lib/tui/components/ui/hascii/card-content.tsx +14 -0
  156. package/lib/tui/components/ui/hascii/card-description.tsx +13 -0
  157. package/lib/tui/components/ui/hascii/card-footer.tsx +14 -0
  158. package/lib/tui/components/ui/hascii/card-header.tsx +14 -0
  159. package/lib/tui/components/ui/hascii/card-title.tsx +13 -0
  160. package/lib/tui/components/ui/hascii/card.tsx +27 -0
  161. package/lib/tui/components/ui/hascii/checkbox.tsx +65 -0
  162. package/lib/tui/components/ui/hascii/command.tsx +159 -0
  163. package/lib/tui/components/ui/hascii/dialog-content.tsx +14 -0
  164. package/lib/tui/components/ui/hascii/dialog-description.tsx +13 -0
  165. package/lib/tui/components/ui/hascii/dialog-footer.tsx +14 -0
  166. package/lib/tui/components/ui/hascii/dialog-header.tsx +14 -0
  167. package/lib/tui/components/ui/hascii/dialog-title.tsx +13 -0
  168. package/lib/tui/components/ui/hascii/dialog.tsx +27 -0
  169. package/lib/tui/components/ui/hascii/file-tree.tsx +142 -0
  170. package/lib/tui/components/ui/hascii/focus-group.tsx +62 -0
  171. package/lib/tui/components/ui/hascii/form-item.tsx +43 -0
  172. package/lib/tui/components/ui/hascii/input-otp.tsx +86 -0
  173. package/lib/tui/components/ui/hascii/input.tsx +130 -0
  174. package/lib/tui/components/ui/hascii/pagination.tsx +105 -0
  175. package/lib/tui/components/ui/hascii/progress.tsx +28 -0
  176. package/lib/tui/components/ui/hascii/select.tsx +131 -0
  177. package/lib/tui/components/ui/hascii/separator.tsx +35 -0
  178. package/lib/tui/components/ui/hascii/sidebar-content.tsx +23 -0
  179. package/lib/tui/components/ui/hascii/sidebar-header.tsx +14 -0
  180. package/lib/tui/components/ui/hascii/sidebar-menu-item.tsx +67 -0
  181. package/lib/tui/components/ui/hascii/sidebar.tsx +24 -0
  182. package/lib/tui/components/ui/hascii/skeleton.tsx +60 -0
  183. package/lib/tui/components/ui/hascii/slider.tsx +91 -0
  184. package/lib/tui/components/ui/hascii/snackbar.tsx +75 -0
  185. package/lib/tui/components/ui/hascii/sparkline.tsx +53 -0
  186. package/lib/tui/components/ui/hascii/spinner.tsx +47 -0
  187. package/lib/tui/components/ui/hascii/stepper.tsx +54 -0
  188. package/lib/tui/components/ui/hascii/switch.tsx +66 -0
  189. package/lib/tui/components/ui/hascii/table.tsx +95 -0
  190. package/lib/tui/components/ui/hascii/tabs.tsx +59 -0
  191. package/lib/tui/components/ui/hascii/toggle-group-item.tsx +45 -0
  192. package/lib/tui/components/ui/hascii/toggle-group.tsx +99 -0
  193. package/lib/tui/components/ui/hascii/tree.tsx +104 -0
  194. package/lib/tui/components/view-shell.tsx +44 -0
  195. package/lib/tui/filter-input.tsx +33 -0
  196. package/lib/tui/hooks/hascii/use-pressable.ts +54 -0
  197. package/lib/tui/parse-comma-list.ts +14 -0
  198. package/lib/tui/profile-launcher.tsx +61 -0
  199. package/lib/tui/scrollbar-options.ts +19 -0
  200. package/lib/tui/sidebar.tsx +50 -0
  201. package/lib/tui/theme.ts +40 -0
  202. package/lib/tui/tui.tsx +20 -0
  203. package/lib/tui/types.ts +38 -0
  204. package/lib/tui/unique-name.ts +18 -0
  205. package/lib/tui/use-event-stream.ts +133 -0
  206. package/lib/tui/use-snapshot.ts +99 -0
  207. package/lib/tui/utils/hascii/form-item-context.tsx +23 -0
  208. package/lib/tui/utils/hascii/input-focus-context.tsx +31 -0
  209. package/lib/tui/utils/hascii/theme-context.tsx +26 -0
  210. package/lib/tui/utils/hascii/theme.ts +176 -0
  211. package/lib/tui/views/channels-view.tsx +108 -0
  212. package/lib/tui/views/connectors-view.tsx +164 -0
  213. package/lib/tui/views/events-view.tsx +160 -0
  214. package/lib/tui/views/listeners-view.tsx +80 -0
  215. package/lib/tui/views/profiles-view.tsx +152 -0
  216. package/package.json +51 -34
  217. package/lib/modules/channels/channel-connector-ref-updater.ts +0 -4
  218. package/lib/modules/channels/funnel-channels.ts +0 -155
  219. package/lib/modules/connectors/connector-config-schema.ts +0 -16
  220. package/lib/modules/connectors/connector-existence-checker.ts +0 -3
  221. package/lib/modules/connectors/funnel-callable-connector-store.ts +0 -9
  222. package/lib/modules/connectors/funnel-connector-listener.ts +0 -5
  223. package/lib/modules/connectors/funnel-connector-stores.ts +0 -24
  224. package/lib/modules/connectors/funnel-connector-type-store.ts +0 -24
  225. package/lib/modules/connectors/funnel-connectors.ts +0 -145
  226. package/lib/modules/connectors/funnel-discord-listener.ts +0 -65
  227. package/lib/modules/connectors/funnel-discord-store.ts +0 -84
  228. package/lib/modules/connectors/funnel-gh-store.ts +0 -84
  229. package/lib/modules/connectors/funnel-json-connector-store.ts +0 -100
  230. package/lib/modules/connectors/funnel-schedule-listener.ts +0 -124
  231. package/lib/modules/connectors/funnel-schedule-store.ts +0 -178
  232. package/lib/modules/connectors/funnel-slack-adapter.ts +0 -31
  233. package/lib/modules/connectors/funnel-slack-store.ts +0 -86
  234. package/lib/modules/connectors/migrate-legacy-connectors.ts +0 -77
  235. package/lib/modules/connectors/schedule-connector-schema.ts +0 -18
  236. package/lib/modules/connectors/schedule-last-fired-store.ts +0 -48
  237. package/lib/modules/gateway/daemon.ts +0 -207
  238. package/lib/modules/gateway/funnel-broadcaster.ts +0 -37
  239. package/lib/modules/gateway/funnel-event-logger.ts +0 -59
  240. package/lib/modules/logger.ts +0 -26
  241. package/lib/modules/mcp/channel-server.ts +0 -76
  242. package/lib/modules/profiles/funnel-profiles.ts +0 -123
  243. package/lib/modules/profiles/profile-channel-checker.ts +0 -3
  244. package/lib/modules/profiles/profile-channel-ref-updater.ts +0 -3
  245. package/lib/modules/repos/funnel-repositories.ts +0 -107
  246. package/lib/modules/schedule/funnel-schedule.ts +0 -34
  247. package/lib/modules/settings/funnel-settings-store.ts +0 -56
  248. package/lib/modules/settings/settings-schema.ts +0 -33
  249. package/lib/modules/tui/app.tsx +0 -44
  250. package/lib/modules/tui/tui.tsx +0 -13
  251. package/lib/routes/channels/add.help.ts +0 -3
  252. package/lib/routes/channels/add.ts +0 -21
  253. package/lib/routes/channels/connectors-attach.help.ts +0 -3
  254. package/lib/routes/channels/connectors-attach.ts +0 -17
  255. package/lib/routes/channels/connectors-detach.help.ts +0 -3
  256. package/lib/routes/channels/connectors-detach.ts +0 -17
  257. package/lib/routes/channels/group.help.ts +0 -16
  258. package/lib/routes/channels/group.ts +0 -22
  259. package/lib/routes/channels/remove.help.ts +0 -3
  260. package/lib/routes/channels/remove.ts +0 -17
  261. package/lib/routes/channels/rename.help.ts +0 -5
  262. package/lib/routes/channels/rename.ts +0 -17
  263. package/lib/routes/channels/routes.ts +0 -19
  264. package/lib/routes/channels/show.help.ts +0 -1
  265. package/lib/routes/channels/show.ts +0 -26
  266. package/lib/routes/claude/claude.help.ts +0 -16
  267. package/lib/routes/claude/claude.ts +0 -76
  268. package/lib/routes/claude/routes.ts +0 -4
  269. package/lib/routes/connectors/add.help.ts +0 -28
  270. package/lib/routes/connectors/add.ts +0 -64
  271. package/lib/routes/connectors/group.help.ts +0 -14
  272. package/lib/routes/connectors/group.ts +0 -18
  273. package/lib/routes/connectors/remove.help.ts +0 -3
  274. package/lib/routes/connectors/remove.ts +0 -17
  275. package/lib/routes/connectors/rename.help.ts +0 -5
  276. package/lib/routes/connectors/rename.ts +0 -17
  277. package/lib/routes/connectors/routes.ts +0 -23
  278. package/lib/routes/connectors/schedules-add.help.ts +0 -11
  279. package/lib/routes/connectors/schedules-add.ts +0 -33
  280. package/lib/routes/connectors/schedules-group.help.ts +0 -1
  281. package/lib/routes/connectors/schedules-group.ts +0 -38
  282. package/lib/routes/connectors/schedules-remove.help.ts +0 -3
  283. package/lib/routes/connectors/schedules-remove.ts +0 -17
  284. package/lib/routes/connectors/set.help.ts +0 -8
  285. package/lib/routes/connectors/set.ts +0 -72
  286. package/lib/routes/connectors/show.help.ts +0 -1
  287. package/lib/routes/connectors/show.ts +0 -41
  288. package/lib/routes/gateway/group.help.ts +0 -15
  289. package/lib/routes/gateway/group.ts +0 -28
  290. package/lib/routes/gateway/logs.help.ts +0 -13
  291. package/lib/routes/gateway/logs.ts +0 -100
  292. package/lib/routes/gateway/restart.help.ts +0 -10
  293. package/lib/routes/gateway/routes.ts +0 -18
  294. package/lib/routes/gateway/run.help.ts +0 -12
  295. package/lib/routes/gateway/run.ts +0 -35
  296. package/lib/routes/gateway/start.help.ts +0 -15
  297. package/lib/routes/gateway/start.ts +0 -32
  298. package/lib/routes/gateway/status.help.ts +0 -9
  299. package/lib/routes/gateway/status.ts +0 -28
  300. package/lib/routes/gateway/stop.help.ts +0 -8
  301. package/lib/routes/gateway/stop.ts +0 -21
  302. package/lib/routes/profiles/add.help.ts +0 -3
  303. package/lib/routes/profiles/add.ts +0 -33
  304. package/lib/routes/profiles/group.help.ts +0 -16
  305. package/lib/routes/profiles/group.ts +0 -25
  306. package/lib/routes/profiles/launch.help.ts +0 -4
  307. package/lib/routes/profiles/launch.ts +0 -36
  308. package/lib/routes/profiles/remove.help.ts +0 -3
  309. package/lib/routes/profiles/remove.ts +0 -17
  310. package/lib/routes/profiles/rename.help.ts +0 -5
  311. package/lib/routes/profiles/rename.ts +0 -17
  312. package/lib/routes/profiles/routes.ts +0 -18
  313. package/lib/routes/profiles/set.help.ts +0 -5
  314. package/lib/routes/profiles/set.ts +0 -32
  315. package/lib/routes/repos/add.help.ts +0 -6
  316. package/lib/routes/repos/add.ts +0 -20
  317. package/lib/routes/repos/group.help.ts +0 -11
  318. package/lib/routes/repos/group.ts +0 -18
  319. package/lib/routes/repos/remove.help.ts +0 -3
  320. package/lib/routes/repos/remove.ts +0 -17
  321. package/lib/routes/repos/rename.help.ts +0 -5
  322. package/lib/routes/repos/rename.ts +0 -17
  323. package/lib/routes/repos/routes.ts +0 -17
  324. package/lib/routes/repos/set.help.ts +0 -5
  325. package/lib/routes/repos/set.ts +0 -21
  326. package/lib/routes/repos/show.help.ts +0 -1
  327. package/lib/routes/repos/show.ts +0 -19
  328. package/lib/routes/request/discord-help.ts +0 -9
  329. package/lib/routes/request/discord.help.ts +0 -19
  330. package/lib/routes/request/discord.ts +0 -65
  331. package/lib/routes/request/group.help.ts +0 -15
  332. package/lib/routes/request/group.ts +0 -9
  333. package/lib/routes/request/routes.ts +0 -14
  334. package/lib/routes/request/slack-help.ts +0 -9
  335. package/lib/routes/request/slack.help.ts +0 -19
  336. package/lib/routes/request/slack.ts +0 -61
  337. package/lib/routes/status/routes.ts +0 -4
  338. package/lib/routes/status/status.help.ts +0 -6
  339. package/lib/routes/status/status.ts +0 -77
  340. package/lib/routes/update/routes.ts +0 -4
  341. package/lib/routes/update/update.help.ts +0 -5
  342. package/lib/routes/update/update.ts +0 -21
  343. package/lib/routes.ts +0 -40
  344. /package/lib/{factory.ts → cli/factory.ts} +0 -0
  345. /package/lib/{modules → cli}/router/query-to-cli-args.ts +0 -0
  346. /package/lib/{modules → cli}/router/validator.ts +0 -0
  347. /package/lib/{modules/connectors/funnel-connector-adapter.ts → connectors/connector-adapter.ts} +0 -0
  348. /package/lib/{modules/connectors/funnel-discord-event-processor.ts → connectors/discord-event-processor.ts} +0 -0
  349. /package/lib/{modules/http/funnel-http-client.ts → engine/http/http-client.ts} +0 -0
package/README.md CHANGED
@@ -1,39 +1,33 @@
1
- # @interactive-inc/claude-funnel
2
-
3
1
  [![npm](https://img.shields.io/npm/v/@interactive-inc/claude-funnel.svg)](https://www.npmjs.com/package/@interactive-inc/claude-funnel)
4
2
  [![license](https://img.shields.io/npm/l/@interactive-inc/claude-funnel.svg)](./LICENSE)
5
3
 
6
- A hub CLI that connects multiple Claude Code agents to external services (Slack / GitHub / Discord) and time-based triggers (cron). External events flow through subscription "channels" into Claude Code sessions, and outbound API calls from Claude are funneled through the same connectors.
4
+ A hub CLI that connects multiple Claude Code agents to external services (Slack / GitHub / Discord) and time-based triggers (cron). External events flow through subscription "channels" into Claude Code sessions, and outbound API calls from Claude are funneled through the same connectors as MCP tools.
7
5
 
8
6
  The command is `funnel` or its shorthand `fnl`.
9
7
 
10
8
  ## Overview
11
9
 
12
10
  ```
13
- External sources
14
- (Slack / GitHub / Discord / cron)
15
-
16
-
17
- Connectors
18
- (per-type stores)
19
-
20
-
21
- Channels
22
- (subscription router)
23
-
24
- ▼ WebSocket
25
- Gateway daemon
26
-
27
- ▼ MCP (stdio)
28
- Claude Code
29
- (events surfaced as <channel> tags;
30
- outbound calls go back through the
31
- same connectors via funnel MCP)
11
+ External sources Outbound calls
12
+ (Slack / GitHub / Discord / cron) (Claude → MCP tools per connector)
13
+
14
+
15
+ Channels (with nested per-type connectors)
16
+
17
+ ▼ WebSocket
18
+ Gateway daemon
19
+ (port 9742: WS /ws + listener supervisor + reply API)
20
+
21
+ ▼ MCP (stdio)
22
+ Claude Code
23
+ (events arrive as <channel> notifications;
24
+ one MCP tool is exposed per configured connector
25
+ so Claude can reply / send / call APIs without bash)
32
26
  ```
33
27
 
34
28
  ## Requirements
35
29
 
36
- - [Bun](https://bun.sh) 1.3 or later (runtime)
30
+ - [Bun](https://bun.sh) 1.3 or later (runtime — used at install time to build the CLI bundle and at runtime to execute it)
37
31
  - [Claude Code](https://docs.claude.com/en/docs/claude-code) CLI
38
32
  - A Slack / GitHub / Discord token or CLI, depending on which connectors you use
39
33
 
@@ -43,123 +37,248 @@ External sources
43
37
  bun add -g @interactive-inc/claude-funnel
44
38
  ```
45
39
 
46
- After install, `funnel` and `fnl` are available globally.
40
+ `postinstall` runs `bun run build` to produce a single bundled CLI at `dist/bin.js`. After install, `funnel` and `fnl` are available globally.
47
41
 
48
42
  ## Quick start
49
43
 
50
44
  ```bash
51
- # Register an external connection (Connector)
52
- fnl connectors add my-slack --type slack --bot-token xoxb-... --app-token xapp-...
53
-
54
- # Create a subscription box (Channel) and attach the connector
55
- fnl channels add my-inbox
56
- fnl channels my-inbox connectors attach my-slack
45
+ # Create a subscription box (channel) and attach a connector
46
+ fnl channels add ops
47
+ fnl channels ops connectors add my-slack --type=slack \
48
+ --bot-token=xoxb-... --app-token=xapp-...
57
49
 
58
- # Start the gateway (connects to Slack Socket Mode)
50
+ # Start the gateway (connects to Slack Socket Mode and surfaces events)
59
51
  fnl gateway start
60
52
 
61
- # Launch Claude (funnel is auto-registered in the current directory's .mcp.json)
62
- fnl claude --channel my-inbox
53
+ # Launch Claude with a raw channel binding (no profile required)
54
+ fnl claude --channel ops
55
+
56
+ # Or save it as a profile and launch by name
57
+ fnl profiles add cto --path=/repo/myapp --sub-agent=cto --channel=ops
58
+ fnl claude --profile cto
63
59
  ```
64
60
 
65
61
  Schedule (cron) trigger:
66
62
 
67
63
  ```bash
68
- # Register a schedule connector and a cron entry
69
- fnl connectors add daily --type schedule
70
- fnl connectors daily schedules add --cron "0 9 * * *" --prompt "morning standup"
71
-
72
- # Attach it to a channel just like any other connector
73
- fnl channels my-inbox connectors attach daily
74
- ```
75
-
76
- ## Commands
77
-
64
+ # A schedule connector contains many cron entries
65
+ fnl channels ops connectors add daily --type=schedule
66
+ fnl channels ops connectors daily schedules add morning \
67
+ --cron="0 9 * * *" --prompt="morning standup"
78
68
  ```
79
- fnl connectors list
80
- fnl connectors add <name> --type slack --bot-token xoxb-... --app-token xapp-...
81
- fnl connectors add <name> --type gh [--poll-interval <sec>]
82
- fnl connectors add <name> --type discord --bot-token <token>
83
- fnl connectors add <name> --type schedule
84
- fnl connectors <name> show details
85
- fnl connectors <name> set [--bot-token ...] [--app-token ...] [--poll-interval ...]
86
- fnl connectors rename <old> <new>
87
- fnl connectors remove <name>
88
69
 
89
- fnl connectors <name> schedules list cron entries
90
- fnl connectors <name> schedules add --cron "<expr>" --prompt "<text>" [--disabled]
91
- fnl connectors <name> schedules remove <id>
70
+ ## CLI surface
92
71
 
93
- fnl request slack post <path> [body] --connector <name> call Slack Web API
94
- fnl request discord <method> <path> [body] --connector <name> call Discord REST API
72
+ Connectors live nested inside their owning channel. Every CLI verb (`add` / `set` / `remove` / `rename` / `as-default` / `request`) maps to `POST` plus the verb in the URL — there is no method-stripping, so the same word stays visible in both shell and HTTP form. Read paths (no verb) stay `GET`.
95
73
 
96
- fnl channels list
97
- fnl channels add <name>
98
- fnl channels <name> show details
99
- fnl channels <name> connectors attach <connector>
100
- fnl channels <name> connectors detach <connector>
101
- fnl channels rename <old> <new>
74
+ ```text
75
+ fnl channels list
76
+ fnl channels add <name> [--delivery=fanout|exclusive]
77
+ fnl channels <name> show details
102
78
  fnl channels remove <name>
103
-
104
- fnl profiles list launch profiles
105
- fnl profiles add <name> --channel <c> [--repo <r>] [--sub-agent <s>] [--env-file <f>]
106
- fnl profiles <name> run launch (sugar for fnl claude)
107
- fnl profiles <name> launch (alias for run)
108
- fnl profiles <name> set [--channel ...] [--repo ...] [--sub-agent ...] [--env-file ...]
79
+ fnl channels rename <old> <new> (also `fnl channels <old> rename <new>`)
80
+ fnl channels <name> set delivery <mode>
81
+
82
+ fnl channels <ch> connectors list
83
+ fnl channels <ch> connectors add <c> --type=slack --bot-token=xoxb-... --app-token=xapp-...
84
+ fnl channels <ch> connectors add <c> --type=gh [--poll-interval=<sec>]
85
+ fnl channels <ch> connectors add <c> --type=discord --bot-token=<token>
86
+ fnl channels <ch> connectors add <c> --type=schedule
87
+ fnl channels <ch> connectors <c> show config
88
+ fnl channels <ch> connectors set <c> [--bot-token=...] [--app-token=...] [--poll-interval=...]
89
+ fnl channels <ch> connectors remove <c>
90
+ fnl channels <ch> connectors rename <c> <new>
91
+ fnl channels <ch> connectors <c> request --method=<api.method> [--key=value ...]
92
+
93
+ fnl channels <ch> connectors <c> schedules list cron entries
94
+ fnl channels <ch> connectors <c> schedules add <id> --cron="<expr>" --prompt="<text>" \
95
+ [--enabled=true] [--catchup-policy=latest|all|skip]
96
+ fnl channels <ch> connectors <c> schedules remove <id>
97
+
98
+ fnl profiles list (first entry is the default)
99
+ fnl profiles add <name> --path=<dir> --sub-agent=<agent> --channel=<channel-name>
100
+ fnl profiles <name> launch (alias for `<name> run`)
101
+ fnl profiles <name> run launch (sugar for `fnl claude --profile <name>`)
102
+ fnl profiles <name> set [--path=...] [--sub-agent=...] [--channel=...]
103
+ fnl profiles <name> as-default move to the front of the list
109
104
  fnl profiles rename <old> <new>
110
105
  fnl profiles remove <name>
111
106
 
112
- fnl repos list repositories (extra)
113
- fnl repos add <name> [--path <path>] register funnel MCP (path defaults to cwd)
114
- fnl repos <name> show details
115
- fnl repos <name> set [--path <path>]
116
- fnl repos rename <old> <new>
117
- fnl repos remove <name>
107
+ fnl claude launch the default profile
108
+ fnl claude --profile <name> launch a named profile
109
+ fnl claude --channel <name> raw launch (no profile, cwd = current dir)
110
+ fnl mcp run as an MCP server (invoked from .mcp.json)
118
111
 
119
- fnl claude launch the "default" profile
120
- fnl claude --profile <name> launch a named profile
121
- fnl claude --channel <c> [--repo <r>] [--sub-agent <s>] [--env-file <f>]
122
- raw launch (no profile)
123
- fnl mcp run as an MCP server (invoked from .mcp.json)
112
+ fnl gateway status (default subcommand)
113
+ fnl gateway {start|stop|restart} daemon lifecycle
114
+ fnl gateway run foreground daemon (developer mode)
115
+ fnl gateway logs [-n <N>] tail diagnostic log
116
+ fnl gateway listeners live registry (alive / dead)
124
117
 
125
- fnl gateway running status
126
- fnl gateway start / stop / restart / run / logs
127
- fnl update update funnel via bun i -g
128
- fnl status overall status (connectors / channels / profiles / repos / gateway)
118
+ fnl status overall status (channels / profiles / gateway / clients)
119
+ fnl update `bun i -g @interactive-inc/claude-funnel`
120
+ fnl (no args) launch the OpenTUI dashboard
129
121
 
130
122
  fnl --version
131
- fnl --help (every subcommand has --help)
123
+ fnl --help every subcommand has --help; verb-without-arg also returns help
124
+ ```
125
+
126
+ `--channel` accepts the channel **name** (not the uuid). The CLI resolves it to a channel id before calling the engine.
127
+
128
+ ## Reply path: MCP tools per connector
129
+
130
+ When `fnl claude` launches Claude Code, the funnel MCP server connects to the gateway and reads the channel's connectors from `~/.funnel/settings.json`. For every callable connector (`slack` / `discord` / `gh`; `schedule` is one-way and skipped), the MCP advertises one tool with the connector's name. Claude can call them like:
131
+
132
+ ```jsonc
133
+ // MCP: tools/list returns
134
+ { "name": "discord", "inputSchema": { ... { method, path, body } ... } }
135
+ { "name": "ops-slack", "inputSchema": { ... } }
136
+ { "name": "gh-main", "inputSchema": { ... } }
137
+
138
+ // Claude calls
139
+ tools/call name="discord" arguments={
140
+ "method": "POST",
141
+ "path": "/channels/123/messages",
142
+ "body": { "content": "got it" }
143
+ }
132
144
  ```
133
145
 
146
+ The MCP forwards via HTTP `POST /channels/<channel>/connectors/<connector>/call` to the gateway daemon, which dispatches through the existing `FunnelChannels.call()` adapter. No bash subshell, no CLI cold start — replies are essentially synchronous.
147
+
148
+ If you need to invoke a connector from outside Claude, the same path is reachable as `fnl channels <ch> connectors <c> request --method=<...> [--key=value ...]`.
149
+
134
150
  ## Data model
135
151
 
136
152
  ```
137
- Connector =
153
+ Channel = { id, name, delivery, connectors[] }
154
+ subscription box; `delivery` is `fanout` (default; every WS client sees every event)
155
+ or `exclusive` (round-robin one client per event)
156
+
157
+ Connector =
138
158
  | { type: "slack", name, botToken, appToken }
139
159
  Slack Socket Mode
140
160
  | { type: "gh", name, pollInterval? }
141
- GitHub (gh CLI)
161
+ GitHub (gh CLI, poll-based)
142
162
  | { type: "discord", name, botToken }
143
163
  Discord Gateway
144
164
  | { type: "schedule", name, entries[] }
145
- cron-driven, entries = { id, cron, prompt, enabled }
165
+ cron-driven; entries = { id, cron, prompt, enabled?, catchupPolicy? }
146
166
 
147
- Channel = { name, connectors[] }
148
- subscription box
167
+ Profile = { name, path, subAgent, channelId }
168
+ named launch preset; the first profile in the list is the default
149
169
 
150
- Repository = { name, path }
151
- extra
170
+ Settings = { channels[], profiles[] }
171
+ → ~/.funnel/settings.json
172
+ ```
152
173
 
153
- Profile = { name, channel, repo?, subAgent?, envFiles? }
154
- launch profile
174
+ Connectors are stored per type, one file per connector, under `~/.funnel/connectors/<type>/<name>.(json|jsonl)` so adding or retiring a type is contained to its own subdirectory.
155
175
 
156
- Settings = { channels[], repositories[], profiles[] }
157
- → ~/.funnel/settings.json
176
+ ## Programmable API (Bun)
158
177
 
159
- Connectors are stored per type, one file per connector:
160
- → ~/.funnel/connectors/<type>/<name>.(json|jsonl)
178
+ `funnel` is also usable as a library — the same `Funnel` facade the CLI uses is exported from the package root, with no CLI side effects.
179
+
180
+ ```ts
181
+ import { Funnel } from "@interactive-inc/claude-funnel"
182
+
183
+ const funnel = new Funnel() // defaults to ~/.funnel + the local filesystem
184
+
185
+ const channel = funnel.channels.add({ name: "inbox" })
186
+
187
+ funnel.channels.addConnector("inbox", {
188
+ type: "slack",
189
+ name: "my-slack",
190
+ botToken: "xoxb-...",
191
+ appToken: "xapp-...",
192
+ })
193
+
194
+ for (const c of funnel.channels.list()) console.log(c.name, c.connectors.length)
161
195
  ```
162
196
 
197
+ Every facet — `channels` / `profiles` / `gateway` / `gatewayServer` / `gatewayToken` / `listeners` / `mcp` / `claude` / `factory` / `store` / `process` / `logger` — is reachable from the same instance:
198
+
199
+ ```ts
200
+ funnel.gateway.getStatus() // { running, pid, port }
201
+ await funnel.gateway.start() // spawns the daemon as a separate process
202
+
203
+ await funnel.listeners.list() // talks to the running daemon over HTTP
204
+ await funnel.listeners.start("inbox", "my-slack")
205
+ await funnel.listeners.restart("inbox", "my-slack")
206
+
207
+ await funnel.claude.launch({ channel: "inbox" })
208
+ funnel.mcp.install("/path/to/repo") // writes .mcp.json
209
+ ```
210
+
211
+ Run the gateway in-process (no daemon spawn — useful for tests or embedding):
212
+
213
+ ```ts
214
+ const server = funnel.gatewayServer({ port: 9742 })
215
+ await server.start() // Bun.serve (HTTP + WS) + listener supervisor
216
+ const unsubscribe = server.getBroadcaster().subscribe(({ content, meta }) => {
217
+ console.log(meta?.connector, content)
218
+ })
219
+ await server.stop()
220
+ unsubscribe()
221
+ ```
222
+
223
+ The gateway daemon exposes `/health`, `/status`, `/listeners*`, `/channels/:channel/connectors/:connector/call`, plus the `/ws?channel=<name>` WebSocket. There is no SPA; for a visual operator view, run `fnl` with no arguments to launch the OpenTUI dashboard.
224
+
225
+ Every side-effecting boundary is a DI seam. For tests / sandbox use, swap them all with the in-memory implementations and Funnel will not touch real disk, real processes, real time, or real UUIDs:
226
+
227
+ ```ts
228
+ import {
229
+ Funnel,
230
+ MemoryFunnelClock,
231
+ MemoryFunnelFileSystem,
232
+ MemoryFunnelIdGenerator,
233
+ MemoryFunnelLogger,
234
+ MemoryFunnelProcessRunner,
235
+ MockFunnelSettingsReader,
236
+ } from "@interactive-inc/claude-funnel"
237
+
238
+ const funnel = new Funnel({
239
+ store: new MockFunnelSettingsReader(),
240
+ fs: new MemoryFunnelFileSystem(),
241
+ process: new MemoryFunnelProcessRunner(),
242
+ logger: new MemoryFunnelLogger(),
243
+ clock: new MemoryFunnelClock({ start: new Date("2026-01-01T00:00:00Z") }),
244
+ idGenerator: new MemoryFunnelIdGenerator({ prefix: "test" }),
245
+ dir: "/sandbox/.funnel",
246
+ tmpDir: "/sandbox/tmp",
247
+ })
248
+ ```
249
+
250
+ Available abstractions (each has `Funnel*` interface, `Node*` default, and `Memory*` for tests): `FunnelFileSystem`, `FunnelProcessRunner`, `FunnelLogger`, `FunnelClock`, `FunnelIdGenerator`. Plus `NoopFunnelLogger` for silent operation.
251
+
252
+ The published package ships both TypeScript sources (under `lib/`) for library consumers and a single bundled CLI (`dist/bin.js`) which is what the `fnl` / `funnel` bin entries point to. Importing `@interactive-inc/claude-funnel/bin` resolves to the bundled CLI entry — only do this if you're embedding the CLI rather than the library.
253
+
254
+ ## Claude Code skill
255
+
256
+ This repo ships a Claude Code skill at `.claude/skills/funnel/SKILL.md`. It briefs Claude on the architecture and command groups, and tells it to defer flag-level details to `funnel <command> --help`.
257
+
258
+ ### Project-scoped (auto)
259
+
260
+ If you run `claude` inside this repo, the skill is picked up automatically — no install step.
261
+
262
+ ### Global (use the skill in any project)
263
+
264
+ Claude Code does not currently provide a CLI to install skills from a remote URL, so copy the file into your personal skills directory:
265
+
266
+ ```bash
267
+ # from a clone of this repo
268
+ mkdir -p ~/.claude/skills/funnel
269
+ cp .claude/skills/funnel/SKILL.md ~/.claude/skills/funnel/
270
+ ```
271
+
272
+ Or fetch it directly without cloning:
273
+
274
+ ```bash
275
+ mkdir -p ~/.claude/skills/funnel
276
+ curl -fsSL https://raw.githubusercontent.com/interactive-inc/open-claude-funnel/main/.claude/skills/funnel/SKILL.md \
277
+ -o ~/.claude/skills/funnel/SKILL.md
278
+ ```
279
+
280
+ After this, Claude Code will load the skill in any session.
281
+
163
282
  ## Discord bot setup
164
283
 
165
284
  - Create a bot in the Discord Developer Portal and obtain its token
@@ -168,39 +287,42 @@ Connectors are stored per type, one file per connector:
168
287
 
169
288
  ## Environment variables
170
289
 
171
- | Variable | Purpose |
172
- | -------------------- | --------------------------------------------------------------------------------------- |
173
- | `FUNNEL_CHANNEL_ID` | Injected into the child process by `fnl claude`; funnel MCP uses it to subscribe. |
174
- | `FUNNEL_PORT` | Gateway port (default 9742). |
175
- | `FUNNEL_GATEWAY_URL` | Gateway WebSocket URL used by MCP (default `ws://localhost:9742/ws`). |
290
+ | Variable | Purpose |
291
+ | ---------------------- | --------------------------------------------------------------------------------------------- |
292
+ | `FUNNEL_CHANNEL_ID` | Injected into the child process by `fnl claude`; the funnel MCP uses it to subscribe. |
293
+ | `FUNNEL_PORT` | Gateway port (default 9742). |
294
+ | `FUNNEL_GATEWAY_URL` | Gateway base URL used by MCP for both WS subscribe and HTTP reply (default `http://localhost:9742`). |
295
+ | `FUNNEL_GATEWAY_TOKEN` | Bearer token for the gateway HTTP / WS. Defaults to the contents of `~/.funnel/gateway.token`. |
176
296
 
177
297
  ## File layout
178
298
 
179
- - Config: `~/.funnel/settings.json` (channels / repositories / profiles)
299
+ - Config: `~/.funnel/settings.json` (channels with nested connectors / profiles)
180
300
  - Connectors: `~/.funnel/connectors/<type>/<name>.(json|jsonl)`
181
301
  - `slack/<name>.json`, `gh/<name>.json`, `discord/<name>.json`
182
302
  - `schedule/<name>.jsonl` (one entry per line) and `schedule/<name>.state.json` (last-fired timestamps for catch-up)
183
- - PID: `~/.funnel/gateway.pid`
303
+ - Gateway PID: `~/.funnel/gateway.pid`, token: `~/.funnel/gateway.token`
184
304
  - Claude PIDs: `~/.funnel/claude/<profile>.pid`
185
- - Event log: `/tmp/funnel/events/*.jsonl` (auto-deleted after 30 days)
186
- - Process log: `/tmp/funnel/gateway.log`
305
+ - Event store: `/tmp/funnel/events/events.db` (SQLite; broadcaster events with replay-by-seq)
306
+ - Diagnostic log: `/tmp/funnel/funnel.log` (gateway lifecycle, connect/disconnect, listener boot — what `funnel gateway logs` tails as YAML)
307
+ - Process log: `/tmp/funnel/gateway.log` (daemon stdout/stderr)
187
308
 
188
309
  ## Links
189
310
 
190
311
  - [GitHub](https://github.com/interactive-inc/open-claude-funnel)
191
312
  - [Issues](https://github.com/interactive-inc/open-claude-funnel/issues)
192
313
  - Coding rules and design principles: [CLAUDE.md](https://github.com/interactive-inc/open-claude-funnel/blob/main/CLAUDE.md)
193
- - Design notes: [`.docs/`](https://github.com/interactive-inc/open-claude-funnel/tree/main/.docs)
194
314
 
195
315
  ## Development
196
316
 
197
317
  ```bash
198
318
  git clone https://github.com/interactive-inc/open-claude-funnel.git
199
- cd claude-funnel
200
- bun install
201
- bun link # register funnel / fnl globally
319
+ cd open-claude-funnel
320
+ bun install # postinstall builds dist/bin.js
321
+ bun link # symlinks fnl / funnel → dist/bin.js
322
+ bun run build # rebuild after editing the cli
202
323
  bun test # run tests
203
324
  bunx tsc -b # type check
325
+ bun lib/bin.ts ... # run the cli from source (no build) for fast iteration
204
326
  ```
205
327
 
206
328
  ## License