mulmoterminal 4.18.0 → 4.19.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 (154) hide show
  1. package/README.md +36 -3
  2. package/common/sessionCollection.ts +37 -0
  3. package/dist/assets/{AllPackages-CF2GkZ5g-BpghxJjj.js → AllPackages-CF2GkZ5g-719DMhy9.js} +1 -1
  4. package/dist/assets/{BaseConfiguration-CAwZOAki-WQURtaX1.js → BaseConfiguration-CAwZOAki-BNy_xNjy.js} +1 -1
  5. package/dist/assets/{Element-BMI7Nj5w-CcDgA_9-.js → Element-BMI7Nj5w-Bgf4crSD.js} +1 -1
  6. package/dist/assets/{Entities-C8p_0jCn-DRWzxsVw.js → Entities-C8p_0jCn-CWllzfNC.js} +1 -1
  7. package/dist/assets/{FunctionList-YWk54TCy-BrIR4n-1.js → FunctionList-YWk54TCy-DaTQdq82.js} +1 -1
  8. package/dist/assets/{InputJax-C5dj-ntL-AT5iU-td.js → InputJax-C5dj-ntL-oeHc0QdR.js} +1 -1
  9. package/dist/assets/{MathItem-YJvQL-XJ-CxJPVleP.js → MathItem-YJvQL-XJ-Dn-AIoGc.js} +1 -1
  10. package/dist/assets/{MmlFactory-DuXYIgx8-Ey_YXuDi.js → MmlFactory-DuXYIgx8-B1mG0lo8.js} +1 -1
  11. package/dist/assets/{Options-oARQeeuT-BZ9bNEz5.js → Options-oARQeeuT-DbzO_1MB.js} +1 -1
  12. package/dist/assets/{OutputJax-DfUZNNCu-De4Z1Pn_.js → OutputJax-DfUZNNCu-CyrSbke3.js} +1 -1
  13. package/dist/assets/{PrioritizedList-6lun1Xqd-BTQmhniB.js → PrioritizedList-6lun1Xqd-BQNzlLGy.js} +1 -1
  14. package/dist/assets/{Styles-BPXeoqzi-Cwo9PIXj.js → Styles-BPXeoqzi-BKeQseQE.js} +1 -1
  15. package/dist/assets/{TeXAtom-LHT3KFWH-B58fWn67.js → TeXAtom-LHT3KFWH-B3Le3Jpe.js} +1 -1
  16. package/dist/assets/{abnfDiagram-VCTEODGH-DoYNjdBB-N4p9eIcR.js → abnfDiagram-VCTEODGH-DoYNjdBB-KmIwH33y.js} +1 -1
  17. package/dist/assets/{arc-CqByPKkF-o90vYcFT.js → arc-CqByPKkF-CHMYwO1F.js} +1 -1
  18. package/dist/assets/architecture-7GRP2DOG-CRS69XmP-C7E5h_KS.js +1 -0
  19. package/dist/assets/{architectureDiagram-5GKGNRK7-BhcT6qS5-y2WkXlFP.js → architectureDiagram-5GKGNRK7-BhcT6qS5-BSNEVHo1.js} +1 -1
  20. package/dist/assets/{assistive-mml-DXJXho4o-DHpoehaR.js → assistive-mml-DXJXho4o-DUJ8w9mu.js} +1 -1
  21. package/dist/assets/{blockDiagram-I7D4REHJ-1Cng0Q4K-BDINYHUk.js → blockDiagram-I7D4REHJ-1Cng0Q4K-CniilI55.js} +1 -1
  22. package/dist/assets/{c4Diagram-7LVT6UL2-CAb9c8nc-BtCR-OQb.js → c4Diagram-7LVT6UL2-CAb9c8nc-CPV-jYrO.js} +1 -1
  23. package/dist/assets/channel-BjESmYnj-rP_lgCcy.js +1 -0
  24. package/dist/assets/{chunk-4HAMMTFA-ChwfIAnF-BoqlitDw.js → chunk-4HAMMTFA-ChwfIAnF-CT2-h6Ex.js} +1 -1
  25. package/dist/assets/{chunk-75Z2AOVW-CbPA0Zt_-sG1wziTf.js → chunk-75Z2AOVW-CbPA0Zt_-lNRmF0qT.js} +1 -1
  26. package/dist/assets/chunk-DU6HZSFF-DuOx2LFX-Bj3yP0uT.js +125 -0
  27. package/dist/assets/{chunk-F27PBJKO-CgBMw9yN-BIA-Rq1B.js → chunk-F27PBJKO-CgBMw9yN-BWp9dfKX.js} +1 -1
  28. package/dist/assets/{chunk-GMAD6QVW-JTqlimUX-B7VyMMki.js → chunk-GMAD6QVW-JTqlimUX-DR52xCzD.js} +3 -3
  29. package/dist/assets/{chunk-GVQU2GXP-D6ccB4DO-CxN0Y161.js → chunk-GVQU2GXP-D6ccB4DO-mk0mCcWD.js} +1 -1
  30. package/dist/assets/{chunk-IMKFNOWR-ij1DSzMb-Cp5MHDVx.js → chunk-IMKFNOWR-ij1DSzMb-DPawHWcf.js} +1 -1
  31. package/dist/assets/{chunk-L3NEJ4N5-CUoAQVG2-Cq8hXkjf.js → chunk-L3NEJ4N5-CUoAQVG2-CNiXsjSR.js} +1 -1
  32. package/dist/assets/{chunk-OSK3NFVY-_VNbXQSu-CLHHccp_.js → chunk-OSK3NFVY-_VNbXQSu-Sf30gNqd.js} +1 -1
  33. package/dist/assets/{chunk-P2QGCYS3-B8lzOn3Y-9R8JiTOW.js → chunk-P2QGCYS3-B8lzOn3Y-YyA4x0uW.js} +1 -1
  34. package/dist/assets/{chunk-POPQ4Y6H-Bh_uOTmp-IIk4SISs.js → chunk-POPQ4Y6H-Bh_uOTmp-CdGEii9l.js} +1 -1
  35. package/dist/assets/{chunk-PWAF6VOD-DzjnfYSw-FXKbHA4z.js → chunk-PWAF6VOD-DzjnfYSw-DTqC2CLs.js} +1 -1
  36. package/dist/assets/{chunk-SHT3W25Y-B8dQLS5w-asO6U825.js → chunk-SHT3W25Y-B8dQLS5w-BJNSSgyk.js} +1 -1
  37. package/dist/assets/{chunk-SVP7TREG-B6A-T8Th-C_31sNJS.js → chunk-SVP7TREG-B6A-T8Th-Dzxcsjuk.js} +1 -1
  38. package/dist/assets/{chunk-TICWLB2K-C1kwD29l-De2Aa9yO.js → chunk-TICWLB2K-C1kwD29l-DeQq0v2D.js} +1 -1
  39. package/dist/assets/{chunk-XXDRQBXY-vg0kfC73-MJrwfLy3.js → chunk-XXDRQBXY-vg0kfC73-C1pQQOE8.js} +1 -1
  40. package/dist/assets/classDiagram-ZZMXUADV-C7gP-pUH-HlEMT_fM.js +1 -0
  41. package/dist/assets/classDiagram-v2-VYDZK3BY-CUwV5k1F-HlEMT_fM.js +1 -0
  42. package/dist/assets/{cose-bilkent-JH36ORCC-NuHCtE3P-CBmhuRye.js → cose-bilkent-JH36ORCC-NuHCtE3P-cyZ1urQU.js} +1 -1
  43. package/dist/assets/cynefin-OW5HDTMX-C4iKivN4-BdoGTvu9.js +1 -0
  44. package/dist/assets/{cynefinDiagram-5FMLGOSQ-CA7sro34-C7EC0rCC.js → cynefinDiagram-5FMLGOSQ-CA7sro34-CrhjxarD.js} +1 -1
  45. package/dist/assets/{dagre-GXQ25YYZ-DOztjUR_-DUYDKcad.js → dagre-GXQ25YYZ-DOztjUR_-6r31tr6a.js} +1 -1
  46. package/dist/assets/{diagram-S7CK7UJ4-D_nsLfRT-6xfPNGOi.js → diagram-S7CK7UJ4-D_nsLfRT-vhfbHm8V.js} +1 -1
  47. package/dist/assets/{diagram-UQ7AKVKN-DNN-YX9a-DabWPcsA.js → diagram-UQ7AKVKN-DNN-YX9a-DT1QxfYf.js} +1 -1
  48. package/dist/assets/{diagram-VSXAHHWV--HENzo-l-0O7qAbYx.js → diagram-VSXAHHWV--HENzo-l-D0htjBwe.js} +1 -1
  49. package/dist/assets/{diagram-VX7I27RA-m2m9dROj-DSsL6lbk.js → diagram-VX7I27RA-m2m9dROj-C0DD_R_R.js} +1 -1
  50. package/dist/assets/{diagram-Z3DM3KII-D4qpv4-B-x5aaLfdn.js → diagram-Z3DM3KII-D4qpv4-B-DkwV0mqd.js} +1 -1
  51. package/dist/assets/{dist-KHYYM69R.js → dist-DI2zc2Jw.js} +2 -2
  52. package/dist/assets/{dist-to-wCxn9.js → dist-DYsqEais.js} +2 -2
  53. package/dist/assets/{dist-DeiyD9Ki-CyYR8D-0.js → dist-DeiyD9Ki-BDkUFZzb.js} +1 -1
  54. package/dist/assets/{dist-CI0Sz8VW.js → dist-ktxf7OoX.js} +1 -1
  55. package/dist/assets/dist-yLpihYnu.js +9 -0
  56. package/dist/assets/{ebnfDiagram-PWID7BFC-CAbv3sZg-CzJDavSQ.js → ebnfDiagram-PWID7BFC-CAbv3sZg-wcFD2pOV.js} +1 -1
  57. package/dist/assets/{erDiagram-RLTQ6QDP-a10Ryh0--BfSvF1ta.js → erDiagram-RLTQ6QDP-a10Ryh0--DXsl0lf-.js} +1 -1
  58. package/dist/assets/eventmodeling-NTZA5JFV-DhqtNS8R-DoPRbV10.js +1 -0
  59. package/dist/assets/flowDiagram-HODETNUW-CAW_8mwY-Dic5M8sg.js +1 -0
  60. package/dist/assets/{ganttDiagram-EL5Y4UJY-Cb7leeOC-DKtB1NzV.js → ganttDiagram-EL5Y4UJY-Cb7leeOC-Zr45_Vfv.js} +1 -1
  61. package/dist/assets/gitGraph-4MIJSDKK-S_Zs6Nxs-Dga7HAMA.js +1 -0
  62. package/dist/assets/{gitGraphDiagram-WWUBYQGX-BCSbUpXG-DKX1wbps.js → gitGraphDiagram-WWUBYQGX-BCSbUpXG-NXTAdglA.js} +1 -1
  63. package/dist/assets/{html-DdQiKDqM-O0S29Dwr.js → html-DdQiKDqM-CWaTZmfg.js} +1 -1
  64. package/dist/assets/{index-yoMfkmrj.js → index-BLQmPGss.js} +440 -327
  65. package/dist/assets/index-ByDLkA7o.css +1 -0
  66. package/dist/assets/info-A6RAGUB7-4sGJh1is-CwJVaAGJ.js +1 -0
  67. package/dist/assets/{infoDiagram-27XIBGKW-BJRaZItN-q1dLBYbI.js → infoDiagram-27XIBGKW-BJRaZItN-bMt9nqLR.js} +1 -1
  68. package/dist/assets/{ishikawaDiagram-5VMMS53U-DHlFe__S-DEAMGQtX.js → ishikawaDiagram-5VMMS53U-DHlFe__S-DXurFn74.js} +1 -1
  69. package/dist/assets/{journeyDiagram-3NMN7TZE-BOIo3JM--BO_7tBTd.js → journeyDiagram-3NMN7TZE-BOIo3JM--BXeOgIb_.js} +1 -1
  70. package/dist/assets/{kanban-definition-UXKFOSKX-yrQdG683-Bx4it8pk.js → kanban-definition-UXKFOSKX-yrQdG683-BzrY2WXE.js} +1 -1
  71. package/dist/assets/{lengths-CvmPfBid-BJ7XjTXv.js → lengths-CvmPfBid-CNFHBUYp.js} +1 -1
  72. package/dist/assets/{line-DUb1TjJS-DTQdqqNY.js → line-DUb1TjJS-Dvf7Rqiu.js} +1 -1
  73. package/dist/assets/{linear-xsuGWu5q-DAJY5eE1.js → linear-xsuGWu5q-Ff_lES8M.js} +1 -1
  74. package/dist/assets/{liteAdaptor-C0FQiOEx-CpU2hMwG.js → liteAdaptor-C0FQiOEx-DCcafR0T.js} +1 -1
  75. package/dist/assets/{mathjax-DVEo4UYj-DblCQqUM.js → mathjax-DVEo4UYj-c4jG0lBH.js} +1 -1
  76. package/dist/assets/{mermaid-parser.core-fkjeiYO7-xLW4or9n.js → mermaid-parser.core-fkjeiYO7-CrJQ0wkP.js} +2 -2
  77. package/dist/assets/{mermaid.core-CZDx2Cyn-BWO3dTDf.js → mermaid.core-CZDx2Cyn-CPykd7mo.js} +4 -4
  78. package/dist/assets/{mindmap-definition-YA3MSWOX-BpKAVyqs-BrJpjBKU.js → mindmap-definition-YA3MSWOX-BpKAVyqs-DvNc99DX.js} +1 -1
  79. package/dist/assets/{mo-CrlNnGXX-Eo4cINyg.js → mo-CrlNnGXX-jbjxEMp9.js} +1 -1
  80. package/dist/assets/packet-AYTQ26CC-MQQyx8fI-cYgi4Dr_.js +1 -0
  81. package/dist/assets/{pegDiagram-XKGWAZYB-C7eG_Ohl-CaXo4ojb.js → pegDiagram-XKGWAZYB-C7eG_Ohl-Cg6PUK-Z.js} +1 -1
  82. package/dist/assets/pie-WAS4IAKB-CyaL5i_d-H2W1K3UG.js +1 -0
  83. package/dist/assets/{pieDiagram-E7YTZNPT-5f9wSfDR-BwnQjyyW.js → pieDiagram-E7YTZNPT-5f9wSfDR-D7VVgN-E.js} +1 -1
  84. package/dist/assets/{quadrantDiagram-AXDQQJYC-mWeaOj5S-DvsMFOc9.js → quadrantDiagram-AXDQQJYC-mWeaOj5S-ymyyn1P8.js} +1 -1
  85. package/dist/assets/radar-RG4KPBEZ-DR-SsHDJ-CF6__0zI.js +1 -0
  86. package/dist/assets/railroad-74A4TZTK-C2gqsOGX-CBV1mz61.js +1 -0
  87. package/dist/assets/railroad-abnf-HS5TGJTU-Dpzw6P5u-BjUi3pLP.js +1 -0
  88. package/dist/assets/railroad-ebnf-LZEXJU2U-J_BuIrPo-C-VmCg_D.js +1 -0
  89. package/dist/assets/railroad-peg-WCYAUIDC-DzMStOR--CU9nQiuV.js +1 -0
  90. package/dist/assets/{railroadDiagram-O6MQD6OU-DJskhE7u-C_0njIFi.js → railroadDiagram-O6MQD6OU-DJskhE7u-D8GPF_N9.js} +1 -1
  91. package/dist/assets/{requirementDiagram-BXWQKSXE-B5E0bU4h-C5hnNnLY.js → requirementDiagram-BXWQKSXE-B5E0bU4h-D0u3p65T.js} +1 -1
  92. package/dist/assets/{sankeyDiagram-P5KCCOFB-DS3AOTai-pWFxLlmZ.js → sankeyDiagram-P5KCCOFB-DS3AOTai-G75qr__V.js} +1 -1
  93. package/dist/assets/{sequenceDiagram-WJ2MYXX4-Bn2L9osv-Qj-GBMA5.js → sequenceDiagram-WJ2MYXX4-Bn2L9osv-CbkN0mm6.js} +1 -1
  94. package/dist/assets/{src-CLC0ddSd-C6SesIb_.js → src-CLC0ddSd-C5t2_8AY.js} +1 -1
  95. package/dist/assets/{stateDiagram-D77RDMKH-DbtoW7HL-0tDoAFAn.js → stateDiagram-D77RDMKH-DbtoW7HL-DCtQ8Hp9.js} +1 -1
  96. package/dist/assets/stateDiagram-v2-MP3YSRHH-CX6RalKY-Immi7al4.js +1 -0
  97. package/dist/assets/{svg-CaHU_sxA-hUQUwI5e.js → svg-CaHU_sxA-DxGdXkDA.js} +1 -1
  98. package/dist/assets/{swimlanes-42K2YHIH-90h8w_3B-BIANSbUk.js → swimlanes-42K2YHIH-90h8w_3B-jEcDr8B6.js} +1 -1
  99. package/dist/assets/swimlanesDiagram-VR7AAH4N-49XH_TMr-NmglpqnQ.js +8 -0
  100. package/dist/assets/{tex-B1cONMvb-BuuMe8DF.js → tex-B1cONMvb-B8V9JDkf.js} +1 -1
  101. package/dist/assets/{timeline-definition-24CTP7MA-Bx3KcICO-uJwxqLxL.js → timeline-definition-24CTP7MA-Bx3KcICO-bsTEXbOL.js} +1 -1
  102. package/dist/assets/treeView-Q6P3EWNA-gFs854Sn-BiaE8FlP.js +1 -0
  103. package/dist/assets/treemap-WGGIJYW6-DGh_szUA-Cky-1FGm.js +1 -0
  104. package/dist/assets/{vennDiagram-4TSXK5OY-DSexNe_H-CEWVEpb7.js → vennDiagram-4TSXK5OY-DSexNe_H-BJbszjQ3.js} +1 -1
  105. package/dist/assets/wardley-WFR3VGLG-BVLYL3gB-mxq3nYIL.js +1 -0
  106. package/dist/assets/{wardleyDiagram-VM6X3IG4-DesYYyZW-7T-CCnI4.js → wardleyDiagram-VM6X3IG4-DesYYyZW-dxH0XcmN.js} +1 -1
  107. package/dist/assets/{xychartDiagram-S5SC5T6Z-dIt6pHWV-BWhy5WEU.js → xychartDiagram-S5SC5T6Z-dIt6pHWV-_kgbLFgL.js} +1 -1
  108. package/dist/index.html +2 -2
  109. package/package.json +6 -6
  110. package/server/backends/notifier.ts +15 -8
  111. package/server/backends/scheduler-adapter.ts +9 -4
  112. package/server/backends/scheduler-boot.ts +51 -0
  113. package/server/backends/scheduler.ts +17 -5
  114. package/server/backends/system-tasks.ts +16 -2
  115. package/server/config/app-config.ts +25 -0
  116. package/server/config/config-routes.ts +8 -0
  117. package/server/index.ts +8 -34
  118. package/server/infra/host-state-root.ts +39 -0
  119. package/server/infra/process-guards.ts +11 -5
  120. package/server/infra/tmux.ts +39 -5
  121. package/server/infra/workspace-key.ts +26 -0
  122. package/server/routes/plugin-routes.ts +13 -3
  123. package/server/routes/session-routes.ts +31 -2
  124. package/server/session/background-chat.ts +9 -0
  125. package/server/session/live-sessions.ts +31 -0
  126. package/server/session/registry.ts +61 -0
  127. package/server/session/scheduled-sessions.ts +2 -14
  128. package/server/session/session-collections.ts +69 -0
  129. package/server/session/spawn-collection.ts +64 -0
  130. package/server/skills/mulmoterminal-config/SKILL.md +26 -0
  131. package/dist/assets/architecture-7GRP2DOG-CRS69XmP-Dofb7uTe.js +0 -1
  132. package/dist/assets/channel-BjESmYnj-D2HJk1kK.js +0 -1
  133. package/dist/assets/chunk-DU6HZSFF-DuOx2LFX-jw2gw2WG.js +0 -125
  134. package/dist/assets/classDiagram-ZZMXUADV-C7gP-pUH-CTNdATck.js +0 -1
  135. package/dist/assets/classDiagram-v2-VYDZK3BY-CUwV5k1F-CTNdATck.js +0 -1
  136. package/dist/assets/cynefin-OW5HDTMX-C4iKivN4-BAbBOyvn.js +0 -1
  137. package/dist/assets/dist-BHbP5Rdy.js +0 -9
  138. package/dist/assets/eventmodeling-NTZA5JFV-DhqtNS8R-DZDQj3ay.js +0 -1
  139. package/dist/assets/flowDiagram-HODETNUW-CAW_8mwY-B4f7Dpo6.js +0 -1
  140. package/dist/assets/gitGraph-4MIJSDKK-S_Zs6Nxs-CZ6NmIpk.js +0 -1
  141. package/dist/assets/index-C1zBtRaC.css +0 -1
  142. package/dist/assets/info-A6RAGUB7-4sGJh1is-DIi5EBfj.js +0 -1
  143. package/dist/assets/packet-AYTQ26CC-MQQyx8fI-yAikr6bQ.js +0 -1
  144. package/dist/assets/pie-WAS4IAKB-CyaL5i_d-BIdTCQS6.js +0 -1
  145. package/dist/assets/radar-RG4KPBEZ-DR-SsHDJ-0JhYwnII.js +0 -1
  146. package/dist/assets/railroad-74A4TZTK-C2gqsOGX-C1zJ70Ow.js +0 -1
  147. package/dist/assets/railroad-abnf-HS5TGJTU-Dpzw6P5u-BMKd1LY4.js +0 -1
  148. package/dist/assets/railroad-ebnf-LZEXJU2U-J_BuIrPo-D5xXkaGL.js +0 -1
  149. package/dist/assets/railroad-peg-WCYAUIDC-DzMStOR--CTf0TsuO.js +0 -1
  150. package/dist/assets/stateDiagram-v2-MP3YSRHH-CX6RalKY-CyxuK80e.js +0 -1
  151. package/dist/assets/swimlanesDiagram-VR7AAH4N-49XH_TMr-nlZP2lTW.js +0 -8
  152. package/dist/assets/treeView-Q6P3EWNA-gFs854Sn-BDnUAqSd.js +0 -1
  153. package/dist/assets/treemap-WGGIJYW6-DGh_szUA-BcyHS0XZ.js +0 -1
  154. package/dist/assets/wardley-WFR3VGLG-BVLYL3gB-CTDrPm0c.js +0 -1
