kennel 0.2.3 → 0.2.5

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 (237) hide show
  1. package/README.md +23 -13
  2. package/dist/cli/dispatch.js +16 -3
  3. package/dist/cli/src/cli/dispatch.js +16 -3
  4. package/dist/cli/src/cli/usage.js +1 -1
  5. package/dist/cli/src/core/command.js +1 -0
  6. package/dist/cli/src/core/init.js +5 -5
  7. package/dist/cli/src/plugins/external.d.ts +28 -2
  8. package/dist/cli/src/plugins/external.js +75 -21
  9. package/dist/cli/src/site/server-plugins.d.ts +2 -7
  10. package/dist/cli/src/site/viewer.js +1 -0
  11. package/dist/cli/usage.js +1 -1
  12. package/dist/core/command.js +1 -0
  13. package/dist/core/init.js +5 -5
  14. package/dist/core/runtime.js +357 -3207
  15. package/dist/package/preview.js +1232 -5113
  16. package/dist/plugins/external.d.ts +28 -2
  17. package/dist/plugins/external.js +75 -21
  18. package/dist/site/server-plugins.d.ts +2 -7
  19. package/dist/site/server-plugins.js +552 -10447
  20. package/dist/site/viewer.js +1 -0
  21. package/kernel/apps/web/package.json +1 -5
  22. package/kernel/apps/web/scripts/dev.mjs +53 -0
  23. package/kernel/apps/web/src/app.css +0 -3
  24. package/kernel/apps/web/src/main.tsx +0 -1
  25. package/kernel/apps/web/src/plugins.ts +0 -30
  26. package/kernel/apps/web/tsconfig.json +1 -2
  27. package/kernel/apps/web/vite.config.ts +31 -13
  28. package/kernel/packages/api/package.json +0 -4
  29. package/kernel/packages/api/src/server/folder-metadata-plugin.ts +13 -38
  30. package/kernel/packages/api/src/server/index.ts +0 -1
  31. package/kernel/packages/api/src/server/plugins.ts +49 -16
  32. package/kernel/packages/api/test/core.test.ts +13 -25
  33. package/kernel/packages/markdown/README.md +1 -1
  34. package/package.json +1 -1
  35. package/web/assets/{abnfDiagram-VRR7QNED-Bgfb1nEB.js → abnfDiagram-VRR7QNED-xd_g1uK3.js} +1 -1
  36. package/web/assets/app-CX20nNIa.js +2 -0
  37. package/web/assets/{app-options-D-RJiQ-X.js → app-options-CkPJE5ep.js} +1 -1
  38. package/web/assets/{app-view-header-BLvLq02T.js → app-view-header-CNk5KnA-.js} +1 -1
  39. package/web/assets/{arc-Dk_KI36B.js → arc-B0u5yBJA.js} +1 -1
  40. package/web/assets/{architectureDiagram-ZJ3FMSHR-NR_KhRCf.js → architectureDiagram-ZJ3FMSHR-DfxOAo8P.js} +1 -1
  41. package/web/assets/{ask-tray-TzeTcO6-.js → ask-tray-SscJecDY.js} +1 -1
  42. package/web/assets/{blockDiagram-677ZJIJ3-CkLkwx9C.js → blockDiagram-677ZJIJ3-Ci3Usxh6.js} +1 -1
  43. package/web/assets/{c4Diagram-LMCZKHZV-CFCUH8e_.js → c4Diagram-LMCZKHZV-BqgwIVgh.js} +1 -1
  44. package/web/assets/channel-X7WHyxxT.js +1 -0
  45. package/web/assets/{chunk-2Q5K7J3B-B_BPLWsW.js → chunk-2Q5K7J3B-CfX69l2U.js} +1 -1
  46. package/web/assets/{chunk-32BRIVSS-B1VB1hOy.js → chunk-32BRIVSS-CuFlzZkl.js} +1 -1
  47. package/web/assets/{chunk-5VM5RSS4-KFcYr8Co.js → chunk-5VM5RSS4-DidCMlJa.js} +1 -1
  48. package/web/assets/{chunk-EX3LRPZG-CpBX3kuK.js → chunk-EX3LRPZG-B5CDm1dS.js} +1 -1
  49. package/web/assets/{chunk-JWPE2WC7-BPSl40wG.js → chunk-JWPE2WC7-D5fGV_sH.js} +1 -1
  50. package/web/assets/{chunk-MOJQB5TN-D2RcYmoU.js → chunk-MOJQB5TN-ayhH5Q-H.js} +1 -1
  51. package/web/assets/{chunk-RYQCIY6F-m7Gyn-t3.js → chunk-RYQCIY6F-C4BfOOZn.js} +1 -1
  52. package/web/assets/{chunk-V7JOEXUC-TDvdopxS.js → chunk-V7JOEXUC-DpUEIM9V.js} +1 -1
  53. package/web/assets/{chunk-VR4S4FIN-DZTsG51a.js → chunk-VR4S4FIN-DoQuFFRh.js} +1 -1
  54. package/web/assets/{chunk-XXDRQBXY-Dp0--RE2.js → chunk-XXDRQBXY-CI9eiLwn.js} +1 -1
  55. package/web/assets/classDiagram-OUVF2IWQ-BjsLQ3dz.js +1 -0
  56. package/web/assets/classDiagram-v2-EOCWNBFH-BjsLQ3dz.js +1 -0
  57. package/web/assets/client-7OWw5kW2.js +6 -0
  58. package/web/assets/client-DYj_td4Q.js +17 -0
  59. package/web/assets/{client-j2kQmxsO.js → client-Dk-NBvJR.js} +4 -4
  60. package/web/assets/command-zkzH4hVz.js +38 -0
  61. package/web/assets/{copy-context-C0Uqsp-3.js → copy-context-D5oiWrYC.js} +1 -1
  62. package/web/assets/{cose-bilkent-JH36ORCC-CPu3PI8h.js → cose-bilkent-JH36ORCC-BHRk1mO3.js} +1 -1
  63. package/web/assets/{cynefin-VYW2F7L2-DWxftYAm.js → cynefin-VYW2F7L2-C1B09TRE.js} +1 -1
  64. package/web/assets/{cynefinDiagram-TSTJHNR4-DsmN2V-p.js → cynefinDiagram-TSTJHNR4-B27qXQbv.js} +1 -1
  65. package/web/assets/{dagre-VKFMJZFB-COEbApyY.js → dagre-VKFMJZFB-B1qEi32g.js} +1 -1
  66. package/web/assets/{diagram-FQU43EPY-0O9WGWKB.js → diagram-FQU43EPY-BMkkgADD.js} +1 -1
  67. package/web/assets/{diagram-G47NLZAW-CutEdMVh.js → diagram-G47NLZAW-Cb8_g1A5.js} +1 -1
  68. package/web/assets/{diagram-NH7WQ7WH-C9KZc3B2.js → diagram-NH7WQ7WH-B51wuc5m.js} +1 -1
  69. package/web/assets/{diagram-OA4YK3LP-D8kkPXbY.js → diagram-OA4YK3LP-xnsecbbI.js} +1 -1
  70. package/web/assets/{diagram-WEI45ONY-_YqiTaGP.js → diagram-WEI45ONY-DSZdyaAV.js} +1 -1
  71. package/web/assets/{document-Dgt5eZFj.js → document-Dc2dftTW.js} +3 -3
  72. package/web/assets/{ebnfDiagram-CCIWWBDH-JO-zQh6g.js → ebnfDiagram-CCIWWBDH-aTHmcUGy.js} +1 -1
  73. package/web/assets/{entities-C3wz7FCx.js → entities-CCUtpskY.js} +1 -1
  74. package/web/assets/{erDiagram-Q63AITRT-9UjQwJ4P.js → erDiagram-Q63AITRT-CUUPBcvo.js} +1 -1
  75. package/web/assets/{file-viewer-DZJ8nYnl.js → file-viewer-DJ3rsmef.js} +1 -1
  76. package/web/assets/{flowDiagram-23GEKE2U-Ca08tnYM.js → flowDiagram-23GEKE2U-aTQXx2Mh.js} +1 -1
  77. package/web/assets/{folder-image-BfGgxo7i.js → folder-image-Bnv43tzP.js} +1 -1
  78. package/web/assets/{folder-landing-qUKBCnG-.js → folder-landing-DCnzYXXY.js} +1 -1
  79. package/web/assets/{folder-list-BfFjv7rR.js → folder-list-DvVkVjiR.js} +1 -1
  80. package/web/assets/{folder-metadata-DCw8xzHk.js → folder-metadata-C9hMMzIH.js} +1 -1
  81. package/web/assets/{folder-mobile-bar-Ubz4babf.js → folder-mobile-bar-VoTL1GS0.js} +1 -1
  82. package/web/assets/folder-plugin-view-Cvd804ZU.js +6 -0
  83. package/web/assets/{ganttDiagram-NO4QXBWP-KnHzX5W3.js → ganttDiagram-NO4QXBWP-DiwdUp7u.js} +1 -1
  84. package/web/assets/{gitGraphDiagram-IHSO6WYX-Cm8woNtK.js → gitGraphDiagram-IHSO6WYX-BL2gG_IS.js} +1 -1
  85. package/web/assets/{index-CNyy98F8.js → index-CUTtMSyJ.js} +2 -2
  86. package/web/assets/index-CegvVQ1C.js +1 -0
  87. package/web/assets/index-Dwhf8F_U.css +1 -0
  88. package/web/assets/{infoDiagram-FWYZ7A6U-yyqmUtIb.js → infoDiagram-FWYZ7A6U-B3n0zZpt.js} +1 -1
  89. package/web/assets/{ishikawaDiagram-FXEZZL3T-BfvR_Zy4.js → ishikawaDiagram-FXEZZL3T-D7YytbEv.js} +1 -1
  90. package/web/assets/{journeyDiagram-5HDEW3XC-BKuw06HM.js → journeyDiagram-5HDEW3XC-BYwqEl3C.js} +1 -1
  91. package/web/assets/{kanban-definition-HUTT4EX6-n0010rmQ.js → kanban-definition-HUTT4EX6-BQHNJgXZ.js} +1 -1
  92. package/web/assets/{linear-C0d0lT8O.js → linear-BPiQCLNk.js} +1 -1
  93. package/web/assets/{mermaid.core-BDVbShyO.js → mermaid.core-CD-KvBjV.js} +4 -4
  94. package/web/assets/{metadata-KV0dpp4G.js → metadata-COJ7fZul.js} +1 -1
  95. package/web/assets/{mindmap-definition-LN4V7U3C--_0ks3GF.js → mindmap-definition-LN4V7U3C-C1L_gyoj.js} +1 -1
  96. package/web/assets/{pegDiagram-2B236MQR-CBoNIpKR.js → pegDiagram-2B236MQR-BDAfItqS.js} +1 -1
  97. package/web/assets/{pieDiagram-ENE6RG2P-MA5tkYh5.js → pieDiagram-ENE6RG2P-CkZYH3Vz.js} +1 -1
  98. package/web/assets/{popover-DBD7FF-W.js → popover-0oA2lLUV.js} +2 -2
  99. package/web/assets/{project-search-dialog-DM1IkSZu.js → project-search-dialog-B2oqMT6h.js} +1 -1
  100. package/web/assets/{quadrantDiagram-ABIIQ3AL-CWT1ryqF.js → quadrantDiagram-ABIIQ3AL-Dy8Al3YZ.js} +1 -1
  101. package/web/assets/{railroadDiagram-RFXS5EU6-ZiLB5FGi.js → railroadDiagram-RFXS5EU6-Dd9_yo7B.js} +1 -1
  102. package/web/assets/{requirementDiagram-TGXJPOKE-CQq9uneq.js → requirementDiagram-TGXJPOKE-DPhIUsbs.js} +1 -1
  103. package/web/assets/{sankeyDiagram-HTMAVEWB-qDG-0JqI.js → sankeyDiagram-HTMAVEWB-B2QkYtub.js} +1 -1
  104. package/web/assets/{search-DNrQA5fF.js → search-C1J0-xiB.js} +1 -1
  105. package/web/assets/select-CtXC_PLC.js +30 -0
  106. package/web/assets/{selection-popup-DmtTeRs2.js → selection-popup-qhlUFzGq.js} +1 -1
  107. package/web/assets/{sequenceDiagram-DBY2YBRQ-CiApurLO.js → sequenceDiagram-DBY2YBRQ-Bx7fcZDx.js} +1 -1
  108. package/web/assets/{sizeCapture-X5ZJPWSS-DZSR5QXm.js → sizeCapture-X5ZJPWSS-CIXIhl_A.js} +1 -1
  109. package/web/assets/{stateDiagram-2N3HPSRC-CjJJR9_z.js → stateDiagram-2N3HPSRC-DCrdAflB.js} +1 -1
  110. package/web/assets/stateDiagram-v2-6OUMAXLB-0KCFLYeQ.js +1 -0
  111. package/web/assets/{swimlanes-5IMT3BWC-CKmo1sg6.js → swimlanes-5IMT3BWC-DA2vc7iZ.js} +2 -2
  112. package/web/assets/swimlanesDiagram-G3AALYLV-CAw3AV84.js +8 -0
  113. package/web/assets/{timeline-definition-FHXFAJF6-D-NMwS3y.js → timeline-definition-FHXFAJF6-lKfJiV9V.js} +1 -1
  114. package/web/assets/{vennDiagram-L72KCM5P-CfL6LBWw.js → vennDiagram-L72KCM5P-DO1q2KzG.js} +1 -1
  115. package/web/assets/{view-context-gyDl_p2V.js → view-context-DXKM3-l1.js} +4 -4
  116. package/web/assets/{viewer-capabilities-Bpp8Uvcg.js → viewer-capabilities-Cig_xM9u.js} +1 -1
  117. package/web/assets/{wardleyDiagram-EHGQE667-DgldMxaj.js → wardleyDiagram-EHGQE667-Dal9LkuZ.js} +1 -1
  118. package/web/assets/{xychartDiagram-FW5EYKEG-CIoAIFX8.js → xychartDiagram-FW5EYKEG-B3dPLPII.js} +1 -1
  119. package/web/index.html +2 -2
  120. package/kernel/packages/api/test/partial-loading.test.ts +0 -43
  121. package/kernel/plugins/calendar/SKILL.md +0 -173
  122. package/kernel/plugins/calendar/eslint.config.js +0 -10
  123. package/kernel/plugins/calendar/package.json +0 -73
  124. package/kernel/plugins/calendar/schema.json +0 -137
  125. package/kernel/plugins/calendar/src/calendar.tsx +0 -328
  126. package/kernel/plugins/calendar/src/client.tsx +0 -139
  127. package/kernel/plugins/calendar/src/context.ts +0 -48
  128. package/kernel/plugins/calendar/src/copy-button.tsx +0 -66
  129. package/kernel/plugins/calendar/src/event-dialog.tsx +0 -270
  130. package/kernel/plugins/calendar/src/index.ts +0 -4
  131. package/kernel/plugins/calendar/src/manifest.ts +0 -7
  132. package/kernel/plugins/calendar/src/parse.ts +0 -610
  133. package/kernel/plugins/calendar/src/server.ts +0 -160
  134. package/kernel/plugins/calendar/src/utils.ts +0 -80
  135. package/kernel/plugins/calendar/src/views.tsx +0 -418
  136. package/kernel/plugins/calendar/test/context.test.mjs +0 -60
  137. package/kernel/plugins/calendar/test/package.test.mjs +0 -43
  138. package/kernel/plugins/calendar/test/parse.test.mjs +0 -392
  139. package/kernel/plugins/calendar/test/server.test.mjs +0 -126
  140. package/kernel/plugins/calendar/tsconfig.json +0 -17
  141. package/kernel/plugins/mail/SKILL.md +0 -97
  142. package/kernel/plugins/mail/eslint.config.js +0 -10
  143. package/kernel/plugins/mail/package.json +0 -79
  144. package/kernel/plugins/mail/src/api.ts +0 -359
  145. package/kernel/plugins/mail/src/bun-ffi.d.ts +0 -14
  146. package/kernel/plugins/mail/src/client.tsx +0 -14
  147. package/kernel/plugins/mail/src/flock.ts +0 -137
  148. package/kernel/plugins/mail/src/folders.ts +0 -37
  149. package/kernel/plugins/mail/src/history.ts +0 -485
  150. package/kernel/plugins/mail/src/index.ts +0 -3
  151. package/kernel/plugins/mail/src/mail-card.tsx +0 -123
  152. package/kernel/plugins/mail/src/mail-conversation.tsx +0 -153
  153. package/kernel/plugins/mail/src/mail-detail-page.tsx +0 -467
  154. package/kernel/plugins/mail/src/mail-hooks.ts +0 -252
  155. package/kernel/plugins/mail/src/mail-page.tsx +0 -109
  156. package/kernel/plugins/mail/src/mail-request.ts +0 -78
  157. package/kernel/plugins/mail/src/mail-send-box.tsx +0 -175
  158. package/kernel/plugins/mail/src/mailos.ts +0 -723
  159. package/kernel/plugins/mail/src/manifest.ts +0 -7
  160. package/kernel/plugins/mail/src/node.ts +0 -171
  161. package/kernel/plugins/mail/src/parse.ts +0 -139
  162. package/kernel/plugins/mail/src/server.ts +0 -125
  163. package/kernel/plugins/mail/src/types.ts +0 -10
  164. package/kernel/plugins/mail/src/viewer.tsx +0 -147
  165. package/kernel/plugins/mail/test/flock.test.mjs +0 -156
  166. package/kernel/plugins/mail/test/folders.test.mjs +0 -138
  167. package/kernel/plugins/mail/test/history.test.mjs +0 -460
  168. package/kernel/plugins/mail/test/mailos.test.mjs +0 -752
  169. package/kernel/plugins/mail/test/node.test.mjs +0 -207
  170. package/kernel/plugins/mail/test/package.test.mjs +0 -54
  171. package/kernel/plugins/mail/test/parse.test.mjs +0 -32
  172. package/kernel/plugins/mail/test/server.test.mjs +0 -116
  173. package/kernel/plugins/mail/test/viewer.test.mjs +0 -192
  174. package/kernel/plugins/mail/tsconfig.json +0 -17
  175. package/kernel/plugins/projects/SKILL.md +0 -73
  176. package/kernel/plugins/projects/eslint.config.js +0 -10
  177. package/kernel/plugins/projects/package.json +0 -70
  178. package/kernel/plugins/projects/src/client.tsx +0 -17
  179. package/kernel/plugins/projects/src/data/model.ts +0 -129
  180. package/kernel/plugins/projects/src/index.ts +0 -17
  181. package/kernel/plugins/projects/src/manifest.ts +0 -7
  182. package/kernel/plugins/projects/src/project-context.ts +0 -41
  183. package/kernel/plugins/projects/src/server.ts +0 -276
  184. package/kernel/plugins/projects/src/ui/project-card.tsx +0 -61
  185. package/kernel/plugins/projects/src/ui/projects-page.tsx +0 -102
  186. package/kernel/plugins/projects/test/package.test.mjs +0 -51
  187. package/kernel/plugins/projects/tsconfig.json +0 -17
  188. package/kernel/plugins/tasks/SKILL.md +0 -341
  189. package/kernel/plugins/tasks/eslint.config.js +0 -10
  190. package/kernel/plugins/tasks/package.json +0 -74
  191. package/kernel/plugins/tasks/schema.json +0 -939
  192. package/kernel/plugins/tasks/src/api.ts +0 -212
  193. package/kernel/plugins/tasks/src/client.tsx +0 -23
  194. package/kernel/plugins/tasks/src/data/parse.ts +0 -544
  195. package/kernel/plugins/tasks/src/data/task-id.ts +0 -56
  196. package/kernel/plugins/tasks/src/data/todo-model.ts +0 -795
  197. package/kernel/plugins/tasks/src/index.ts +0 -34
  198. package/kernel/plugins/tasks/src/manifest.ts +0 -7
  199. package/kernel/plugins/tasks/src/pages/task-detail.tsx +0 -48
  200. package/kernel/plugins/tasks/src/pages/task-list.tsx +0 -88
  201. package/kernel/plugins/tasks/src/server.ts +0 -447
  202. package/kernel/plugins/tasks/src/styles.css +0 -9
  203. package/kernel/plugins/tasks/src/ui/compact-todo-list.tsx +0 -372
  204. package/kernel/plugins/tasks/src/ui/error-details.tsx +0 -78
  205. package/kernel/plugins/tasks/src/ui/task-page.tsx +0 -392
  206. package/kernel/plugins/tasks/src/ui/todo-agent-filter.tsx +0 -36
  207. package/kernel/plugins/tasks/src/ui/todo-filter-bar.tsx +0 -66
  208. package/kernel/plugins/tasks/src/ui/todo-item.tsx +0 -494
  209. package/kernel/plugins/tasks/src/ui/todo-status-filter.tsx +0 -60
  210. package/kernel/plugins/tasks/src/ui/todo-tag-filter.tsx +0 -48
  211. package/kernel/plugins/tasks/src/ui/todo-warnings.tsx +0 -106
  212. package/kernel/plugins/tasks/test/api.test.mjs +0 -99
  213. package/kernel/plugins/tasks/test/folder-sources.test.mjs +0 -46
  214. package/kernel/plugins/tasks/test/package.test.mjs +0 -54
  215. package/kernel/plugins/tasks/test/parse.test.mjs +0 -225
  216. package/kernel/plugins/tasks/test/server.test.mjs +0 -386
  217. package/kernel/plugins/tasks/tsconfig.json +0 -17
  218. package/web/assets/app-DoGr2Zi7.js +0 -2
  219. package/web/assets/channel-uMEjV8qc.js +0 -1
  220. package/web/assets/classDiagram-OUVF2IWQ-fbZocVor.js +0 -1
  221. package/web/assets/classDiagram-v2-EOCWNBFH-fbZocVor.js +0 -1
  222. package/web/assets/client-C6Nxdfif.js +0 -2
  223. package/web/assets/client-CXYfBko5.js +0 -17
  224. package/web/assets/client-CoKtOq-X.js +0 -7
  225. package/web/assets/client-DyRQz5RU.js +0 -53
  226. package/web/assets/client-OY6HUzuD.js +0 -98
  227. package/web/assets/client-YOYWZIFi.js +0 -34
  228. package/web/assets/command-BugZBGXE.js +0 -38
  229. package/web/assets/folder-plugin-view-DsWR1zmQ.js +0 -6
  230. package/web/assets/index-BaRnbYRw.js +0 -1
  231. package/web/assets/index-BexmLxIP.css +0 -1
  232. package/web/assets/index-DDirZMgx.js +0 -1
  233. package/web/assets/note-card-DBfX6gW1.js +0 -6
  234. package/web/assets/select-D8cqNgcp.js +0 -30
  235. package/web/assets/stateDiagram-v2-6OUMAXLB-BpeGSCu9.js +0 -1
  236. package/web/assets/swimlanesDiagram-G3AALYLV-D9RjLKb9.js +0 -8
  237. package/web/assets/use-folder-filter-LQyXns5Q.js +0 -1
