mulmoterminal 9.7.0 → 9.9.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 (166) hide show
  1. package/README.md +19 -6
  2. package/common/bundledSkills.ts +1 -0
  3. package/common/mdPreviewMessage.ts +5 -2
  4. package/common/tmuxPrefix.ts +57 -0
  5. package/dist/assets/{abnfDiagram-YUKMZFIV-Bc3M8oAu.js → abnfDiagram-YUKMZFIV-DSIHQLCR.js} +1 -1
  6. package/dist/assets/{architecture-WOLXFQ4H-Dxk8ukGT.js → architecture-WOLXFQ4H-CuaFde5g.js} +1 -1
  7. package/dist/assets/{architectureDiagram-47P4ROYG-BjlVfGp0.js → architectureDiagram-47P4ROYG-DM9sjzl3.js} +1 -1
  8. package/dist/assets/{blockDiagram-E7TT5TSB-BhLPvKcs.js → blockDiagram-E7TT5TSB-DJWoD4kH.js} +1 -1
  9. package/dist/assets/{c4Diagram-CRA5TL53-l9JztTur.js → c4Diagram-CRA5TL53-BdKZm-Qq.js} +1 -1
  10. package/dist/assets/channel-BylLlugM.js +1 -0
  11. package/dist/assets/{chunk-2BW5OAIV-EggMYLpl.js → chunk-2BW5OAIV-Pm-SjVYY.js} +1 -1
  12. package/dist/assets/{chunk-3YJQHVM4-D5YjAjNs.js → chunk-3YJQHVM4-CRHtGa8R.js} +1 -1
  13. package/dist/assets/{chunk-4EA7E6EY-B2Bi45c0.js → chunk-4EA7E6EY-BEApBMtM.js} +1 -1
  14. package/dist/assets/{chunk-7TKQ45FW-BX4TKY9A.js → chunk-7TKQ45FW-kpEnChvL.js} +1 -1
  15. package/dist/assets/{chunk-AW2ZBBNX-Db513VL_.js → chunk-AW2ZBBNX-4pHfKBsS.js} +1 -1
  16. package/dist/assets/{chunk-DBDB3WZW-ouizEO2_.js → chunk-DBDB3WZW-Ujmi2ugS.js} +1 -1
  17. package/dist/assets/{chunk-E2ZNV5FY-DP4pRCEW.js → chunk-E2ZNV5FY-Bjpe59na.js} +1 -1
  18. package/dist/assets/{chunk-EU5HNXII-AHbdUHik.js → chunk-EU5HNXII-CUXlDfPl.js} +1 -1
  19. package/dist/assets/{chunk-FVRAUYC3-BuK6_zW2.js → chunk-FVRAUYC3-CpO1mJeh.js} +1 -1
  20. package/dist/assets/{chunk-HJ2JQQFS-Cr7WKXRC.js → chunk-HJ2JQQFS-B9bCVfI7.js} +1 -1
  21. package/dist/assets/{chunk-HTAEGDNF-D0Gf47NU.js → chunk-HTAEGDNF-Dx2Qegto.js} +1 -1
  22. package/dist/assets/{chunk-KQW6MTUR-DLi0kaJz.js → chunk-KQW6MTUR-Da2aP601.js} +1 -1
  23. package/dist/assets/{chunk-NTY3LDVX-Ct1TGEEh.js → chunk-NTY3LDVX-B912Szqv.js} +1 -1
  24. package/dist/assets/{chunk-VPRB5NB3-0gDJvzqR.js → chunk-VPRB5NB3-Dj20tFqN.js} +1 -1
  25. package/dist/assets/{chunk-XC4XBNZT-DMg4NiVd.js → chunk-XC4XBNZT-C7bFqTbJ.js} +1 -1
  26. package/dist/assets/{classDiagram-v2-K4WV4PDN-DDmVPVI_.js → classDiagram-v2-K4WV4PDN-B80F0KMA.js} +1 -1
  27. package/dist/assets/{cynefin-EF2NZ3EQ-BF0w-gpq.js → cynefin-EF2NZ3EQ-Bl7z6XCQ.js} +1 -1
  28. package/dist/assets/{cynefinDiagram-3GCD6N5R-DcdzqfM4.js → cynefinDiagram-3GCD6N5R-qAHmVOUq.js} +1 -1
  29. package/dist/assets/{dagre-W4DXFKR2-CJSTp3_X.js → dagre-W4DXFKR2-B1MePpen.js} +1 -1
  30. package/dist/assets/{diagram-2UJZ2QOL-DlXwV7jP.js → diagram-2UJZ2QOL-ADSKiSqD.js} +1 -1
  31. package/dist/assets/{diagram-OVF4WLC6-B8JBkoLC.js → diagram-OVF4WLC6-D1taTzkW.js} +1 -1
  32. package/dist/assets/{diagram-PFPMY2P6-tzXPDBnb.js → diagram-PFPMY2P6-ph8x3PQF.js} +1 -1
  33. package/dist/assets/{diagram-UMYRVEAY-DiXKe0ef.js → diagram-UMYRVEAY-BDVPufMW.js} +1 -1
  34. package/dist/assets/{diagram-YEKJPTXX-ZdkdZAmL.js → diagram-YEKJPTXX-BHD8Za4y.js} +1 -1
  35. package/dist/assets/{diagram-ZIFT7M5P-DGmkRkP3.js → diagram-ZIFT7M5P-D7QtA_t6.js} +1 -1
  36. package/dist/assets/{dist-PUjH4xcy.js → dist-9ZQ2gQ7P.js} +1 -1
  37. package/dist/assets/{dist-DQyLsCOD.js → dist-B1VHyamY.js} +1 -1
  38. package/dist/assets/{dist-Cb957G0Y.js → dist-BefB7e6h.js} +1 -1
  39. package/dist/assets/{dist-DBZEw2q8.js → dist-CZR1xmq0.js} +1 -1
  40. package/dist/assets/{dist-DKi0Ysta.js → dist-Cl-feCtf.js} +1 -1
  41. package/dist/assets/{ebnfDiagram-VR2GEFS7-DWfnsUqs.js → ebnfDiagram-VR2GEFS7-wD98lTRG.js} +1 -1
  42. package/dist/assets/{elk-IJKZMXRS-DDbjBg5o.js → elk-IJKZMXRS-K4Xjl1d0.js} +1 -1
  43. package/dist/assets/{erDiagram-O2IAPWRE-Br3_P7dq.js → erDiagram-O2IAPWRE-BjY7jKnV.js} +1 -1
  44. package/dist/assets/{eventmodeling-K75KTNOO-BQWfEpLq.js → eventmodeling-K75KTNOO-Bl9tIhky.js} +1 -1
  45. package/dist/assets/flowDiagram-OXPTDLAJ-BhH6Qffp.js +1 -0
  46. package/dist/assets/{ganttDiagram-R7TSEDQI-Ntfgx1BY.js → ganttDiagram-R7TSEDQI-BO9_wwDf.js} +1 -1
  47. package/dist/assets/{gitGraph-VSP46ZUC-Bs4oWeTw.js → gitGraph-VSP46ZUC-CRffKQOo.js} +1 -1
  48. package/dist/assets/{gitGraphDiagram-XJZIOB7I-DRrVNAim.js → gitGraphDiagram-XJZIOB7I-CpDXt3PU.js} +1 -1
  49. package/dist/assets/index-CPITW2xe.css +1 -0
  50. package/dist/assets/{index-BuzOErIU.js → index-CfuHlPQc.js} +342 -342
  51. package/dist/assets/{info-OHQRW6UA-Fscbeguy.js → info-OHQRW6UA-DyRgl8N3.js} +1 -1
  52. package/dist/assets/{infoDiagram-5W2HQ5XZ-C3Nym05L.js → infoDiagram-5W2HQ5XZ-BvWFfUM-.js} +1 -1
  53. package/dist/assets/{ishikawaDiagram-K3B6WC7H-X0OIlWvA.js → ishikawaDiagram-K3B6WC7H-DwF0XWsM.js} +1 -1
  54. package/dist/assets/{journeyDiagram-COXZFDF6-D9p2c2Ua.js → journeyDiagram-COXZFDF6-D1FJOSbZ.js} +1 -1
  55. package/dist/assets/{kanban-definition-P3RFRI5V-D_DrJIQd.js → kanban-definition-P3RFRI5V-qlKFzV9L.js} +1 -1
  56. package/dist/assets/{line-HeMc9KCE.js → line-IvDbfjKz.js} +1 -1
  57. package/dist/assets/{manifold-BaTKZ_Gm.js → manifold-DAOw2XRD.js} +1 -1
  58. package/dist/assets/{mermaid-parser.core-DxlPNzF1.js → mermaid-parser.core-DeUDbmOb.js} +3 -3
  59. package/dist/assets/{mermaid.core-CCalm0S4.js → mermaid.core-BnT3wMwo.js} +4 -4
  60. package/dist/assets/{mindmap-definition-LZFPQGKD-UO0JdGwQ.js → mindmap-definition-LZFPQGKD-CdNBxDve.js} +1 -1
  61. package/dist/assets/{packet-JDAUHWVQ-CV6_daNN.js → packet-JDAUHWVQ-B0iC5abl.js} +1 -1
  62. package/dist/assets/{pegDiagram-BGZESJAR-CthgOxpB.js → pegDiagram-BGZESJAR-C53izYN4.js} +1 -1
  63. package/dist/assets/{pie-XZMESJXO-DZg3FKCp.js → pie-XZMESJXO-BbVP9D3i.js} +1 -1
  64. package/dist/assets/{pieDiagram-CAPJLFHJ-BqtM3U-K.js → pieDiagram-CAPJLFHJ-BWSp3Fdb.js} +1 -1
  65. package/dist/assets/{quadrantDiagram-GDMTTRAM-CBOsoTVo.js → quadrantDiagram-GDMTTRAM-KD8tGY8h.js} +1 -1
  66. package/dist/assets/{radar-ABXABTNO-Bd_tJSOg.js → radar-ABXABTNO-C1ORJck5.js} +1 -1
  67. package/dist/assets/{railroad-I3PHUGI6-Bb3ukDrU.js → railroad-I3PHUGI6-D8kJJPjo.js} +1 -1
  68. package/dist/assets/{railroad-abnf-LNEFI6M7-EhK8NIEQ.js → railroad-abnf-LNEFI6M7-B02NcKpn.js} +1 -1
  69. package/dist/assets/{railroad-ebnf-DWYD2UWJ-BCPRn7Ck.js → railroad-ebnf-DWYD2UWJ-DbqSfby_.js} +1 -1
  70. package/dist/assets/{railroad-peg-JR7BVNR7-79og-B_g.js → railroad-peg-JR7BVNR7-BXFfYbex.js} +1 -1
  71. package/dist/assets/{railroadDiagram-SM67HX2B-C0mnTr1T.js → railroadDiagram-SM67HX2B-BdawA9C9.js} +1 -1
  72. package/dist/assets/{requirementDiagram-X7JNWC4A-eesytt7g.js → requirementDiagram-X7JNWC4A-qX9lrcTt.js} +1 -1
  73. package/dist/assets/{sankeyDiagram-UM26HJRW-7cM8RIKb.js → sankeyDiagram-UM26HJRW-Bi5VbC4v.js} +1 -1
  74. package/dist/assets/{sequenceDiagram-ZO4K6R2Y-V8k7zHu9.js → sequenceDiagram-ZO4K6R2Y-D8W3uMWv.js} +1 -1
  75. package/dist/assets/{stateDiagram-v2-TBUQTH76-ZlouAYhr.js → stateDiagram-v2-TBUQTH76-BhizBx7d.js} +1 -1
  76. package/dist/assets/{swimlanes-N4OXWK64-C7JH_UlY.js → swimlanes-N4OXWK64-DP1M8V93.js} +1 -1
  77. package/dist/assets/swimlanesDiagram-K3J5GTZL-B7CmMqE3.js +8 -0
  78. package/dist/assets/{timeline-definition-YOQAKGHF-khqYzQpl.js → timeline-definition-YOQAKGHF-CH0r5I0Z.js} +1 -1
  79. package/dist/assets/{treeView-D4JQ5SDB-Jns32W8E.js → treeView-D4JQ5SDB-BvVkUXwP.js} +1 -1
  80. package/dist/assets/{treemap-SAJKECNS-CtLcLLz5.js → treemap-SAJKECNS-DRvUI9Pf.js} +1 -1
  81. package/dist/assets/{usecaseDiagram-VIAY4XPW-BKrVhlOO.js → usecaseDiagram-VIAY4XPW-DJDMbQlz.js} +1 -1
  82. package/dist/assets/{vennDiagram-BLWOH2XV-BLk_1l4H.js → vennDiagram-BLWOH2XV-DqLka6D7.js} +1 -1
  83. package/dist/assets/{wardley-7MLQ67FV-C_TBT1hK.js → wardley-7MLQ67FV-D5SVGI-w.js} +1 -1
  84. package/dist/assets/{wardleyDiagram-YMQ3BMBF-CvA0PCqf.js → wardleyDiagram-YMQ3BMBF-BYqM69ek.js} +1 -1
  85. package/dist/assets/{xychartDiagram-TAQBALBS-PhN_PEd5.js → xychartDiagram-TAQBALBS-Bcay5SsS.js} +1 -1
  86. package/dist/index.html +2 -2
  87. package/docs/ChangeLog.md +8801 -0
  88. package/docs/facts.json +66 -0
  89. package/docs/guide/en/accounts.md +138 -0
  90. package/docs/guide/en/agents.md +252 -0
  91. package/docs/guide/en/alternatives.md +175 -0
  92. package/docs/guide/en/basics.md +377 -0
  93. package/docs/guide/en/blueprints.md +188 -0
  94. package/docs/guide/en/claude-ollama.md +75 -0
  95. package/docs/guide/en/config.md +2376 -0
  96. package/docs/guide/en/conversation.md +271 -0
  97. package/docs/guide/en/faq.md +285 -0
  98. package/docs/guide/en/feature-list.md +412 -0
  99. package/docs/guide/en/features.md +258 -0
  100. package/docs/guide/en/from-collection.md +263 -0
  101. package/docs/guide/en/getting-started.md +445 -0
  102. package/docs/guide/en/github.md +176 -0
  103. package/docs/guide/en/glossary.md +134 -0
  104. package/docs/guide/en/header-reference.md +359 -0
  105. package/docs/guide/en/header.md +322 -0
  106. package/docs/guide/en/index.md +293 -0
  107. package/docs/guide/en/mulmocast.md +154 -0
  108. package/docs/guide/en/notifications.md +148 -0
  109. package/docs/guide/en/phone.md +127 -0
  110. package/docs/guide/en/providers.md +384 -0
  111. package/docs/guide/en/remote.md +168 -0
  112. package/docs/guide/en/scenarios.md +116 -0
  113. package/docs/guide/en/shared-apps.md +551 -0
  114. package/docs/guide/en/token-rotation.md +165 -0
  115. package/docs/guide/en/v9.8.0.md +77 -0
  116. package/docs/guide/en/v9.9.0.md +69 -0
  117. package/docs/guide/en/worktree.md +161 -0
  118. package/docs/guide/ja/accounts.md +106 -0
  119. package/docs/guide/ja/agents.md +247 -0
  120. package/docs/guide/ja/alternatives.md +157 -0
  121. package/docs/guide/ja/basics.md +364 -0
  122. package/docs/guide/ja/blueprints.md +186 -0
  123. package/docs/guide/ja/claude-ollama.md +57 -0
  124. package/docs/guide/ja/config.md +2250 -0
  125. package/docs/guide/ja/conversation.md +264 -0
  126. package/docs/guide/ja/faq.md +281 -0
  127. package/docs/guide/ja/feature-list.md +411 -0
  128. package/docs/guide/ja/features.md +224 -0
  129. package/docs/guide/ja/from-collection.md +263 -0
  130. package/docs/guide/ja/getting-started.md +446 -0
  131. package/docs/guide/ja/github.md +171 -0
  132. package/docs/guide/ja/glossary.md +135 -0
  133. package/docs/guide/ja/header-reference.md +352 -0
  134. package/docs/guide/ja/header.md +310 -0
  135. package/docs/guide/ja/index.md +318 -0
  136. package/docs/guide/ja/mulmocast.md +143 -0
  137. package/docs/guide/ja/notifications.md +137 -0
  138. package/docs/guide/ja/phone.md +120 -0
  139. package/docs/guide/ja/providers.md +376 -0
  140. package/docs/guide/ja/remote.md +163 -0
  141. package/docs/guide/ja/scenarios.md +111 -0
  142. package/docs/guide/ja/shared-apps.md +485 -0
  143. package/docs/guide/ja/token-rotation.md +155 -0
  144. package/docs/guide/ja/v9.8.0.md +71 -0
  145. package/docs/guide/ja/v9.9.0.md +69 -0
  146. package/docs/guide/ja/worktree.md +162 -0
  147. package/package.json +6 -3
  148. package/server/config/app-config.ts +7 -0
  149. package/server/config/config-routes.ts +5 -0
  150. package/server/files/files-browse.ts +31 -13
  151. package/server/files/mdPreviewReporter.ts +3 -0
  152. package/server/files/mermaidAssets.ts +69 -0
  153. package/server/files/previewMermaid.ts +109 -0
  154. package/server/help/help-sources.ts +59 -0
  155. package/server/help/routes.ts +24 -0
  156. package/server/infra/process/tmux.ts +24 -2
  157. package/server/routes/app-routes.ts +4 -0
  158. package/server/routes/ws-accept.ts +53 -0
  159. package/server/routes/ws-routes.ts +66 -87
  160. package/server/skills/mulmoterminal-bug-report/SKILL.md +1 -1
  161. package/server/skills/mulmoterminal-help/SKILL.md +148 -0
  162. package/server/skills/mulmoterminal-keys/SKILL.md +23 -1
  163. package/dist/assets/channel-DGIHcwe8.js +0 -1
  164. package/dist/assets/flowDiagram-OXPTDLAJ-BWmnW1kX.js +0 -1
  165. package/dist/assets/index-Dftt4qrs.css +0 -1
  166. package/dist/assets/swimlanesDiagram-K3J5GTZL-DRgUd_e7.js +0 -8