package/README.md CHANGED
@@ -598,7 +598,7 @@ the `claude` / `codex` sessions themselves.
598
598
  | `PORT` | `34567` | Backend HTTP/WebSocket port (prod: the URL you open). |
599
599
  | `CLIENT_PORT` | `6856` | Vite dev-server port (dev only: the URL you open with `yarn dev`). |
600
600
  | `CLAUDE_BIN` | `claude` | The Claude Code binary to spawn. On Windows a bare name is resolved on `PATH` before it reaches the PTY layer (which matches file names exactly): to the `.exe` when there is one, otherwise to the `.cmd` shim an npm-global install leaves, run through `cmd.exe`. |
601
- | `CLAUDE_CWD` | current dir | Working directory each `claude` PTY runs in; determines which project's sessions are listed. Via `npx mulmoterminal@latest` it defaults to the directory you ran the command from (override with `--cwd <dir>`, relative allowed); when the server is run directly it falls back to `~/mulmoclaude`. A value read from `.env` must be an absolute path (`~` is not expanded). |
601
+ | `CLAUDE_CWD` | current dir | Working directory each `claude` PTY runs in; determines which project's sessions are listed. Via `npx mulmoterminal@latest` it defaults to the directory you ran the command from (override with `--cwd <dir>`, relative allowed); when the server is run directly it falls back to `~/mulmoclaude`. A value read from `.env` must be an absolute path (`~` is not expanded). Running in one of your own project directories does **not** litter it — see the note under the table. |
602
602
  | `CLAUDE_PERMISSION_MODE` | `auto` | Permission mode passed to each `claude` spawn. |
