termdock 1.0.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 (227) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +385 -0
  3. package/dist/client/apple-splash-default-1170x2532.png +0 -0
  4. package/dist/client/apple-splash-landscape-1136x640.png +0 -0
  5. package/dist/client/apple-splash-landscape-1334x750.png +0 -0
  6. package/dist/client/apple-splash-landscape-1792x828.png +0 -0
  7. package/dist/client/apple-splash-landscape-2048x1536.png +0 -0
  8. package/dist/client/apple-splash-landscape-2160x1620.png +0 -0
  9. package/dist/client/apple-splash-landscape-2208x1242.png +0 -0
  10. package/dist/client/apple-splash-landscape-2224x1668.png +0 -0
  11. package/dist/client/apple-splash-landscape-2266x1488.png +0 -0
  12. package/dist/client/apple-splash-landscape-2360x1640.png +0 -0
  13. package/dist/client/apple-splash-landscape-2388x1668.png +0 -0
  14. package/dist/client/apple-splash-landscape-2436x1125.png +0 -0
  15. package/dist/client/apple-splash-landscape-2532x1170.png +0 -0
  16. package/dist/client/apple-splash-landscape-2556x1179.png +0 -0
  17. package/dist/client/apple-splash-landscape-2622x1206.png +0 -0
  18. package/dist/client/apple-splash-landscape-2688x1242.png +0 -0
  19. package/dist/client/apple-splash-landscape-2732x2048.png +0 -0
  20. package/dist/client/apple-splash-landscape-2778x1284.png +0 -0
  21. package/dist/client/apple-splash-landscape-2796x1290.png +0 -0
  22. package/dist/client/apple-splash-landscape-2868x1320.png +0 -0
  23. package/dist/client/apple-splash-portrait-1125x2436.png +0 -0
  24. package/dist/client/apple-splash-portrait-1170x2532.png +0 -0
  25. package/dist/client/apple-splash-portrait-1179x2556.png +0 -0
  26. package/dist/client/apple-splash-portrait-1206x2622.png +0 -0
  27. package/dist/client/apple-splash-portrait-1242x2208.png +0 -0
  28. package/dist/client/apple-splash-portrait-1242x2688.png +0 -0
  29. package/dist/client/apple-splash-portrait-1284x2778.png +0 -0
  30. package/dist/client/apple-splash-portrait-1290x2796.png +0 -0
  31. package/dist/client/apple-splash-portrait-1320x2868.png +0 -0
  32. package/dist/client/apple-splash-portrait-1488x2266.png +0 -0
  33. package/dist/client/apple-splash-portrait-1536x2048.png +0 -0
  34. package/dist/client/apple-splash-portrait-1620x2160.png +0 -0
  35. package/dist/client/apple-splash-portrait-1640x2360.png +0 -0
  36. package/dist/client/apple-splash-portrait-1668x2224.png +0 -0
  37. package/dist/client/apple-splash-portrait-1668x2388.png +0 -0
  38. package/dist/client/apple-splash-portrait-2048x2732.png +0 -0
  39. package/dist/client/apple-splash-portrait-640x1136.png +0 -0
  40. package/dist/client/apple-splash-portrait-750x1334.png +0 -0
  41. package/dist/client/apple-splash-portrait-828x1792.png +0 -0
  42. package/dist/client/apple-touch-icon-180x180.png +0 -0
  43. package/dist/client/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  44. package/dist/client/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  45. package/dist/client/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  46. package/dist/client/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  47. package/dist/client/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  48. package/dist/client/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  49. package/dist/client/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  50. package/dist/client/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  51. package/dist/client/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  52. package/dist/client/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  53. package/dist/client/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  54. package/dist/client/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  55. package/dist/client/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  56. package/dist/client/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  57. package/dist/client/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  58. package/dist/client/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  59. package/dist/client/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  60. package/dist/client/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  61. package/dist/client/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  62. package/dist/client/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  63. package/dist/client/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  64. package/dist/client/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  65. package/dist/client/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  66. package/dist/client/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  67. package/dist/client/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  68. package/dist/client/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  69. package/dist/client/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  70. package/dist/client/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  71. package/dist/client/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  72. package/dist/client/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  73. package/dist/client/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  74. package/dist/client/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  75. package/dist/client/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  76. package/dist/client/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  77. package/dist/client/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  78. package/dist/client/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  79. package/dist/client/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  80. package/dist/client/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  81. package/dist/client/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  82. package/dist/client/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  83. package/dist/client/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  84. package/dist/client/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  85. package/dist/client/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  86. package/dist/client/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  87. package/dist/client/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  88. package/dist/client/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  89. package/dist/client/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  90. package/dist/client/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  91. package/dist/client/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  92. package/dist/client/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  93. package/dist/client/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  94. package/dist/client/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  95. package/dist/client/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  96. package/dist/client/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  97. package/dist/client/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  98. package/dist/client/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  99. package/dist/client/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  100. package/dist/client/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  101. package/dist/client/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  102. package/dist/client/assets/abnfDiagram-VRR7QNED-D0NxeSHA.js +1 -0
  103. package/dist/client/assets/arc-B7GoKc6u.js +1 -0
  104. package/dist/client/assets/architectureDiagram-ZJ3FMSHR-BQPW-wUx.js +36 -0
  105. package/dist/client/assets/blockDiagram-677ZJIJ3-CX_hbcgG.js +132 -0
  106. package/dist/client/assets/c4Diagram-LMCZKHZV-BwOMQA4x.js +10 -0
  107. package/dist/client/assets/channel-C2gUFcyU.js +1 -0
  108. package/dist/client/assets/chunk-2Q5K7J3B-BLJzEQXz.js +1 -0
  109. package/dist/client/assets/chunk-32BRIVSS-CjBDr_gz.js +1 -0
  110. package/dist/client/assets/chunk-5VM5RSS4-lddvv0x2.js +15 -0
  111. package/dist/client/assets/chunk-EX3LRPZG-Dtsq1Stg.js +231 -0
  112. package/dist/client/assets/chunk-JWPE2WC7-BG3PZx4j.js +1 -0
  113. package/dist/client/assets/chunk-MOJQB5TN-CMtlCuQg.js +88 -0
  114. package/dist/client/assets/chunk-RYQCIY6F-uplKqw64.js +1 -0
  115. package/dist/client/assets/chunk-V7JOEXUC-CpteLsY3.js +206 -0
  116. package/dist/client/assets/chunk-VR4S4FIN-1zYOJQXL.js +1 -0
  117. package/dist/client/assets/chunk-XXDRQBXY-C0wXH91I.js +1 -0
  118. package/dist/client/assets/classDiagram-OUVF2IWQ-BTOnA9HS.js +1 -0
  119. package/dist/client/assets/classDiagram-v2-EOCWNBFH-BTOnA9HS.js +1 -0
  120. package/dist/client/assets/cose-bilkent-JH36ORCC-BceT5ki2.js +1 -0
  121. package/dist/client/assets/cynefin-VYW2F7L2-BqCIkNeC.js +166 -0
  122. package/dist/client/assets/cynefinDiagram-TSTJHNR4-Dm7y-tsN.js +62 -0
  123. package/dist/client/assets/cytoscape.esm-D3_iZ_3b.js +321 -0
  124. package/dist/client/assets/dagre-VKFMJZFB-Bn8eh0lE.js +4 -0
  125. package/dist/client/assets/defaultLocale-CrowFXzY.js +1 -0
  126. package/dist/client/assets/diagram-FQU43EPY-DmZGMAsX.js +3 -0
  127. package/dist/client/assets/diagram-G47NLZAW-BLWSm_Rn.js +24 -0
  128. package/dist/client/assets/diagram-NH7WQ7WH-C2-HK8pv.js +24 -0
  129. package/dist/client/assets/diagram-OA4YK3LP-8Ex4XIU5.js +30 -0
  130. package/dist/client/assets/diagram-WEI45ONY-MRNIpBXG.js +41 -0
  131. package/dist/client/assets/diffWorker-B6msVyjo.js +18 -0
  132. package/dist/client/assets/dnd-BCFAPC0L.js +1 -0
  133. package/dist/client/assets/ebnfDiagram-CCIWWBDH-D7Z6wZi_.js +1 -0
  134. package/dist/client/assets/erDiagram-Q63AITRT-C96Q5x9y.js +85 -0
  135. package/dist/client/assets/flowDiagram-23GEKE2U-DzQp40QH.js +156 -0
  136. package/dist/client/assets/ganttDiagram-NO4QXBWP-ZzkchZJ8.js +292 -0
  137. package/dist/client/assets/gitGraphDiagram-IHSO6WYX-CFacEf54.js +106 -0
  138. package/dist/client/assets/graph-D2o_JWn5.js +1 -0
  139. package/dist/client/assets/index-Ca-rq7yX.js +6 -0
  140. package/dist/client/assets/index-Cv7q4nZR.css +1 -0
  141. package/dist/client/assets/index-XktPMm51.js +394 -0
  142. package/dist/client/assets/infoDiagram-FWYZ7A6U-CVRXs5rF.js +2 -0
  143. package/dist/client/assets/init-Gi6I4Gst.js +1 -0
  144. package/dist/client/assets/ishikawaDiagram-FXEZZL3T-B8FP_wzM.js +70 -0
  145. package/dist/client/assets/journeyDiagram-5HDEW3XC-BR__4Hbd.js +139 -0
  146. package/dist/client/assets/kanban-definition-HUTT4EX6-v39oZe6X.js +89 -0
  147. package/dist/client/assets/katex-55ZPZeOF.css +1 -0
  148. package/dist/client/assets/katex-DnlPpQZa.js +257 -0
  149. package/dist/client/assets/katex-HP8lGamR.js +257 -0
  150. package/dist/client/assets/layout-1eBIAoSl.js +1 -0
  151. package/dist/client/assets/linear-jlTiHqO6.js +1 -0
  152. package/dist/client/assets/map-BdqsVdb3.js +1 -0
  153. package/dist/client/assets/mermaid.core-DiiIN0EC.js +306 -0
  154. package/dist/client/assets/mindmap-definition-LN4V7U3C-AeUxAZeq.js +96 -0
  155. package/dist/client/assets/ordinal-Cboi1Yqb.js +1 -0
  156. package/dist/client/assets/pegDiagram-2B236MQR-Dh-bgAbv.js +1 -0
  157. package/dist/client/assets/pieDiagram-ENE6RG2P-De7Si7Tm.js +39 -0
  158. package/dist/client/assets/purify.es-CC4Brkr_.js +3 -0
  159. package/dist/client/assets/quadrantDiagram-ABIIQ3AL-CgWfHqy0.js +7 -0
  160. package/dist/client/assets/railroadDiagram-RFXS5EU6-BXnQW-pI.js +1 -0
  161. package/dist/client/assets/react-XDCjal2T.js +8 -0
  162. package/dist/client/assets/requirementDiagram-TGXJPOKE-CU1nnpUM.js +84 -0
  163. package/dist/client/assets/sankeyDiagram-HTMAVEWB-DFK-AXY6.js +40 -0
  164. package/dist/client/assets/sequenceDiagram-DBY2YBRQ-D_bVDWgq.js +162 -0
  165. package/dist/client/assets/sizeCapture-X5ZJPWSS-nh89ExHT.js +1 -0
  166. package/dist/client/assets/stateDiagram-2N3HPSRC-DUvT6Ruk.js +1 -0
  167. package/dist/client/assets/stateDiagram-v2-6OUMAXLB-Dz-3r-Yq.js +1 -0
  168. package/dist/client/assets/swimlanes-5IMT3BWC-ZYa52gjG.js +2 -0
  169. package/dist/client/assets/swimlanesDiagram-G3AALYLV-DXR_9lf9.js +8 -0
  170. package/dist/client/assets/terminal-C7X98Amf.js +10 -0
  171. package/dist/client/assets/timeline-definition-FHXFAJF6-Bp6A49KQ.js +120 -0
  172. package/dist/client/assets/vennDiagram-L72KCM5P-CDDUmLOI.js +34 -0
  173. package/dist/client/assets/wardleyDiagram-EHGQE667-CRc2ptu7.js +78 -0
  174. package/dist/client/assets/xychartDiagram-FW5EYKEG-ht_S0LUA.js +7 -0
  175. package/dist/client/favicon.ico +0 -0
  176. package/dist/client/fonts/JetBrainsMonoNL-Bold.woff2 +0 -0
  177. package/dist/client/fonts/JetBrainsMonoNL-BoldItalic.woff2 +0 -0
  178. package/dist/client/fonts/JetBrainsMonoNL-Italic.woff2 +0 -0
  179. package/dist/client/fonts/JetBrainsMonoNL-Regular.woff2 +0 -0
  180. package/dist/client/fonts/JetBrainsMonoNLNerdFontMono-Bold.ttf +0 -0
  181. package/dist/client/fonts/JetBrainsMonoNLNerdFontMono-BoldItalic.ttf +0 -0
  182. package/dist/client/fonts/JetBrainsMonoNLNerdFontMono-Italic.ttf +0 -0
  183. package/dist/client/fonts/JetBrainsMonoNLNerdFontMono-Regular.ttf +0 -0
  184. package/dist/client/fonts/NotoSansMonoCJKsc-Bold-Subset.woff2 +0 -0
  185. package/dist/client/fonts/NotoSansMonoCJKsc-Subset.woff2 +0 -0
  186. package/dist/client/fonts/NotoSansSymbols2-Subset.woff2 +0 -0
  187. package/dist/client/fonts/SymbolsNerdFontMono-Regular.woff2 +0 -0
  188. package/dist/client/fonts/TermdockStarSymbol-Subset.woff2 +0 -0
  189. package/dist/client/index.html +255 -0
  190. package/dist/client/manifest.webmanifest +1 -0
  191. package/dist/client/maskable-icon-512x512.png +0 -0
  192. package/dist/client/pwa-192x192.png +0 -0
  193. package/dist/client/pwa-192x192.svg +5 -0
  194. package/dist/client/pwa-512x512.png +0 -0
  195. package/dist/client/pwa-512x512.svg +5 -0
  196. package/dist/client/pwa-64x64.png +0 -0
  197. package/dist/client/registerSW.js +1 -0
  198. package/dist/client/robots.txt +4 -0
  199. package/dist/client/shell-integration/termdock.bash +107 -0
  200. package/dist/client/shell-integration/termdock.fish +60 -0
  201. package/dist/client/shell-integration/termdock.zsh +164 -0
  202. package/dist/client/sw-notifications.js +42 -0
  203. package/dist/client/sw.js +1 -0
  204. package/dist/client/workbox-e4022e15.js +1 -0
  205. package/dist/server/certificateWatcher.js +111 -0
  206. package/dist/server/cli.js +2534 -0
  207. package/dist/server/config.js +54 -0
  208. package/dist/server/entry.js +571 -0
  209. package/dist/server/onboardingServer.js +54 -0
  210. package/dist/server/routes/auth.js +48 -0
  211. package/dist/server/routes/filesystem.js +3749 -0
  212. package/dist/server/routes/local.js +32 -0
  213. package/dist/server/routes/onboarding.js +134 -0
  214. package/dist/server/routes/terminal.js +4879 -0
  215. package/dist/server/utils/authProtection.js +338 -0
  216. package/dist/server/utils/caffeinate.js +124 -0
  217. package/dist/server/utils/changeAuditStore.js +521 -0
  218. package/dist/server/utils/cookieSecurity.js +13 -0
  219. package/dist/server/utils/csrfProtection.js +112 -0
  220. package/dist/server/utils/localAccess.js +211 -0
  221. package/dist/server/utils/pathValidator.js +272 -0
  222. package/dist/server/utils/requestSecurity.js +103 -0
  223. package/dist/server/utils/serverLogger.js +57 -0
  224. package/dist/server/utils/settings.js +157 -0
  225. package/dist/server/utils/tmuxFocus.js +45 -0
  226. package/dist/server/utils/tmuxProgramDetection.js +148 -0
  227. package/package.json +125 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,385 @@