package/README.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  Publishing, MCP generation, and knowledge-source commands for Kennel workspaces. The compact schema validator has moved to the private [`raggle-ai/kennel-compact`](https://github.com/raggle-ai/kennel-compact) repository.
4
4
 
5
+ ## Local web development
6
+
7
+ Run `bun run web` from the repository root. The dev server uses the plugins
8
+ installed with `kennel plugin add` in your Kennel user configuration. It shares
9
+ the CLI's client registry and server/API bundling; it does not require a local
10
+ `plugins/` directory. Restart the dev server after installing a plugin.
11
+
5
12
  ## Usage
6
13
 
7
14
  ```bash
@@ -27,6 +34,7 @@ kennel serve /path/to/workspace
27
34
  kennel dev /path/to/docs-site --config index.json
28
35
  kennel init .
29
36
  kennel plugin add https://github.com/example/kennel-transcripts-plugin.git#main
37
+ kennel plugin add https://github.com/raggle-ai/kennel-plugins.git --path plugins/calendar
30
38
  kennel core-folders .
31
39
  kennel mcp generate . --config index.json
32
40
  kennel publish init cloudflare .
@@ -76,13 +84,14 @@ Entity search reads allowed local roots from
76
84
  ```
77
85
 
78
86
  The same user config stores trusted external folder plugins added with
79
- `kennel plugin add <git-repository-url[#ref]>`. The command pins the requested
80
- ref, or `HEAD` with no fragment, to a full commit, validates package metadata
81
- and explicit client/server/manifest exports, builds the composed kernel in the
82
- XDG cache, and only then atomically updates config. Installed plugin imports are
83
- derived from package metadata, not from URL text. The transcripts plugin
84
- contract is package `kennel-transcripts-plugin`, id `memos`, trigger
85
- `memos.json`.
87
+ `kennel plugin add <git-repository-url[#ref]> [--path <subdirectory>]`. The
88
+ command pins the requested ref, or `HEAD` with no fragment, to a full commit,
89
+ selects the repository root or the requested subdirectory as the plugin package
90
+ root, validates package metadata and explicit client/server/manifest exports
91
+ plus optional API/CSS exports, builds the composed kernel in the XDG cache, and
92
+ only then atomically updates config. Installed plugin imports are derived from
93
+ package metadata, not from URL text. The transcripts plugin contract is package
94
+ `kennel-transcripts-plugin`, id `memos`, trigger `memos.json`.
86
95
 
87
96
  When this file is absent, entity search allows only the workspace opened by
88
97
  `knl`. Invalid config fails closed.
@@ -92,12 +101,13 @@ Suggested convention for agents: write generated HTML components to
92
101
  .kennel/preview/<name>.html --watch` (reuses 5180), so preview items share one
93
102
  well-known scratch folder across any AI client.
94
103
 
95
- `kennel init` scaffolds starter content files for the folder plugins into
96
- the current folder (or the given path): `todo.json` for Tasks and
97
- `calendar.json` for Calendar, each referencing its published schema and
98
- passing the plugin's validation immediately. Existing files are left
99
- untouched; `--plugin <id>` scaffolds one plugin, `--force` overwrites, and
100
- `--list` prints what would be created without writing.
104
+ `kennel init` scaffolds starter content files for installed folder plugins into
105
+ the current folder (or the given path). The external Tasks and Calendar plugins
106
+ provide `todo.json` and `calendar.json` templates after they are installed from
107
+ `raggle-ai/kennel-plugins` with `kennel plugin add ... --path plugins/<id>`.
108
+ Existing files are left untouched; `--plugin <id>` scaffolds one plugin,
109
+ `--force` overwrites, and `--list` prints what would be created without
110
+ writing.
101
111
 
102
112
  `kennel core-folders` lists schema-declared collections and their records using
103
113
  the same metadata index as the UI. Titles, icons, counts, fields and validation
@@ -13,10 +13,23 @@ export async function dispatch(argv) {
13
13
  }
14
14
  if (command === 'plugin' && args[0] === 'add') {
15
15
  const url = args[1];
16
- if (!url || args.length !== 2)
17
- throw new Error('Usage: kennel plugin add <git-repository-url>');
16
+ let directory;
17
+ for (let index = 2; index < args.length; index += 1) {
18
+ const arg = args[index];
19
+ if (arg === '--path' || arg === '--directory') {
20
+ directory = args[index + 1];
21
+ if (!directory)
22
+ throw new Error(`${arg} requires a plugin subdirectory`);
23
+ index += 1;
24
+ }
25
+ else {
26
+ throw new Error('Usage: kennel plugin add <git-repository-url> [--path <subdirectory>]');
27
+ }
28
+ }
29
+ if (!url)
30
+ throw new Error('Usage: kennel plugin add <git-repository-url> [--path <subdirectory>]');
18
31
  const { installExternalPlugin } = await import('../plugins/external.js');
19
- const plugin = await installExternalPlugin(url);
32
+ const plugin = await installExternalPlugin(url, { directory });
20
33
  console.log(`Installed plugin ${plugin.id} from ${plugin.packageName} at ${plugin.commit}`);
21
34
  return;
22
35
  }
@@ -13,10 +13,23 @@ export async function dispatch(argv) {
13
13
  }
14
14
  if (command === 'plugin' && args[0] === 'add') {
15
15
  const url = args[1];
16
- if (!url || args.length !== 2)
17
- throw new Error('Usage: kennel plugin add <git-repository-url>');
16
+ let directory;
17
+ for (let index = 2; index < args.length; index += 1) {
18
+ const arg = args[index];
19
+ if (arg === '--path' || arg === '--directory') {
20
+ directory = args[index + 1];
21
+ if (!directory)
22
+ throw new Error(`${arg} requires a plugin subdirectory`);
23
+ index += 1;
24
+ }
25
+ else {
26
+ throw new Error('Usage: kennel plugin add <git-repository-url> [--path <subdirectory>]');
27
+ }
28
+ }
29
+ if (!url)
30
+ throw new Error('Usage: kennel plugin add <git-repository-url> [--path <subdirectory>]');
18
31
  const { installExternalPlugin } = await import('../plugins/external.js');
19
- const plugin = await installExternalPlugin(url);
32
+ const plugin = await installExternalPlugin(url, { directory });
20
33
  console.log(`Installed plugin ${plugin.id} from ${plugin.packageName} at ${plugin.commit}`);
21
34
  return;
22
35
  }
@@ -2,7 +2,7 @@ export function usage() {
2
2
  console.log(`Usage:
3
3
  knl core [folder] [--host <host>] [--port <port>] [--api-only]
4
4
  kennel init [path] [--plugin <id>] [--force] [--list]
5
- kennel plugin add <git-repository-url>
5
+ kennel plugin add <git-repository-url> [--path <subdirectory>]
6
6
  kennel core-folders [path] [--json]
7
7
  kennel [folder] [--host <host>] [--port <port>] [--lan|--tailscale]
8
8
  kennel pop|p <file|folder> [--open] [--watch] [--host <host>] [--port <port>] [--lan|--tailscale]
@@ -45,6 +45,7 @@ export async function core(args) {
45
45
  throw new Error("Web assets missing; build the CLI or use --api-only");
46
46
  process.env.KENNEL_KERNEL_KEY = kernel.key;
47
47
  process.env.KENNEL_EXTERNAL_SERVER_ENTRIES = JSON.stringify(kernel.serverEntries);
48
+ process.env.KENNEL_EXTERNAL_API_ENTRIES = JSON.stringify(kernel.apiEntries);
48
49
  const api = createKennelApi({
49
50
  root,
50
51
  host,
@@ -22,7 +22,7 @@ function parseArgs(args) {
22
22
  else if (arg === '--plugin') {
23
23
  const value = args[index + 1];
24
24
  if (!value)
25
- throw new Error('--plugin requires a plugin id (tasks, calendar)');
25
+ throw new Error('--plugin requires a plugin id');
26
26
  options.plugin = value;
27
27
  index += 1;
28
28
  }
@@ -41,11 +41,11 @@ function initUsage() {
41
41
  return `Usage:
42
42
  kennel init [path] [--plugin <id>] [--force] [--list]
43
43
 
44
- Scaffold starter content files for folder plugins (todo.json, calendar.json)
45
- into the given folder (default: current directory). Existing files are left
46
- untouched unless --force is passed.
44
+ Scaffold starter content files for installed folder plugins into the given
45
+ folder (default: current directory). Existing files are left untouched unless
46
+ --force is passed.
47
47
 
48
- --plugin <id> only scaffold one plugin (tasks, calendar)
48
+ --plugin <id> only scaffold one plugin
49
49
  --force overwrite existing starter files
50
50
  --list show which files each plugin would create, without writing`;
51
51
  }
@@ -4,6 +4,7 @@ export type ExternalPluginEntry = {
4
4
  commit: string;
5
5
  packageName: string;
6
6
  id: string;
7
+ directory?: string;
7
8
  trigger?: string;
8
9
  entries: {
9
10
  client: string;
@@ -12,13 +13,19 @@ export type ExternalPluginEntry = {
12
13
  serverSymbol: string;
13
14
  manifest: string;
14
15
  manifestSymbol: string;
16
+ api?: string;
17
+ apiSymbol?: string;
15
18
  css?: string;
16
19
  };
17
20
  };
18
21
  export declare function kennelConfigPath(): string;
19
- export declare function validateExternalPlugin(inputUrl: string, existing?: ExternalPluginEntry[]): Promise<ExternalPluginEntry>;
22
+ export declare function validateExternalPlugin(inputUrl: string, existing?: ExternalPluginEntry[], options?: {
23
+ directory?: string;
24
+ }): Promise<ExternalPluginEntry>;
20
25
  export declare function readExternalPlugins(): ExternalPluginEntry[];
21
- export declare function installExternalPlugin(url: string): Promise<ExternalPluginEntry>;
26
+ export declare function installExternalPlugin(url: string, options?: {
27
+ directory?: string;
28
+ }): Promise<ExternalPluginEntry>;
22
29
  export declare function kernelKey(plugins?: ExternalPluginEntry[]): string;
23
30
  export type ActiveKernel = {
24
31
  buildIdentity: string;
@@ -32,5 +39,24 @@ export type ActiveKernel = {
32
39
  symbol: string;
33
40
  trigger?: string;
34
41
  }>;
42
+ apiEntries: Array<{
43
+ id: string;
44
+ module: string;
45
+ symbol: string;
46
+ }>;
35
47
  };
48
+ export declare function prepareExternalPluginModules(temp: string, target?: string, plugins?: ExternalPluginEntry[]): Promise<{
49
+ clientModule: string;
50
+ serverEntries: {
51
+ id: string;
52
+ module: string;
53
+ symbol: string;
54
+ trigger?: string;
55
+ }[];
56
+ apiEntries: {
57
+ id: string;
58
+ module: string;
59
+ symbol: string;
60
+ }[];
61
+ }>;
36
62
  export declare function ensureKernel(plugins?: ExternalPluginEntry[]): Promise<ActiveKernel>;
@@ -15,10 +15,10 @@ import { pathToFileURL, fileURLToPath } from "node:url";
15
15
  import { spawnSync } from "node:child_process";
16
16
  const CONFIG_FILE = join("kennel", "config.json");
17
17
  const VALID_ID = /^[a-z][a-z0-9-]*$/u;
18
- const CORE_IDS = new Set(["agents", "calendar", "mail", "notes", "projects", "tasks"]);
18
+ const CORE_IDS = new Set(["agents", "notes"]);
19
19
  const KENNEL_KERNEL_SCHEMA = 2;
20
20
  const BUILD_RUNTIME = `node-${process.versions.node}`;
21
- const BUILD_IDENTITY = "kennel-external-kernel-v2";
21
+ const BUILD_IDENTITY = "kennel-external-kernel-v3";
22
22
  function xdgConfigHome() {
23
23
  return process.env.XDG_CONFIG_HOME?.trim() || join(homedir(), ".config");
24
24
  }
@@ -103,6 +103,19 @@ function sourceCheckout(url, commit) {
103
103
  run("git", ["checkout", "--force", commit], { cwd: dir });
104
104
  return realpathSync(dir);
105
105
  }
106
+ function pluginRoot(repoRoot, directory) {
107
+ if (!directory)
108
+ return repoRoot;
109
+ if (isAbsolute(directory) || directory.includes("\0"))
110
+ throw new Error(`Unsafe plugin directory: ${directory}`);
111
+ const target = resolve(repoRoot, directory);
112
+ const rel = relative(repoRoot, target);
113
+ if (rel === "" || rel.startsWith("..") || isAbsolute(rel))
114
+ throw new Error(`Unsafe plugin directory: ${directory}`);
115
+ if (!existsSync(target) || !statSync(target).isDirectory())
116
+ throw new Error(`Missing plugin directory: ${directory}`);
117
+ return target;
118
+ }
106
119
  function packageExportPath(exportsValue, key) {
107
120
  if (!exportsValue || typeof exportsValue !== "object" || Array.isArray(exportsValue))
108
121
  return undefined;
@@ -150,16 +163,12 @@ function internalSourceAliases(root = kernelSourceRoot()) {
150
163
  const aliases = {};
151
164
  for (const [name, path] of Object.entries({
152
165
  "@raggle-ai/agents": "packages/agents/src",
153
- "@raggle-ai/calendar": "plugins/calendar/src",
154
166
  "@raggle-ai/folder-plugin": "packages/folder-plugin/src",
155
167
  "@raggle-ai/kennel-api": "packages/api/src",
156
- "@raggle-ai/mail": "plugins/mail/src",
157
168
  "@raggle-ai/markdown": "packages/markdown/src",
158
169
  "@raggle-ai/notes": "packages/notes/src",
159
- "@raggle-ai/projects": "plugins/projects/src",
160
170
  "@raggle-ai/schemas": "packages/schemas/src",
161
171
  "@raggle-ai/session-finding": "packages/session-finding/src",
162
- "@raggle-ai/tasks": "plugins/tasks/src",
163
172
  "@raggle-ai/ui": "packages/ui/src",
164
173
  "kennel-client": "packages/api-client/src",
165
174
  })) {
@@ -188,7 +197,7 @@ function resolveAliasPath(target, suffix) {
188
197
  }
189
198
  function esbuildAliasPlugin(root = kernelSourceRoot()) {
190
199
  const sourceAliases = internalSourceAliases(root);
191
- const hostPackages = ["@raggle-ai/barkdown", "@raggle-ai/scout-ui", "@tanstack/react-query", "@tanstack/react-router", "lucide-react", "react", "react-dom", "react/jsx-runtime", "yaml", "lexical"];
200
+ const hostPackages = ["@raggle-ai/barkdown", "@raggle-ai/scout-ui", "@tanstack/react-query", "@tanstack/react-router", "date-fns", "effect", "lucide-react", "react", "react-dom", "react/jsx-runtime", "yaml", "lexical"];
192
201
  return {
193
202
  name: "kennel-host-resolution",
194
203
  setup(build) {
@@ -241,9 +250,12 @@ async function validateImports(entry) {
241
250
  const manifestOut = join(dir, "manifest.mjs");
242
251
  const serverOut = join(dir, "server.mjs");
243
252
  const clientOut = join(dir, "client.mjs");
253
+ const apiOut = join(dir, "api.mjs");
244
254
  await bundleForImport(entry.entries.manifest, manifestOut, "browser");
245
255
  await bundleForImport(entry.entries.server, serverOut, "node");
246
256
  await bundleForImport(entry.entries.client, clientOut, "node");
257
+ if (entry.entries.api)
258
+ await bundleForImport(entry.entries.api, apiOut, "node");
247
259
  const manifestModule = await import(__rewriteRelativeImportExtension(pathToFileURL(manifestOut).href));
248
260
  const serverModule = await import(__rewriteRelativeImportExtension(pathToFileURL(serverOut).href));
249
261
  const clientModule = await import(__rewriteRelativeImportExtension(pathToFileURL(clientOut).href));
@@ -260,15 +272,22 @@ async function validateImports(entry) {
260
272
  throw new Error("client id mismatch");
261
273
  if (typeof client.component !== "function")
262
274
  throw new Error("client export missing component");
275
+ if (entry.entries.api && entry.entries.apiSymbol) {
276
+ const apiModule = await import(__rewriteRelativeImportExtension(pathToFileURL(apiOut).href));
277
+ if (typeof apiModule[entry.entries.apiSymbol] !== "function")
278
+ throw new Error("API export missing handler");
279
+ }
263
280
  }
264
281
  finally {
265
282
  await rm(dir, { force: true, recursive: true });
266
283
  }
267
284
  }
268
- export async function validateExternalPlugin(inputUrl, existing = []) {
285
+ export async function validateExternalPlugin(inputUrl, existing = [], options = {}) {
269
286
  const { url, requestedRef } = splitRepositoryUrl(inputUrl);
270
287
  const commit = resolveCommit(url, requestedRef);
271
- const root = sourceCheckout(url, commit);
288
+ const checkoutRoot = sourceCheckout(url, commit);
289
+ const directory = options.directory?.trim() || undefined;
290
+ const root = pluginRoot(checkoutRoot, directory);
272
291
  const pkgPath = join(root, "package.json");
273
292
  if (!existsSync(pkgPath))
274
293
  throw new Error("Plugin repository has no package.json at its root");
@@ -277,8 +296,6 @@ export async function validateExternalPlugin(inputUrl, existing = []) {
277
296
  const metadata = pkg.kennel?.plugin;
278
297
  if (!metadata || typeof metadata !== "object")
279
298
  throw new Error("package.json must define kennel.plugin metadata");
280
- if (!metadata.exports || typeof metadata.exports !== "object")
281
- throw new Error("kennel.plugin.exports is required");
282
299
  const id = stringField(metadata.id, "plugin id");
283
300
  if (!VALID_ID.test(id))
284
301
  throw new Error(`Invalid plugin id: ${id}`);
@@ -293,7 +310,16 @@ export async function validateExternalPlugin(inputUrl, existing = []) {
293
310
  const client = safeRelativeFile(root, packageExportPath(exportsValue, "./client"), "./client package export");
294
311
  const server = safeRelativeFile(root, packageExportPath(exportsValue, "./server"), "./server package export");
295
312
  const manifest = safeRelativeFile(root, packageExportPath(exportsValue, "./manifest"), "./manifest package export");
296
- const cssValue = metadata.exports.css;
313
+ const apiPath = packageExportPath(exportsValue, "./api");
314
+ const apiExport = apiPath
315
+ ? safeRelativeFile(root, apiPath, "./api package export")
316
+ : undefined;
317
+ const apiSymbol = apiExport
318
+ ? typeof metadata.exports?.apiSymbol === "string"
319
+ ? metadata.exports.apiSymbol
320
+ : "default"
321
+ : undefined;
322
+ const cssValue = metadata.exports?.css;
297
323
  const css = cssValue === undefined ? undefined : safeRelativeFile(root, cssValue, "css export path");
298
324
  const entry = {
299
325
  url,
@@ -301,14 +327,22 @@ export async function validateExternalPlugin(inputUrl, existing = []) {
301
327
  commit,
302
328
  packageName,
303
329
  id,
330
+ ...(directory ? { directory } : {}),
304
331
  ...(trigger ? { trigger } : {}),
305
332
  entries: {
306
333
  client,
307
- clientSymbol: stringField(metadata.exports.clientSymbol, "client export symbol"),
334
+ clientSymbol: typeof metadata.exports?.clientSymbol === "string"
335
+ ? metadata.exports.clientSymbol
336
+ : "default",
308
337
  server,
309
- serverSymbol: stringField(metadata.exports.serverSymbol, "server export symbol"),
338
+ serverSymbol: typeof metadata.exports?.serverSymbol === "string"
339
+ ? metadata.exports.serverSymbol
340
+ : "default",
310
341
  manifest,
311
- manifestSymbol: stringField(metadata.exports.manifestSymbol, "manifest export symbol"),
342
+ manifestSymbol: typeof metadata.exports?.manifestSymbol === "string"
343
+ ? metadata.exports.manifestSymbol
344
+ : "default",
345
+ ...(apiExport ? { api: apiExport, apiSymbol } : {}),
312
346
  ...(css ? { css } : {}),
313
347
  },
314
348
  };
@@ -319,13 +353,13 @@ export function readExternalPlugins() {
319
353
  const config = readJson(kennelConfigPath());
320
354
  return Array.isArray(config.externalPlugins) ? config.externalPlugins : [];
321
355
  }
322
- export async function installExternalPlugin(url) {
356
+ export async function installExternalPlugin(url, options = {}) {
323
357
  const path = kennelConfigPath();
324
358
  const config = readJson(path);
325
359
  const externalPlugins = Array.isArray(config.externalPlugins) ? config.externalPlugins : [];
326
360
  let entry;
327
361
  try {
328
- entry = await validateExternalPlugin(url, externalPlugins);
362
+ entry = await validateExternalPlugin(url, externalPlugins, options);
329
363
  const nextPlugins = [...externalPlugins, entry];
330
364
  await ensureKernel(nextPlugins);
331
365
  writeJsonAtomic(path, { ...config, externalPlugins: nextPlugins });
@@ -349,6 +383,7 @@ export function kernelKey(plugins = readExternalPlugins()) {
349
383
  requestedRef: plugin.requestedRef ?? null,
350
384
  packageName: plugin.packageName,
351
385
  id: plugin.id,
386
+ directory: plugin.directory ?? null,
352
387
  commit: plugin.commit,
353
388
  trigger: plugin.trigger,
354
389
  entries: plugin.entries,
@@ -369,7 +404,9 @@ async function readKernelMarker(marker, key) {
369
404
  kernel.key !== key ||
370
405
  !existsSync(resolve(kernel.webRoot, "index.html")) ||
371
406
  !Array.isArray(kernel.serverEntries) ||
372
- kernel.serverEntries.some((entry) => !entry.id || !entry.module || !entry.symbol || !existsSync(entry.module)))
407
+ kernel.serverEntries.some((entry) => !entry.id || !entry.module || !entry.symbol || !existsSync(entry.module)) ||
408
+ !Array.isArray(kernel.apiEntries) ||
409
+ kernel.apiEntries.some((entry) => !entry.id || !entry.module || !entry.symbol || !existsSync(entry.module)))
373
410
  return undefined;
374
411
  return kernel;
375
412
  }
@@ -404,8 +441,7 @@ function moveIncompleteAside(target) {
404
441
  renameSync(target, broken);
405
442
  rmSync(broken, { force: true, recursive: true });
406
443
  }
407
- async function buildKernelTemp(temp, target, key, plugins) {
408
- const sourceRoot = kernelSourceRoot();
444
+ export async function prepareExternalPluginModules(temp, target = temp, plugins = readExternalPlugins()) {
409
445
  const clientModule = join(temp, "external-plugins.tsx");
410
446
  const serverDir = join(temp, "server");
411
447
  mkdirSync(serverDir, { recursive: true });
@@ -414,16 +450,29 @@ async function buildKernelTemp(temp, target, key, plugins) {
414
450
  const clientItems = plugins.map((plugin, index) => ` { ...manifest${index}, component: lazy(async () => ({ default: (await import(${JSON.stringify(plugin.entries.client)}))[${JSON.stringify(plugin.entries.clientSymbol)}].component })) }`).join(",\n");
415
451
  await writeFile(clientModule, `import { lazy } from "react";\nimport type { FolderPluginClient } from "@raggle-ai/folder-plugin/client";\n${cssImports}\n${clientImports}\nexport const externalFolderPlugins: FolderPluginClient[] = [\n${clientItems}\n];\n`);
416
452
  const serverEntries = [];
453
+ const apiEntries = [];
417
454
  for (const plugin of plugins) {
418
455
  const outfile = join(serverDir, `${plugin.id}.js`);
419
456
  await bundleForImport(plugin.entries.server, outfile, "node");
420
457
  serverEntries.push({ id: plugin.id, module: join(target, "server", `${plugin.id}.js`), symbol: plugin.entries.serverSymbol, trigger: plugin.trigger });
458
+ if (plugin.entries.api && plugin.entries.apiSymbol) {
459
+ const apiOutfile = join(serverDir, `${plugin.id}-api.js`);
460
+ await bundleForImport(plugin.entries.api, apiOutfile, "node");
461
+ apiEntries.push({ id: plugin.id, module: join(target, "server", `${plugin.id}-api.js`), symbol: plugin.entries.apiSymbol });
462
+ }
421
463
  }
464
+ return { clientModule, serverEntries, apiEntries };
465
+ }
466
+ async function buildKernelTemp(temp, target, key, plugins) {
467
+ const sourceRoot = kernelSourceRoot();
468
+ const { clientModule, serverEntries, apiEntries } = await prepareExternalPluginModules(temp, target, plugins);
422
469
  const vite = await import("vite");
423
470
  const previousClientModule = process.env.KENNEL_EXTERNAL_CLIENT_MODULE;
424
471
  const previousSourceRoot = process.env.KENNEL_KERNEL_SOURCE_ROOT;
472
+ const previousHostNodeModules = process.env.KENNEL_HOST_NODE_MODULES;
425
473
  process.env.KENNEL_EXTERNAL_CLIENT_MODULE = clientModule;
426
474
  process.env.KENNEL_KERNEL_SOURCE_ROOT = sourceRoot;
475
+ process.env.KENNEL_HOST_NODE_MODULES = resolve(cliRoot(), "node_modules");
427
476
  try {
428
477
  await vite.build({
429
478
  configFile: resolve(sourceRoot, "apps/web/vite.config.ts"),
@@ -442,6 +491,10 @@ async function buildKernelTemp(temp, target, key, plugins) {
442
491
  delete process.env.KENNEL_KERNEL_SOURCE_ROOT;
443
492
  else
444
493
  process.env.KENNEL_KERNEL_SOURCE_ROOT = previousSourceRoot;
494
+ if (previousHostNodeModules === undefined)
495
+ delete process.env.KENNEL_HOST_NODE_MODULES;
496
+ else
497
+ process.env.KENNEL_HOST_NODE_MODULES = previousHostNodeModules;
445
498
  }
446
499
  const kernel = {
447
500
  buildIdentity: BUILD_IDENTITY,
@@ -450,6 +503,7 @@ async function buildKernelTemp(temp, target, key, plugins) {
450
503
  key,
451
504
  webRoot: join(target, "web"),
452
505
  serverEntries,
506
+ apiEntries,
453
507
  };
454
508
  await writeFile(join(temp, "kernel.json"), JSON.stringify(kernel, null, 2));
455
509
  return kernel;
@@ -457,7 +511,7 @@ async function buildKernelTemp(temp, target, key, plugins) {
457
511
  export async function ensureKernel(plugins = readExternalPlugins()) {
458
512
  if (plugins.length === 0) {
459
513
  const webRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../../web");
460
- return { buildIdentity: BUILD_IDENTITY, schema: KENNEL_KERNEL_SCHEMA, runtime: BUILD_RUNTIME, key: "core", webRoot, serverEntries: [] };
514
+ return { buildIdentity: BUILD_IDENTITY, schema: KENNEL_KERNEL_SCHEMA, runtime: BUILD_RUNTIME, key: "core", webRoot, serverEntries: [], apiEntries: [] };
461
515
  }
462
516
  const key = kernelKey(plugins);
463
517
  const target = kernelRoot(key);
@@ -18,13 +18,8 @@ export type { FolderPluginContext, FolderPluginData, FolderPluginDetection, Fold
18
18
  export declare class FolderPluginFailure extends Error {
19
19
  constructor(message: string);
20
20
  }
21
- export declare function handleMailApiRoutes(request: import("node:http").IncomingMessage, response: import("node:http").ServerResponse, context: {
22
- authorizeFolder: (value: string | null) => string;
23
- mailDir?: string;
24
- watch: (folder: string) => void;
25
- }): Promise<boolean>;
26
21
  export declare function folderServerRegistry(options?: {
27
- mailDir?: string;
22
+ agentsHomeDir?: string;
28
23
  }): Map<string, FolderPluginServer>;
29
24
  export type FolderPluginScaffoldFile = {
30
25
  plugin: string;
@@ -50,5 +45,5 @@ export type FolderPluginScaffoldResult = {
50
45
  export declare function scaffoldFolderPlugins(folder: string, options?: {
51
46
  force?: boolean;
52
47
  write?: boolean;
53
- mailDir?: string;
48
+ agentsHomeDir?: string;
54
49
  }): Promise<FolderPluginScaffoldResult>;
@@ -313,6 +313,7 @@ export async function viewer(input) {
313
313
  }
314
314
  process.env.KENNEL_KERNEL_KEY = kernel.key;
315
315
  process.env.KENNEL_EXTERNAL_SERVER_ENTRIES = JSON.stringify(kernel.serverEntries);
316
+ process.env.KENNEL_EXTERNAL_API_ENTRIES = JSON.stringify(kernel.apiEntries);
316
317
  const api = createKennelApi({
317
318
  root: options.root,
318
319
  host: options.host,
package/dist/cli/usage.js CHANGED
@@ -2,7 +2,7 @@ export function usage() {
2
2
  console.log(`Usage:
3
3
  knl core [folder] [--host <host>] [--port <port>] [--api-only]
4
4
  kennel init [path] [--plugin <id>] [--force] [--list]
5
- kennel plugin add <git-repository-url>
5
+ kennel plugin add <git-repository-url> [--path <subdirectory>]
6
6
  kennel core-folders [path] [--json]
7
7
  kennel [folder] [--host <host>] [--port <port>] [--lan|--tailscale]
8
8
  kennel pop|p <file|folder> [--open] [--watch] [--host <host>] [--port <port>] [--lan|--tailscale]
@@ -45,6 +45,7 @@ export async function core(args) {
45
45
  throw new Error("Web assets missing; build the CLI or use --api-only");
46
46
  process.env.KENNEL_KERNEL_KEY = kernel.key;
47
47
  process.env.KENNEL_EXTERNAL_SERVER_ENTRIES = JSON.stringify(kernel.serverEntries);
48
+ process.env.KENNEL_EXTERNAL_API_ENTRIES = JSON.stringify(kernel.apiEntries);
48
49
  const api = createKennelApi({
49
50
  root,
50
51
  host,
package/dist/core/init.js CHANGED
@@ -22,7 +22,7 @@ function parseArgs(args) {
22
22
  else if (arg === '--plugin') {
23
23
  const value = args[index + 1];
24
24
  if (!value)
25
- throw new Error('--plugin requires a plugin id (tasks, calendar)');
25
+ throw new Error('--plugin requires a plugin id');
26
26
  options.plugin = value;
27
27
  index += 1;
28
28
  }
@@ -41,11 +41,11 @@ function initUsage() {
41
41
  return `Usage:
42
42
  kennel init [path] [--plugin <id>] [--force] [--list]
43
43
 
44
- Scaffold starter content files for folder plugins (todo.json, calendar.json)
45
- into the given folder (default: current directory). Existing files are left
46
- untouched unless --force is passed.
44
+ Scaffold starter content files for installed folder plugins into the given
45
+ folder (default: current directory). Existing files are left untouched unless
46
+ --force is passed.
47
47
 
48
- --plugin <id> only scaffold one plugin (tasks, calendar)
48
+ --plugin <id> only scaffold one plugin
49
49
  --force overwrite existing starter files
50
50
  --list show which files each plugin would create, without writing`;
51
51
  }