603
603
  | `MT_TITLE_SOURCE` | `transcript` | Where the cell header's AI title comes from. `transcript` reads the title Claude Code writes into its own transcript — no extra process. `headless` restores the old behaviour of summarizing the recent turns with `claude -p`, which costs a model call but follows a session whose topic drifts (Claude's own title is written once and never revised). |
604
604
  | `MT_TITLE_MODEL` | `haiku` | Model used for the cell header's AI title. Only read when `MT_TITLE_SOURCE=headless`. Accepts a `--model` alias or a full model id. |
@@ -613,11 +613,30 @@ the `claude` / `codex` sessions themselves.
613
613
  | `GROK_HOME` | `~/.grok` | Grok home directory containing its per-directory session store. |
614
614
  | `MULMOTERMINAL_HOME` | `~/.mulmoterminal` | Root for managed **git worktrees**. |
615
615
  | `CLAUDE_CONFIG_DIR` | `~` | Claude Code's own config directory. `.claude.json` lives **inside** it, so relocating your Claude Code config moves that file too — MulmoTerminal reads it to tell whether the per-project GUI MCP server is registered (`server/infra/gui-mcp-registration.ts`). Leave it unset and `~/.claude.json` is used. |
616
- | `MULMOCLAUDE_WORKSPACE_PATH` | `~/mulmoclaude` | Where the managed MulmoClaude workspace lives. MulmoTerminal seeds presets/helps **only** into this directory, so launching in an arbitrary project never writes them there (`server/backends/workspaceSetup.ts`). Set it to the same value MulmoClaude uses. |
616
+ | `MULMOCLAUDE_WORKSPACE_PATH` | `~/mulmoclaude` | Where the managed MulmoClaude workspace lives. MulmoTerminal seeds presets/helps **only** into this directory, so launching in an arbitrary project never writes them there (`server/backends/workspaceSetup.ts`), and it is what decides where MulmoTerminal's own runtime state goes — see the note under the table. Set it to the same value MulmoClaude uses. |
617
617
  | `MULMOTERMINAL_NO_SKILL_INSTALL` | unset | Set to any value to skip installing the bundled skills (`mulmoterminal-config` and the `-dirs` / `-theme` / `-header` / `-keys` / `-model` / `-notify` / `-bug-report` / `-decisions` family) into `~/.claude/skills/` and the Codex skills root on startup. |