1
+ # Termdock
2
+
3
+ 一个面向移动端与桌面端的 Web 终端,由 tmux 持久托管会话,xterm.js + WebGL 负责渲染,Express + WebSocket 提供后端通信。
4
+
5
+ ![License](https://img.shields.io/badge/license-MIT-green)
6
+
7
+ ## 功能特性
8
+
9
+ ### 终端能力
10
+
11
+ - **xterm.js + WebGL 渲染**:使用 `@xterm/addon-webgl` 加速绘制,自动处理上下文丢失与纹理刷新
12
+ - **tmux 持久会话**:所有会话由 tmux 托管,关闭页面/掉线后仍可恢复,支持 `detach`、`destroy`、强杀
13
+ - **WebSocket 双向通信**:单条持久连接同时承载输入与输出(取代旧的 SSE + POST 方案)
14
+ - **自动重连**:网络或后端中断后会自动尝试 attach 回原会话
15
+ - **鼠标支持**:完整透传 SGR 鼠标协议,vim、htop、tmux copy-mode 内的滚动/点击都按预期工作
16
+ - **OSC 0 CWD 嗅探**:标签页可动态显示当前进程或目录,无需轮询 `/proc`
17
+
18
+ ### 多会话与标签栏
19
+
20
+ - **多会话管理**:创建、切换、重启、重命名(双击标签)、强杀
21
+ - **预渲染所有会话**:避免页面切换时 WebGL 上下文丢失
22
+ - **磁盘持久化**:会话布局与 tmux 元数据落盘,重启后自动恢复
23
+
24
+ ### 移动端体验
25
+
26
+ - **Swiper 翻页**:左右滑动在多个终端之间切换,与终端内滚动手势已做冲突隔离
27
+ - **触摸优先的设置抽屉**:分 Tab、可滑动、长按 destroy
28
+ - **可定制虚拟键盘**:内置 Esc / Tab / Ctrl / Alt / Cmd / 方向键 / Enter / Backspace,并支持自定义工具条预设
29
+ - **手势**:点击 = 鼠标左键,长按 = 右键,捏合缩放调字号,触摸滑动 = 终端滚动
30
+ - **iOS 适配**:处理选择菜单、键盘弹起、翻页与会话恢复时的纹理刷新等细节
31
+
32
+ ### 安全与认证
33
+
34
+ - **密码保护**(可选):通过 `termdock --set-password` 启用,登录页 + Cookie 会话
35
+ - **登录限流**:基于来源 IP 的指数退避,防暴力破解
36
+ - **CSRF 防护**:所有写入接口要求 CSRF token
37
+ - **WebSocket 升级鉴权**:未登录的 upgrade 请求会被 401 拒绝
38
+ - **路径校验**:内置 `pathValidator` 防止路径穿越
39
+
40
+ ### PWA
41
+
42
+ - 自托管 JetBrains Mono NL + Symbols Nerd Font(含 Bold)
43
+ - 完整的 PWA 图标 / 启动屏 / manifest,可安装到主屏幕全屏运行
44
+ - Service Worker 缓存静态资源,支持离线打开
45
+
46
+ ## 技术栈
47
+
48
+ - **前端**:React 18 + TypeScript + Vite 7
49
+ - **终端渲染**:`@xterm/xterm` + `@xterm/addon-webgl` + `@xterm/addon-fit`
50
+ - **状态管理**:Zustand
51
+ - **触摸滑动**:Swiper
52
+ - **拖拽排序**:dnd-kit
53
+ - **后端**:Express 5 + ws + node-pty + tmux
54
+ - **样式**:Tailwind CSS
55
+ - **图标**:Remix Icon + Nerd Fonts
56
+
57
+ ## 快速开始
58
+
59
+ ### 一行命令启动
60
+
61
+ ```bash
62
+ npx termdock
63
+ ```
64
+
65
+ 默认监听 `0.0.0.0:9834`,并在后台运行。常用变体:
66
+
67
+ ```bash
68
+ npx termdock --host 127.0.0.1 --port 4000
69
+ termdock --foreground # 前台运行
70
+ termdock --status # 查看后台状态
71
+ termdock --stop # 停止后台服务
72
+ ```
73
+
74
+ ### 设置访问密码(强烈推荐)
75
+
76
+ 如果服务暴露在 LAN 上,**务必先设置密码**,否则任何能访问到主机/端口的人都能执行 shell 命令:
77
+
78
+ ```bash
79
+ # 交互式设置(输入隐藏)
80
+ termdock --set-password
81
+
82
+ # 通过管道设置(CI / 脚本场景)
83
+ echo "my-secret" | termdock --set-password
84
+
85
+ # 关闭鉴权
86
+ termdock --clear-password
87
+ ```
88
+
89
+ 密码状态存放在 `~/.termdock/auth.json`(mode 0600,scrypt 哈希,不可逆)。修改密码会使所有已登录会话失效。
90
+
91
+ 服务在未设置密码时启动会打印醒目的安全警告。
92
+
93
+ ### 局域网 HTTPS 访问(手机 / 本机)
94
+
95
+ Termdock 可以为当前机器发布一个产品化的局域网地址:
96
+
97
+ ```text
98
+ https://<name>.termdock.local:9834
99
+ ```
100
+
101
+ `<name>` 会在首次启动时自动生成一个 4 位默认值,也可以在设置抽屉里的「本地访问」中自定义。自定义名称不做人为长度限制,但必须是合法 hostname label。
102
+
103
+ 第一版仍然保留 `:9834` 端口;无端口的 `https://<name>.termdock.local` 需要后续单独引入 443 代理/Helper。
104
+
105
+ 第一次直接运行 `termdock` 时,CLI 会先引导你选择 `.termdock.local` 前缀,并询问是否立刻启用 HTTPS;选择启用后会自动安装/配置 mkcert、生成证书,然后继续启动服务。
106
+
107
+ 使用建议:
108
+
109
+ ```bash
110
+ # 1. 先启用密码,避免把 shell 暴露给同一内网其他人
111
+ termdock --set-password
112
+
113
+ # 2. 自动准备本地 HTTPS 证书
114
+ # 若未安装 mkcert,会自动通过 Homebrew 执行 brew install mkcert
115
+ termdock --setup-local-https
116
+
117
+ # 3. 正常启动;如果 ~/.termdock/certs/ 下已有证书,会自动启用 HTTPS
118
+ termdock
119
+
120
+ # 4. 查看正式地址和手机首次接入地址
121
+ termdock --status
122
+ ```
123
+
124
+ 该命令会生成并保存:
125
+
126
+ ```text
127
+ ~/.termdock/certs/termdock-local.pem
128
+ ~/.termdock/certs/termdock-local-key.pem
129
+ ~/.termdock/certs/rootCA.pem
130
+ ```
131
+
132
+ 也可以手动覆盖证书路径:
133
+
134
+ ```bash
135
+ termdock --https-cert <cert.pem> --https-key <key.pem> --https-ca <rootCA.pem>
136
+ ```
137
+
138
+ 手机首次接入时,先在同一 Wi‑Fi 下打开 `termdock --status` 或服务启动日志输出的 onboarding 地址,例如:
139
+
140
+ ```text
141
+ http://192.168.1.23:52741/onboarding
142
+ ```
143
+
144
+ 该页面会提供 CA 证书下载和 iPhone / Android 安装步骤;如果只想直接下载证书,也可以打开更短的:
145
+
146
+ ```text
147
+ http://192.168.1.23:52741/ca
148
+ ```
149
+
150
+ 安装并信任 CA 后,再打开正式地址:
151
+
152
+ ```text
153
+ https://<name>.termdock.local:9834
154
+ ```
155
+
156
+ 注意:mDNS 依赖同一局域网的 `.local` 组播;访客 Wi‑Fi、客户端隔离、VPN 或部分企业网络可能会阻止解析。此时 `localhost` 访问仍然可用,但手机上的漂亮域名可能不可用。
157
+
158
+ ### 从源码安装
159
+
160
+ ```bash
161
+ git clone https://github.com/Jovines/termdock.git
162
+ cd termdock
163
+ ./install-local.sh
164
+ ```
165
+
166
+ 脚本会执行 `npm install` → `npm rebuild node-pty --build-from-source` → `npm run build` → `npm install -g .`。在 macOS 上会额外检查 `node-pty` 的 `spawn-helper` 是否生成成功,若失败会提示安装 Xcode Command Line Tools。
167
+
168
+ 若你开启了访问密码,并希望在自动化脚本里无交互访问(不关闭鉴权),可先尝试复用 cookie,再按需登录刷新:
169
+
170
+ ```bash
171
+ # 首先直接尝试复用已有 cookie(推荐)
172
+ bash auth-login.sh
173
+
174
+ # 仅当 cookie 失效时,再提供原密码刷新登录态
175
+ export TERMDOCK_PASSWORD="<your-termdock-password>"
176
+ bash auth-login.sh
177
+
178
+ # 自动化请求统一带 cookie
179
+ curl -b ~/.termdock/automation.cookies http://localhost:9834/api/auth/status
180
+ ```
181
+
182
+ 这不会创建第二套密码,也不会关闭鉴权。
183
+
184
+ 卸载:
185
+
186
+ ```bash
187
+ ./uninstall-local.sh
188
+ ```
189
+
190
+ ### 开发模式
191
+
192
+ ```bash
193
+ # 同时启动前后端
194
+ npm run dev
195
+
196
+ # 或分开启动
197
+ npm run dev:client # Vite 前端:9833
198
+ npm run dev:server # tsx watch 后端:9835
199
+ ```
200
+
201
+ 开发期请访问 `http://localhost:9833`,Vite 会把 API/WebSocket 代理到后端开发端口 9835。正式/本地安装服务独立使用 9834。
202
+
203
+ ### 构建
204
+
205
+ ```bash
206
+ npm run build
207
+ ```
208
+
209
+ 输出:
210
+
211
+ - `dist/client/`:前端静态资源
212
+ - `dist/server/`:Node.js 服务端 + CLI 入口
213
+
214
+ 直接运行构建产物:
215
+
216
+ ```bash
217
+ node dist/server/cli.js
218
+ # 或
219
+ npm start
220
+ ```
221
+
222
+ ## 系统依赖
223
+
224
+ - **Node.js ≥ 18**
225
+ - **tmux**:会话托管必需,请确保 `tmux` 在 PATH 中
226
+ - **macOS**:需安装 Xcode Command Line Tools 以便 `node-pty` 编译 `spawn-helper`
227
+ - **Linux**:通常需要 `build-essential`、`python3` 才能编译 `node-pty`
228
+
229
+ ### tmux 焦点跟踪
230
+
231
+ Termdock 复用系统默认 tmux server。每次创建、复用、切换或通过 CLI attach tmux 会话时,Termdock 会自动确保 shared tmux server 的 `focus-events` 为 `on`,并在浏览器焦点变化时把 focus in/out 事件按需转发给 tmux 内部请求了 focus tracking 的程序(例如 Claude Code、Vim、fzf 等)。这是单向增强项:Termdock 不会在会话关闭后把 `focus-events` 自动恢复为 `off`。如果你手动维护 `~/.tmux.conf`,也可以显式加入:
232
+
233
+ ```tmux
234
+ set -g focus-events on
235
+ ```
236
+
237
+ ## 项目结构
238
+
239
+ ```
240
+ termdock/
241
+ ├── src/
242
+ │ ├── main.tsx # 应用入口
243
+ │ ├── App.tsx # 根组件
244
+ │ ├── index.css # 全局样式
245
+ │ ├── lib/
246
+ │ │ ├── terminal/ # xterm 适配层、主题、API
247
+ │ │ ├── stores/ # Zustand store
248
+ │ │ │ ├── useTerminalStore.ts
249
+ │ │ │ └── useMultiSessionStore.ts
250
+ │ │ ├── components/
251
+ │ │ │ ├── MultiTerminalView.tsx # 多会话 Swiper 主视图
252
+ │ │ │ ├── auth/LoginScreen.tsx # 登录页
253
+ │ │ │ ├── terminal/ # 终端视图、错误/加载、移动键盘
254
+ │ │ │ ├── settings/ # 调试面板、工具条预设
255
+ │ │ │ ├── ui/ErrorBoundary.tsx
256
+ │ │ │ └── views/TerminalView.tsx
257
+ │ │ ├── hooks/ # 字号、滚动、断连清理、视口高度等
258
+ │ │ └── utils/ # 错误处理、调试
259
+ │ └── server/
260
+ │ ├── cli.ts # CLI 入口(前后台、密码管理)
261
+ │ ├── entry.ts # Express + WebSocket 启动
262
+ │ ├── config.ts # 端口配置(dev: 9833/9835,prod: 9834)
263
+ │ ├── routes/
264
+ │ │ ├── auth.ts # 登录 / 登出 / 状态
265
+ │ │ └── terminal.ts # 终端 + tmux 路由
266
+ │ └── utils/
267
+ │ ├── authProtection.ts # scrypt 密码哈希、会话、限流
268
+ │ ├── csrfProtection.ts
269
+ │ └── pathValidator.ts
270
+ ├── public/ # PWA 图标、字体、manifest
271
+ ├── install-local.sh / uninstall-local.sh
272
+ ├── package.json
273
+ ├── vite.config.ts
274
+ └── tsconfig.json
275
+ ```
276
+
277
+ ## 主要 API 端点
278
+
279
+ > 写入接口需要登录后获取 CSRF token,并通过 Cookie + token 一起调用。
280
+
281
+ ### 鉴权
282
+
283
+ | 方法 | 端点 | 描述 |
284
+ |------|------|------|
285
+ | GET | `/api/auth/status` | 查询是否启用鉴权 / 当前 cookie 是否有效 |
286
+ | POST | `/api/auth/login` | 登录(限流) |
287
+ | POST | `/api/auth/logout` | 登出 |
288
+ | GET | `/api/csrf-token` | 获取 CSRF token(需登录) |
289
+
290
+ ### 终端 / tmux
291
+
292
+ | 方法 | 端点 | 描述 |
293
+ |------|------|------|
294
+ | POST | `/api/terminal/create` | 创建新会话 |
295
+ | GET | `/api/terminal/:sessionId/ws` *(WebSocket)* | 双向通信通道 |
296
+ | POST | `/api/terminal/:sessionId/input` | 发送输入(HTTP 兜底) |
297
+ | POST | `/api/terminal/:sessionId/resize` | 调整终端尺寸 |
298
+ | POST | `/api/terminal/:sessionId/tmux` | 执行 tmux 控制命令 |
299
+ | POST | `/api/terminal/:sessionId/restart` | 重启会话 |
300
+ | POST | `/api/terminal/:sessionId/detach` | 断开 attach |
301
+ | GET | `/api/terminal/:sessionId/attach` | 重新 attach |
302
+ | GET | `/api/terminal/:sessionId/health` | 健康检查 |
303
+ | DELETE | `/api/terminal/:sessionId` | 关闭会话 |
304
+ | POST | `/api/terminal/force-kill` | 强制结束 |
305
+ | GET | `/api/terminal/tmux/sessions` | 列出所有 tmux 会话 |
306
+ | DELETE | `/api/terminal/tmux/sessions/:name` | 销毁指定 tmux 会话 |
307
+ | GET | `/api/terminal/processes` | 进程列表 |
308
+
309
+ ## 主题
310
+
311
+ 当前内置 **Flexoki Dark** —— 一套低对比度、暖色调的配色,长时间阅读更舒适。
312
+ 主题定义在 `src/lib/terminal/theme.ts`,可按需扩展。
313
+
314
+ ## 配置
315
+
316
+ ### CLI 参数
317
+
318
+ ```
319
+ --host <host> 绑定地址(默认 0.0.0.0)
320
+ --port <port> 监听端口(默认 9834)
321
+ --foreground 前台运行
322
+ --status 查看后台服务状态
323
+ --stop 停止后台服务
324
+ --set-password 设置 / 修改访问密码(交互式)
325
+ --clear-password 清除密码并关闭鉴权
326
+ -h, --help 查看帮助
327
+ ```
328
+
329
+ ### 环境变量
330
+
331
+ ```bash
332
+ PORT=9834 # 正式/安装后服务端口;dev:server 使用 9835
333
+ HOST=0.0.0.0 # 绑定地址
334
+ NODE_ENV=development # 运行环境
335
+ TERM=xterm-256color # 终端类型
336
+ SHELL=/bin/zsh # 默认 shell
337
+ MAX_TERMINAL_SESSIONS=20 # 最大会话数
338
+ TERMINAL_IDLE_TIMEOUT=1800000 # 空闲超时 (毫秒)
339
+ ```
340
+
341
+ ### 状态目录
342
+
343
+ ```
344
+ ~/.termdock/
345
+ ├── auth.json # 密码哈希(mode 0600,仅在启用鉴权时存在)
346
+ ├── server.json # 后台进程 PID / 端口
347
+ └── server.log # 后台运行日志
348
+ ```
349
+
350
+ ## 移动端控制
351
+
352
+ ### 虚拟按键
353
+
354
+ Esc / Tab / Ctrl / Alt / Cmd / ↑↓←→ / Enter / Backspace,并支持在设置中自定义工具条预设。
355
+
356
+ ### 触摸交互
357
+
358
+ - **点击**:模拟鼠标左键
359
+ - **长按**:模拟鼠标右键
360
+ - **滑动**(终端区):滚动当前会话内容
361
+ - **滑动**(边缘):在多个会话之间翻页
362
+ - **捏合缩放**:调整字号
363
+
364
+ ## 发布到 npm
365
+
366
+ ```bash
367
+ npm publish
368
+ ```
369
+
370
+ `prepublishOnly` 钩子会自动执行 `npm run build`。发布前请确认:
371
+
372
+ - npm 包名可用
373
+ - `repository` / `homepage` / `bugs` 字段已更新
374
+ - README、版本号已同步
375
+
376
+ ## 浏览器支持
377
+
378
+ - Chrome 88+
379
+ - Firefox 79+
380
+ - Safari 14+(含 iOS 14+)
381
+ - Edge 88+
382
+
383
+ ## 许可证
384
+
385
+ MIT