package/README.md CHANGED
@@ -172,7 +172,7 @@ than as bytes (files within the session's working directory only):
172
172
 
173
173
  | A clicked … | opens as |
174
174
  |---|---|
175
- | `.md` `.markdown` | **rendered** markdown in a new tab — the same sandboxed `…/md` HTML the Files preview renders, minus the one script the preview needs to report where you are reading. It follows your system light/dark setting, since under the sandbox CSP it can't ask the app which theme is on |
175
+ | `.md` `.markdown` | **rendered** markdown in a new tab — the same sandboxed `…/md` HTML the Files preview renders, minus the scripts the preview needs (the one that reports where you are reading, and the one that draws mermaid diagrams — so a mermaid fence stays a code block here). It follows your system light/dark setting, since under the sandbox CSP it can't ask the app which theme is on |
176
176
  | `.json` | **indented** in a new tab (Chrome and Safari otherwise show one long line) |
177
177
  | `.csv` `.tsv` | a **table** in a new tab, with a sticky header that scrolls inside its own box |
178
178
  | source, config, logs, and `.txt` — 46 extensions | the app's own **Files** view (`/files?path=`), where CodeMirror highlights it, the tree is right there, and it can be edited |
@@ -286,7 +286,7 @@ Needs **Node ≥ 22.12**, plus these CLIs — on your `PATH`, or named by the ma
286
286
  | **Required** | `git` | [worktree isolation](#git-worktrees--pull-requests), each cell's branch / unsaved-dot / diff readout, the PR footer | `brew install git` · `sudo apt install git` · `sudo dnf install git` · Windows: [git-scm.com](https://git-scm.com/download/win) |
287
287
  | **Required** | `gh` | the cross-repo **PRs & Issues** view and one-click PR creation — it uses your `gh` login, so no token is stored | [cli.github.com](https://cli.github.com), then `gh auth login` |
288
288
  | Optional | `glab` | the same for **GitLab** projects (#981) — gitlab.com, and a self-hosted instance you declare in `gitlabHosts` (#1332). Same arrangement: the CLI holds the credentials, this app stores no token | `brew install glab`, then `glab auth login` (self-hosted: `glab auth login --hostname gitlab.example.com`) |
289
- | Recommended | `tmux` | [session persistence](#session-persistence-tmux) — terminals survive a server restart | `brew install tmux` · `sudo apt install tmux` · `sudo dnf install tmux` · no native Windows build (falls back to plain PTYs) |
289
+ | Recommended | `tmux` — the **latest release** (3.8 as of 2026-10-10); older ones are not supported | [session persistence](#session-persistence-tmux) — terminals survive a server restart | `brew install tmux` · `sudo apt install tmux` · `sudo dnf install tmux` · no native Windows build (falls back to plain PTYs) |
290
290
  | Optional | any other agent CLI | a cell can run **Codex**, **Antigravity** (`agy`), **Grok**, **Muse**, **GitHub Copilot CLI** or **Cursor CLI** instead of Claude — install only the ones you use, and a missing one simply fails to start that cell. What each can do is [the capability matrix](docs/agent-capability-matrix.md); how to install and pick one is the [agents guide](https://receptron.github.io/mulmoterminal/guide/en/agents.html) | e.g. `npm i -g @openai/codex` |
291
291
  | Optional | `ffmpeg` | video rendering from the [mulmo-script panel](#wiki-collections--the-gui-panel) (its plugin ships enabled) | `brew install ffmpeg` · `sudo apt install ffmpeg` · `sudo dnf install ffmpeg` |
292
292
  | Optional | `remotion` packages | MulmoCast's `remotion` beats, where Claude Code writes each scene as a Remotion component (mulmocast 2.13.0). Not a dependency of this app: install them yourself, into your home directory so an `npx` upgrade does not lose them — `init` reports whether mulmocast can see them | [Remotion scenes](https://receptron.github.io/mulmoterminal/guide/en/mulmocast.html#remotion) · [日本語](https://receptron.github.io/mulmoterminal/guide/ja/mulmocast.html#remotion) |
@@ -384,6 +384,12 @@ The launcher detects it and prints the exact, OS-appropriate removal command; ru
384
384
  > masked. Getting you unstuck is the goal; an issue is what is left when the first three steps
385
385
  > fail.
386
386
 
387
+ > **Have a question instead?** Press the **help** icon in the toolbar (next to the gear), or type
388
+ > `/mulmoterminal-help` in any session. The bundled skill answers questions about MulmoTerminal — what
389
+ > it can do, how a feature or a part of the screen works, how to set something up, what is new in
390
+ > your version and in the latest one — from the shipped guide, changelog and source, and names where
391
+ > each fact was checked. It changes nothing.
392
+
387
393
  ---
388
394
 
389
395
  ## Contents
@@ -687,6 +693,11 @@ sudo apt install tmux # Debian / Ubuntu
687
693
  sudo dnf install tmux # Fedora
688
694
  ```
689
695
 
696
+ Use the **latest tmux release** (3.8 as of 2026-10-10); older versions are not supported. Some
697
+ things MulmoTerminal asks tmux for, such as restoring bracketed paste after a reload, need 3.7 or
698
+ newer. A distribution's package is often older, so check `tmux -V` and take a newer build from
699
+ [tmux releases](https://github.com/tmux/tmux/releases) when it is.
700
+
690
701
  On Windows there's no native tmux, so sessions use the non-persistent fallback — run the
691
702
  server under **WSL** if you want persistence. Nothing else is required: MulmoTerminal
692
703
  detects `tmux` on `PATH` at startup and uses it automatically when present.
@@ -752,7 +763,7 @@ the `claude` / `codex` sessions themselves.
752
763
  | `MULMOTERMINAL_HOME` | `~/.mulmoterminal` | Root for managed **git worktrees**. |
753
764
  | `CLAUDE_CONFIG_DIR` | `~/.claude` | Claude Code's own config directory. MulmoTerminal reads Claude's transcripts (`projects/`), prompt history (`history.jsonl`) and user skills (`skills/`) from it, and `.claude.json` from **inside** it (unset: `~/.claude.json`), which is how the per-project GUI MCP registration is checked (`server/session/project-dir.ts`). Set it in the environment MulmoTerminal starts from, so it matches the one Claude runs under. |
754
765
  | `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. |
755
- | `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's skills root (`~/.claude/skills/`, and `$CLAUDE_CONFIG_DIR/skills/` as well when that is set) and the Codex skills root on startup. |
766
+ | `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` / `-help` family) into Claude's skills root (`~/.claude/skills/`, and `$CLAUDE_CONFIG_DIR/skills/` as well when that is set) and the Codex skills root on startup. |
756
767
  | `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. |
757
768
  | `WAIT_REAP_GRACE_MS` | `1800000` | How long a **waiting** background session is kept before it's auto-reaped (`0` or negative = never). |
758
769
 
@@ -791,7 +802,7 @@ The Settings modal (the gear button) persists per-user UI choices to `~/.mulmote
791
802
 
792
803
  ![The Settings modal — a sidebar of grouped sections beside the one being edited](https://raw.githubusercontent.com/receptron/mulmoterminal/main/docs/guide/images/settings-tabs.png)
793
804
 
794
- *Open it from the gear button in the toolbar. The **sidebar** groups the sections — Appearance, Projects, Header & launch, Input, Models & servers, Notifications, Integrations, Sessions, Help — and one is on screen at a time; on a phone the sidebar becomes a picker above the section. The interface is available in **English, 日本語, 简体中文, 繁體中文 and 한국어**: it follows your browser's language unless you pick one under **Language** (per browser, like the theme). Translated so far: this modal, the grid's status words, and every button's hover tip and screen-reader label; the rest of the app's words are still English. Under the title, a **Version** row shows what is running: the version from the shipped `package.json`, plus a `commit <sha>` chip on a git checkout — there the version is only whatever was last released, so the commit is what identifies the build. When something newer exists, the row is followed by the header badge's update notice, command included. Pick a **theme**, set the **terminal font size**, **font** and **scroll speed** (and whether sending **returns to the latest output**), set a custom **attention sound**, list the repos the cross-repo **PRs & Issues** view should aggregate, add **launch commands** for grid cells, register your own **MCP servers**, and turn on the switches for what this app writes on your behalf — **issue work comments**, the **PR clone footer**, the **closing summary**, the **decision digest**, the **dev worklog** — no need to hand-edit the config file. Three settings stay with their skill because a form would be the wrong tool for them (`keymap`, `themes`, `buttons`/`chips`); Settings shows what each is doing now and launches that skill. Backends (`providers`), custom agents and accounts are added and removed in **Models and backends**. Note that **theme, font size, scroll speed and the return-to-latest switch are stored per browser** (they're display preferences, so a phone and a desktop keep their own); the rest live in `~/.mulmoterminal/config.json` and are shared by every client.*
805
+ *Open it from the gear button in the toolbar. The **sidebar** groups the sections — Appearance, Projects, Header & launch, Input, Models & servers, Notifications, Integrations, Sessions, Help — and one is on screen at a time; on a phone the sidebar becomes a picker above the section. The interface is available in **English, 日本語, 简体中文, 繁體中文 and 한국어**: it follows your browser's language unless you pick one under **Language** (per browser, like the theme). Translated so far: this modal, the grid's status words, and every button's hover tip and screen-reader label; the rest of the app's words are still English. Under the title, a **Version** row shows what is running: the version from the shipped `package.json`, plus a `commit <sha>` chip on a git checkout — there the version is only whatever was last released, so the commit is what identifies the build. When something newer exists, the row is followed by the header badge's update notice, command included. Pick a **theme**, set the **terminal font size**, **font** and **scroll speed** (and whether sending **returns to the latest output**), set a custom **attention sound**, list the repos the cross-repo **PRs & Issues** view should aggregate, add **launch commands** for grid cells, register your own **MCP servers**, and turn on the switches for what this app writes on your behalf — **issue work comments**, the **PR clone footer**, the **closing summary**, the **decision digest**, the **dev worklog** — no need to hand-edit the config file. Three settings stay with their skill because a form would be the wrong tool for them (`keymap`, `themes`, `buttons`/`chips`); Settings shows what each is doing now and launches that skill. Backends (`providers`), custom agents and accounts are added and removed in **Models and backends**. Note that **theme, font size, scroll speed and the return-to-latest switch are stored per browser** (they're display preferences, so a phone and a desktop keep their own); the rest live in `~/.mulmoterminal/config.json` and are shared by every client. **Help** links to the guide and has a button that opens a terminal where an agent answers questions about MulmoTerminal from the shipped docs and source — the same help desk as the toolbar's help icon.*
795
806
 
796
807
  | Field | Meaning |
797
808
  | ------------ | ------- |
@@ -816,6 +827,7 @@ The Settings modal (the gear button) persists per-user UI choices to `~/.mulmote
816
827
  | `worklogIntervalHours` | Worklog cadence in hours (default `6`, clamped to `1`–`168`). A stepper in the same Settings section covers the range. |
817
828
  | `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. Saved from Settings (or any `POST /api/config`), it applies at once — the running scheduler rebuilds its built-in tasks; a hand-edit applies after **Settings → Reload config file** (or a restart). Feeds still refresh on demand. Checkbox in Settings → **Sessions**. |
818
829
  | `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. |
830
+ | `tmuxPrefix` | The prefix key of the dedicated tmux server: `"none"` (default — every key reaches the agent, so Ctrl+B is "one character left" again), `"C-b"` (tmux's own default) or another control key such as `"C-]"`. Applied to a running tmux server on save. See the [Configuration guide](https://receptron.github.io/mulmoterminal/guide/en/config.html#tmux-prefix). Settings → **Terminal keys** has a dropdown. |
819
831
  | `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. |
820
832
  | `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). |
821
833
  | `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). |
@@ -1289,7 +1301,8 @@ rooted at **that terminal's project directory** — so after Claude says "wrote
1289
1301
  you can jump straight there to read or edit it. The left pane is a lazy-loaded directory
1290
1302
  tree; clicking a file opens it in a **CodeMirror** editor (Markdown / JS-TS / JSON
1291
1303
  highlighting, everything else as plain text). Markdown files get a **Preview** toggle
1292
- that renders via the server's sandboxed `…/md` HTML; a `.csv` / `.tsv` previews as a table (the
1304
+ that renders via the server's sandboxed `…/md` HTML, with a ` ```mermaid ` fence drawn as a diagram
1305
+ (its code block stays under it, folded, so the copy button is still there); a `.csv` / `.tsv` previews as a table (the
1293
1306
  same `…/table` document a clicked path opens, in the app's colours), and an `.html` / `.svg` as the
1294
1307
  page or picture it is. **Save** (or ⌘/Ctrl-S) writes back. **History** lists the versions the pane
1295
1308
  kept of the file (in `~/.mulmoterminal/backups`, taken when it is opened or reloaded here and before a save
@@ -2468,7 +2481,7 @@ server/
2468
2481
  backends/ wiki, collections, feeds, accounting, notifier,
2469
2482
  translation, whisper, remote-host, html, files
2470
2483
  skills/ bundled skills: mulmoterminal-config (entry point + audit), -dirs, -theme,
2471
- -header, -keys, -model, -notify, -bug-report, -decisions
2484
+ -header, -keys, -model, -notify, -bug-report, -decisions, -help
2472
2485
  fix-pty-perms.js postinstall: fixes node-pty binary permissions
2473
2486
  src/
2474
2487
  App.vue Layout; owns the grid, the overlays and the tab favicon
@@ -23,6 +23,7 @@ export const BUNDLED_SKILL_NAMES = [
23
23
  "mulmoterminal-bug-report",
24
24
  "mulmoterminal-decisions",
25
25
  "mulmoterminal-shared-app",
26
+ "mulmoterminal-help",
26
27
  ] as const;
27
28
 
28
29
  export type BundledSkillName = (typeof BUNDLED_SKILL_NAMES)[number];
@@ -79,13 +79,16 @@ export interface MdPreviewHostMessage {
79
79
  scrollY: number;
80
80
  /** The accessible name for the code blocks' copy buttons, in the app's language (#2615). */
81
81
  codeCopyLabel?: string;
82
+ /** What the disclosure under a rendered diagram is called (#2991). */
83
+ diagramSourceLabel?: string;
82
84
  }
83
85
 
84
- /** A new name for the code blocks' copy buttons: the app's language changed while this document was
85
- * open (the first name comes with the answer to `ready`). */
86
+ /** New names for the code blocks' copy buttons and the diagrams' source disclosures: the app's
87
+ * language changed while this document was open (the first names come with the answer to `ready`). */
86
88
  export interface MdPreviewLabelMessage {
87
89
  source: typeof MD_PREVIEW_FROM_HOST;
88
90
  codeCopyLabel: string;
91
+ diagramSourceLabel: string;
89
92
  }
90
93
 
91
94
  /** Take the reader to a heading (#2576): the `heading`-th one in the document (0-based) when it reads
@@ -0,0 +1,57 @@
1
+ // The tmux prefix key of the dedicated mulmoterminal tmux server (#2981).
2
+ //
3
+ // tmux's default `C-b` is also "one character left" in every readline, in Claude Code's input and
4
+ // in the macOS text system, so with it armed the first Ctrl+B in a cell is swallowed as a prefix and
5
+ // the next key is read as a tmux command. Nothing in this app uses the prefix: sessions are driven
6
+ // from the server with tmux commands, and the wheel reaches scrollback through the root table.
7
+ export const TMUX_PREFIX_NONE = "none";
8
+ export const TMUX_PREFIX_DEFAULT = TMUX_PREFIX_NONE;
9
+
10
+ // Control + one key, spelled the way tmux spells it. Deliberately narrow: each of these is written
11
+ // into a tmux conf line unquoted, so a character with meaning there never gets through.
12
+ const TMUX_CONTROL_KEY = /^C-(?:[a-z]|Space|\]|_|\^|@)$/u;
13
+
14
+ export const TMUX_PREFIX_CHOICES: readonly string[] = [TMUX_PREFIX_NONE, "C-b", "C-]"];
15
+
16
+ // vue-i18n reads `]` as path syntax, so the labels cannot be keyed by the tmux spelling itself.
17
+ export const TMUX_PREFIX_LABEL_KEYS: Readonly<Record<string, string>> = { none: "none", "C-b": "ctrlB", "C-]": "ctrlBracket" };
18
+
19
+ export const isTmuxPrefix = (input: unknown): input is string => input === TMUX_PREFIX_NONE || (typeof input === "string" && TMUX_CONTROL_KEY.test(input));
20
+
21
+ export const sanitizeTmuxPrefix = (input: unknown): string => (isTmuxPrefix(input) ? input : TMUX_PREFIX_DEFAULT);
22
+
23
+ /** The offered choices, plus the value in force when config.json holds a valid key the dropdown does
24
+ * not list, so the control shows what is running instead of a blank. */
25
+ export const tmuxPrefixChoicesFor = (current: string): readonly string[] =>
26
+ TMUX_PREFIX_CHOICES.includes(current) ? TMUX_PREFIX_CHOICES : [...TMUX_PREFIX_CHOICES, current];
27
+
28
+ const TMUX_OWN_DEFAULT_PREFIX = "C-b";
29
+
30
+ // The commands that put a prefix in force. Idempotent, so the same lines serve the conf file of a
31
+ // fresh server and a server that is already running. `unbind-key C-b` matters for "none" and for any
32
+ // other key: tmux binds the default's `send-prefix` in the prefix table independently of the option.
33
+ export function tmuxPrefixCommands(prefix: string): string[] {
34
+ if (prefix === TMUX_PREFIX_NONE) return ["set -g prefix None", `unbind-key ${TMUX_OWN_DEFAULT_PREFIX}`];
35
+ if (prefix === TMUX_OWN_DEFAULT_PREFIX) return [`set -g prefix ${prefix}`, `bind-key ${prefix} send-prefix`];
36
+ return [`set -g prefix ${prefix}`, `unbind-key ${TMUX_OWN_DEFAULT_PREFIX}`, `bind-key ${prefix} send-prefix`];
37
+ }
38
+
39
+ // `list-keys -T prefix` prints one `bind-key [-r] -T prefix <key> <command>` per binding. Every key in
40
+ // the prefix table that sends the prefix on, other than the one now in force, is left over from an
41
+ // earlier setting - possibly from an earlier PROCESS, which is why this reads the server's own table
42
+ // instead of remembering what was set last.
43
+ // Read as words, not a pattern: flags such as `-r` may precede `-T prefix`.
44
+ const sendPrefixKeyOf = (line: string): string | undefined => {
45
+ const words = line.trim().split(/\s+/u);
46
+ const tableAt = words.indexOf("-T");
47
+ const isPrefixTable = words[0] === "bind-key" && tableAt > 0 && words[tableAt + 1] === "prefix";
48
+ const sendsPrefix = words.length === tableAt + 4 && words[tableAt + 3] === "send-prefix";
49
+ return isPrefixTable && sendsPrefix ? words[tableAt + 2] : undefined;
50
+ };
51
+
52
+ export function staleSendPrefixKeys(listKeysOutput: string, prefix: string): string[] {
53
+ return listKeysOutput
54
+ .split("\n")
55
+ .map(sendPrefixKeyOf)
56
+ .filter((key): key is string => key !== undefined && key !== prefix);
57
+ }
@@ -1 +1 @@
1
- import{m as e,t}from"./mermaid-parser.core-DxlPNzF1.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-JH1jZ6Eh.js";import"./chunk-VPRB5NB3-0gDJvzqR.js";import{n as i,r as a,t as o}from"./chunk-AW2ZBBNX-Db513VL_.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-CCalm0S4.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
1
+ import{m as e,t}from"./mermaid-parser.core-DeUDbmOb.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-JH1jZ6Eh.js";import"./chunk-VPRB5NB3-Dj20tFqN.js";import{n as i,r as a,t as o}from"./chunk-AW2ZBBNX-4pHfKBsS.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-BnT3wMwo.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
@@ -1 +1 @@
1
- import"./chunk-NGNAAXSQ-C2Wy9Xmz.js";export{M as createArchitectureServices}from"./mermaid-parser.core-DxlPNzF1.js";
1
+ import"./chunk-NGNAAXSQ-C2Wy9Xmz.js";export{M as createArchitectureServices}from"./mermaid-parser.core-DeUDbmOb.js";