618
618
  | `GEMINI_IMAGE_MODEL` | `gemini-3.1-flash-image-preview` | Model used for image generation (needs `GEMINI_API_KEY`). The default is a **preview** model Google schedules for retirement around mid-2026, so pin a stable one here (e.g. `gemini-2.5-flash-image`) rather than waiting for a code change. |
619
619
  | `WAIT_REAP_GRACE_MS` | `1800000` | How long a **waiting** background session is kept before it's auto-reaped (`0` or negative = never). |
620
620
 
621
+ **Where MulmoTerminal's own runtime state goes.** The launcher defaults the workspace to the
622
+ directory you ran it from, which is usually one of your own projects — so the state MulmoTerminal
623
+ keeps for itself does not go there. The scheduler's execution state and logs
624
+ (`config/scheduler/state.json`, `data/scheduler/logs/`) and the notifier's
625
+ (`data/notifier/`) live under `~/.mulmoterminal/workspaces/<workspace-key>/` instead, one
626
+ directory per workspace — `<workspace-key>` is the workspace's path folded to a safe name plus a
627
+ short digest of it, so two workspaces never share one. What you made stays in the workspace either way: collections, feeds, and the
628
+ scheduled tasks you write in `config/scheduler/tasks.json`.
629
+
630
+ The one exception is the **managed** workspace named by `MULMOCLAUDE_WORKSPACE_PATH`
631
+ (`~/mulmoclaude` by default), where that state stays in the workspace — MulmoClaude reads the
632
+ same files there, and splitting them would give the two apps different answers.
633
+
634
+ If you ran an older version in a project directory, what it left behind is inert and nothing
635
+ recreates it — but delete the generated files, **not** the whole directory:
636
+ `config/scheduler/state.json`, `data/scheduler/`, `data/notifier/`. Leave
637
+ `config/scheduler/tasks.json` alone; that one is yours, it is still read from the workspace, and
638
+ deleting it deletes your scheduled tasks.
639
+
621
640
  The update-check opt-outs (`MULMOTERMINAL_NO_UPDATE_CHECK`, `NO_UPDATE_NOTIFIER`) are
622
641
  covered in [Install & run](#install--run).
623
642
 
@@ -655,6 +674,8 @@ The Settings modal (the gear button) persists per-user UI choices to `~/.mulmote
655
674
  | `pushKinds` | Which moments push: `"finished"` (a turn ended, ✅) and/or `"waiting"` (the agent stopped to ask — a permission prompt or a question, ❓, **once per prompt**). Omit to keep both; `[]` for none. A kind added in a later version stays off until you tick it. |
656
675
  | `worklogEnabled` | `true` to run the built-in **dev worklog** batch (see below). Off by default (each run spawns an LLM session, so it costs tokens). Editable in Settings → **Sessions and background tasks**. |
657
676
  | `worklogIntervalHours` | Worklog cadence in hours (default `6`, clamped to `1`–`168`). A stepper in the same Settings section covers the range. |
677
+ | `feedRefreshEnabled` | `false` stops the hourly **collection/feed refresh** (one scheduled task per root — the workspace and every saved project directory). **On by default**; only an explicit `false` turns it off, so an existing config keeps the behaviour it has. Takes effect at the next server start — the scheduler registers once at boot. Feeds still refresh on demand. Checkbox in Settings → **Sessions**. |
678
+ | `calendarSyncEnabled` | `false` stops the hourly **Google Calendar sync** (pulls changed events into collections that declare a calendar). Same default and the same restart rule as `feedRefreshEnabled`; calendar collections still sync on demand. Checkbox in the same Settings section. With both off and `worklogEnabled` off, no **built-in** task is registered. Your own tasks in `config/scheduler/tasks.json` are unaffected — these switches do not touch them, and an enabled one still registers and still runs the tick loop. Only when there is no enabled user task either does the scheduler stop writing its state file and run logs. |
658
679
  | `terminalSubmit` | Which bytes Claude reads as **submit** vs **newline**: `"cr"` (default — Enter submits, Shift+Enter makes a newline) or `"esc-cr"` (for a Claude Code rebound the other way). Applies to the keyboard **and** the phone remote-view submit, for **Claude sessions only** (shell/codex keep plain Enter). See the [Configuration guide](https://receptron.github.io/mulmoterminal/guide/en/config.html#terminal-submit). Settings → **Terminal keys** offers both, worded as behaviour. |
659
680
  | `copyOnSelect` | `true` puts a **mouse selection on the clipboard the moment it settles**, with no key pressed (the PuTTY / iTerm2 behaviour). **Off by default** — it changes the clipboard when you may only have meant to highlight something. There is a checkbox in Settings → **Terminal keys**, applied at once; a hand edit of the file needs a **server restart, then a tab reload** (the server reads this file once at startup, and the browser reads the value from it on load). Composes with the `copy` keymap action rather than replacing it. Over plain `http://` the browser gives a page no clipboard access, so a fallback asks xterm to copy instead; see the [Configuration guide](https://receptron.github.io/mulmoterminal/guide/en/config.html#copy-on-select). |
660
681
  | `questionPaneEnabled` | `true` offers a Claude session's **`AskUserQuestion` choices as buttons** in a pane beside the enlarged terminal. **The terminal's own dialog stays** and the pane drives it — a click presses the arrow keys and Enter in the real dialog, so either end can answer and the first one wins. Claude sessions only (the choices arrive on Claude Code's hooks). A **single** question can also be answered in your own words — a text box under the buttons writes into the dialog's own `Type something` row; several questions at once, or a multi-select one, get buttons only, and `Chat about this` stays in the terminal. **Off by default** — it lets a pane type into your terminal. Checkbox in Settings → **Terminal keys**, applied at once (the server re-reads the file per question). See the [Feature reference](https://receptron.github.io/mulmoterminal/guide/en/features.html#question-pane). |
@@ -855,7 +876,7 @@ Settings → Directory settings names both files and lists which keys the local
855
876
  | Field | Meaning |
856
877
  | ------------ | ------- |
857
878
  | `name` | Label shown as a badge in the terminal/cell header. |
858
- | `icon` | An **image** marking this directory — shown in the cell header, the cockpit roster, the filmstrip thumbnails, the launcher's directory chips, and the phone's terminal list and terminal screen. Either a path **relative to this directory** (an absolute path, or a `../` that escapes it, is rejected), an `http(s)://` URL, or a `data:image/…` URI. PNG / JPEG / **GIF (animated plays)** / WebP / AVIF / SVG / ICO / BMP. Not to be confused with a header **button's** `icon`, which is a Material Symbols name. **Omit it and the repository's own favicon is used** (`public/favicon.svg`, `apple-touch-icon.png`, a web manifest — see `autoDirIcon`); `false` means no icon here and stops that search. |
879
+ | `icon` | An **image** marking this directory — shown in the cell header, the cockpit roster, the filmstrip thumbnails, the launcher's directory chips, and the phone's terminal list and terminal screen. Either a path **relative to this directory** (an absolute path, or a `../` that escapes it, is rejected), an `http(s)://` URL, or a `data:image/…` URI. PNG / JPEG / **GIF (animated plays)** / WebP / AVIF / SVG / ICO / BMP. Not to be confused with a header **button's** `icon`, which is a Material Symbols name, or with the small glyph a chat started from a **collection** wears beside its status dot — that one is the collection's own `icon`, and it says which collection the cell was opened for while this one says which directory it runs in. **Omit it and the repository's own favicon is used** (`public/favicon.svg`, `apple-touch-icon.png`, a web manifest — see `autoDirIcon`); `false` means no icon here and stops that search. |
859
880
  | `badgeColor` | Badge background color (`#rrggbb`); text auto-contrasts. |
860
881
  | `headerColor` | Header **background** color (`#rrggbb`) — the grid cell's header row and the terminal's own header row (grid row 2). While a terminal is working/blocked the status tint still shows; the custom color applies when idle. |
861
882
  | `headerTextColor` | Header **text** color (`#rrggbb`) — everything written on the header: the dir path, title and prompt, plus the model/context badge, the token counts and any custom chip. **Omit it and a readable colour is derived from `headerColor`.** It applies while that colour is what shows: a working/done/blocked cell paints the theme's own status tint, so its text returns to the theme's too — an ink chosen for your header colour is not readable on a tint the theme mixed. Recolour those states with `headerStatusColors` instead. |
@@ -1434,6 +1455,16 @@ prompt and spawns a fresh agent session for it — the **Launch with Claude / Co
1434
1455
  decides which agent (and whether the seed auto-runs or drops in as an editable draft).
1435
1456
  Favorited collections get their own toolbar buttons.
1436
1457
 
1458
+ That session is an ordinary **grid cell**, and starting it no longer takes the screen to the
1459
+ grid: while the collection is open, the grid **teleports that cell into a pane below it**, so
1460
+ the same terminal is driven from whichever view you have open — no hand-off, no reconnect, and
1461
+ nothing to move back. Several chats under one collection become tabs, each with the grid's own
1462
+ attention dot and a line of what the shown one is doing; the **Collections** button carries how
1463
+ many are running behind it. Which collection a chat belongs to survives a reload, and a chat
1464
+ whose cell is gone drops out rather than sitting over an empty pane. A button in the tab strip
1465
+ moves the pane **under the collection or beside it** — wide and short for a list you are scanning,
1466
+ narrow and tall for one record you are discussing — and each position keeps its own size.
1467
+
1437
1468
  ---
1438
1469
 
1439
1470
  ## More features
@@ -2117,6 +2148,8 @@ src/
2117
2148
  GitBranchChip.vue, ModelContextBadge.vue header chips / badges
2118
2149
  PrsOverlay.vue cross-repo PRs & Issues
2119
2150
  Wiki*View.vue, Collections*.vue, AccountingOverlay.vue workspace views
2151
+ CollectionChatPane.vue the pane under an open collection: tabs, and the
2152
+ receptacle the grid teleports a chat's cell into
2120
2153
  TimelineOverlay.vue, ToolsPane.vue, NotificationBell.vue, RemoteHostControl.vue
2121
2154
  SettingsModal.vue settings — the dialog shell + section order
2122
2155
  settings/ one file per settings section (theme, sounds,
@@ -0,0 +1,37 @@
1
+ // Which collection a session was started from (#2020), as BOTH sides agree it should look.
2
+ //
3
+ // The server records it at spawn and answers it on `/api/session/:id`; the grid draws it beside
4
+ // the cell's status dot. In common/ because that response shape is decided by both — the wire type
5
+ // mirrored into `server/` and `src/` is exactly the drift this directory exists to prevent.
6
+ //
7
+ // The DISPLAY fields travel with the slug rather than being looked up per render, and that is a
8
+ // snapshot on purpose: resolving `slug -> icon` needs a collection discovery pass, and
9
+ // `/api/session/:id` is polled once per cell. A collection that later changes its icon leaves the
10
+ // sessions started before it wearing the old glyph, which is the right answer for a historical
11
+ // record anyway.
12
+ import { isRecord } from "./isRecord";
13
+
14
+ export interface SessionCollection {
15
+ slug: string;
16
+ /** The schema's `icon`: a Material Symbols ligature name OR a single emoji. Never an image —
17
+ * that is the DIRECTORY's icon, a different question the cell answers separately. Draw it with
18
+ * `IconGlyph` from `@mulmoclaude/core/plugin-vue`, which is the one renderer that classifies
19
+ * the two and contains a value it cannot resolve. May be "" when the schema names none. */
20
+ icon: string;
21
+ /** What the collection calls itself, falling back to its slug. Never empty, and never absent:
22
+ * the producer normalizes it (`resolveSpawnCollection`) because the package's own summary type
23
+ * promises a string and hands back `undefined` for a schema that names no title. */
24
+ title: string;
25
+ }
26
+
27
+ /** Read a session's collection off an untrusted body, or null when there is none / it is unusable.
28
+ *
29
+ * A missing key and a malformed one answer the same way on purpose: the field is decoration, and
30
+ * the cell that renders nothing is correct in both cases. */
31
+ export function asSessionCollection(value: unknown): SessionCollection | null {
32
+ if (!isRecord(value)) return null;
33
+ const { slug, icon, title } = value;
34
+ if (typeof slug !== "string" || slug.length === 0) return null;
35
+ if (typeof icon !== "string" || typeof title !== "string") return null;
36
+ return { slug, icon, title };
37
+ }