@hienlh/ppm 0.18.11 → 0.18.13

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 (571) hide show
  1. package/AGENTS.md +17 -5
  2. package/CHANGELOG.md +27 -0
  3. package/CLAUDE.md +3 -0
  4. package/README.md +87 -29
  5. package/assets/skills/ppm/SKILL.md +1 -1
  6. package/assets/skills/ppm/references/http-api.md +19 -1
  7. package/dist/web/assets/{adaptive-context-menu-DGCKKeTy.js → adaptive-context-menu-CbgPYQmj.js} +1 -1
  8. package/dist/web/assets/{ai-resource-editor-BOHHTTe7.js → ai-resource-editor-unM2HNmg.js} +1 -1
  9. package/dist/web/assets/{ai-settings-section-BigC_nZR.js → ai-settings-section-CdktdrwF.js} +1 -1
  10. package/dist/web/assets/{angular-html-BYPaydvh.js → angular-html-DcpbdcNG.js} +1 -1
  11. package/dist/web/assets/{angular-ts-Bb4AMKlk.js → angular-ts-Bv_WIk34.js} +1 -1
  12. package/dist/web/assets/api-client-BogqsFna.js +1 -0
  13. package/dist/web/assets/{api-settings-Bd3M4YpI.js → api-settings-BdCtex9i.js} +1 -1
  14. package/dist/web/assets/api-settings-DfXViPKz.js +1 -0
  15. package/dist/web/assets/{api-themes-Cpx419SL.js → api-themes-pRRoLvgD.js} +1 -1
  16. package/dist/web/assets/{apl-DB2VjFCS.js → apl-D5_lLszu.js} +1 -1
  17. package/dist/web/assets/architecture-PBZL5I3N-BzFm9ELu.js +1 -0
  18. package/dist/web/assets/{astro-BeoJdVpk.js → astro-CBHwddYL.js} +1 -1
  19. package/dist/web/assets/{audio-preview-BgFuTn-0.js → audio-preview-BD1iDovf.js} +1 -1
  20. package/dist/web/assets/{blade-Cf2q1sPf.js → blade-DGe1d2Pq.js} +1 -1
  21. package/dist/web/assets/{bsl-W1kOaNpu.js → bsl-2lyAzRJA.js} +1 -1
  22. package/dist/web/assets/{button-5zTrkEoN.js → button-2WCAS8dI.js} +1 -1
  23. package/dist/web/assets/{cairo-BoAZFcje.js → cairo-DjzZeJrq.js} +1 -1
  24. package/dist/web/assets/chat-tab-DzK8LGti.js +15 -0
  25. package/dist/web/assets/{cobol-B0Nm7RXj.js → cobol-cC3XIuAJ.js} +1 -1
  26. package/dist/web/assets/code-editor-CuMfPN9X.js +10 -0
  27. package/dist/web/assets/{coffee-BakMn3on.js → coffee-4eGboVoU.js} +1 -1
  28. package/dist/web/assets/{conflict-editor-BUs5k9q_.js → conflict-editor-DdJag4QK.js} +1 -1
  29. package/dist/web/assets/{context-menu-Bq92km4s.js → context-menu-BO1c9jKy.js} +1 -1
  30. package/dist/web/assets/{cpp-BRAJQHK2.js → cpp-DF9_G-OU.js} +1 -1
  31. package/dist/web/assets/{crystal-kqqO3zkK.js → crystal-OavZlzcm.js} +1 -1
  32. package/dist/web/assets/{csv-preview-ByoDgLAZ.js → csv-preview-DnXwouF3.js} +1 -1
  33. package/dist/web/assets/{data-grid-overlay-editor-Brkf9z41.js → data-grid-overlay-editor-B9Gpjm3l.js} +1 -1
  34. package/dist/web/assets/{database-viewer-Btc3h8Yu.js → database-viewer-Dk8oGyZx.js} +1 -1
  35. package/dist/web/assets/{dialog-DwtGlowE.js → dialog-B-l2ZxVm.js} +1 -1
  36. package/dist/web/assets/{diff-viewer-CZaDnR4w.js → diff-viewer-eaUBjLCH.js} +1 -1
  37. package/dist/web/assets/{docx-preview-DAD_vg59.js → docx-preview-DAdHPlhZ.js} +1 -1
  38. package/dist/web/assets/{edge-Cq1ZKZuE.js → edge-TzYh8OlN.js} +1 -1
  39. package/dist/web/assets/{edit-diff-preview-B_VE7ppQ.js → edit-diff-preview-DlwP3UIU.js} +1 -1
  40. package/dist/web/assets/{elixir-BM_JoJRk.js → elixir-Cy3RhKKH.js} +1 -1
  41. package/dist/web/assets/{elm-Dw7oO08Y.js → elm-BTBZdweK.js} +1 -1
  42. package/dist/web/assets/{erb-CfKOGAfk.js → erb-dv1mI0y4.js} +1 -1
  43. package/dist/web/assets/{erlang-DlDmGVeE.js → erlang-DjeiDrkl.js} +1 -1
  44. package/dist/web/assets/{esm-DGAP0GFh.js → esm-FRwvcesu.js} +1 -1
  45. package/dist/web/assets/explorer-body-DkCkSVrN.js +2 -0
  46. package/dist/web/assets/explorer-window-content-MsnTVngu.js +1 -0
  47. package/dist/web/assets/{extension-store-Cpfh2vMm.js → extension-store-DUaZINyC.js} +1 -1
  48. package/dist/web/assets/{extension-webview-B2OnjuCu.js → extension-webview-W0qRfaAU.js} +1 -1
  49. package/dist/web/assets/{file-store-aOERIEo-.js → file-store-yReVbR8q.js} +1 -1
  50. package/dist/web/assets/{fortran-fixed-form-XnAhQWxS.js → fortran-fixed-form-BCH9DAIJ.js} +1 -1
  51. package/dist/web/assets/{fsharp-CdNvy0PG.js → fsharp-C93NYKYD.js} +1 -1
  52. package/dist/web/assets/{gdresource-DxuG5i8i.js → gdresource-BcIEE2eX.js} +1 -1
  53. package/dist/web/assets/{git-commit-3lMonsur.js → git-commit-BVjlXEy8.js} +1 -1
  54. package/dist/web/assets/{git-log-panel-Co0PBPHC.js → git-log-panel-2_4HuP47.js} +1 -1
  55. package/dist/web/assets/{git-rebase-N8Z9kIMf.js → git-rebase-Bj_21B1V.js} +1 -1
  56. package/dist/web/assets/gitGraph-HDMCJU4V-B72vcb2r.js +1 -0
  57. package/dist/web/assets/glide-data-grid-B0IY6n_Q.js +138 -0
  58. package/dist/web/assets/{glimmer-js-Dp9OXiib.js → glimmer-js-C20yj4Zv.js} +1 -1
  59. package/dist/web/assets/{glimmer-ts-CDVKBcDj.js → glimmer-ts-ipbYC7kh.js} +1 -1
  60. package/dist/web/assets/{glsl-DPJxI4us.js → glsl-Dovazu3t.js} +1 -1
  61. package/dist/web/assets/{graphql-BrFhaQQl.js → graphql-DpMlM7hC.js} +1 -1
  62. package/dist/web/assets/{group-chat-tab-rOd8J8GC.js → group-chat-tab-DRLDHOp6.js} +1 -1
  63. package/dist/web/assets/{hack-BzXbDMlA.js → hack-gc7LCBuV.js} +1 -1
  64. package/dist/web/assets/{haml-CPpkX0s5.js → haml-vtlFm9gm.js} +1 -1
  65. package/dist/web/assets/{handlebars-BqrApy52.js → handlebars-DGKhpCji.js} +1 -1
  66. package/dist/web/assets/{html-DmjUl-OA.js → html-DvfhQbXb.js} +1 -1
  67. package/dist/web/assets/{html-derivative-Cnd6XFR5.js → html-derivative-C3oTSSCN.js} +1 -1
  68. package/dist/web/assets/{http-DMLWYun2.js → http-SG6zLTo7.js} +1 -1
  69. package/dist/web/assets/{hurl-CKkCVxbj.js → hurl-BWXsYlqW.js} +1 -1
  70. package/dist/web/assets/{hxml-CAx19TtQ.js → hxml-DUdMzaoh.js} +1 -1
  71. package/dist/web/assets/{image-preview-DHUoylQ1.js → image-preview-DxgFOV1T.js} +1 -1
  72. package/dist/web/assets/index-CBn4SOoT.js +52 -0
  73. package/dist/web/assets/index-DWpNR3nB.css +2 -0
  74. package/dist/web/assets/info-3K5VOQVL-3irPxRK_.js +1 -0
  75. package/dist/web/assets/{input-DcEk7mA3.js → input-DuAF-Stj.js} +1 -1
  76. package/dist/web/assets/{jinja-BmB9YN9l.js → jinja-955w9RKM.js} +1 -1
  77. package/dist/web/assets/{jison-BaVsKKpw.js → jison-WWfqPo50.js} +1 -1
  78. package/dist/web/assets/{julia-BgVBLveX.js → julia-BFrfnaNl.js} +1 -1
  79. package/dist/web/assets/{just-C2ENIbl9.js → just-BrZdyR_I.js} +1 -1
  80. package/dist/web/assets/{keybindings-store-BGIyqXHI.js → keybindings-store-0Wqfa7Qp.js} +1 -1
  81. package/dist/web/assets/keybindings-store-d54pv2NK.js +1 -0
  82. package/dist/web/assets/{latex-BiDIWxKL.js → latex-CwtPPASD.js} +1 -1
  83. package/dist/web/assets/{liquid-NxpapreE.js → liquid-CYZuvDDd.js} +1 -1
  84. package/dist/web/assets/{lua-DVepQvwH.js → lua-BV095ZyY.js} +1 -1
  85. package/dist/web/assets/markdown-renderer-BTS8ifdu.js +1 -0
  86. package/dist/web/assets/{markdown-renderer-DlcDhgrF.js → markdown-renderer-CnRcKK3d.js} +3 -3
  87. package/dist/web/assets/{marko-CJ2606Xl.js → marko-CNeljZ1C.js} +1 -1
  88. package/dist/web/assets/{mdc-D2bjqclE.js → mdc-JfGapShy.js} +1 -1
  89. package/dist/web/assets/{media-url-H17XJF-I.js → media-url-Bm4PsduE.js} +1 -1
  90. package/dist/web/assets/{mobile-bottom-sheet-g-r2hCFa.js → mobile-bottom-sheet-M5iZDX7y.js} +1 -1
  91. package/dist/web/assets/mobile-explorer-sheet-BqK2-WuN.js +1 -0
  92. package/dist/web/assets/{nextflow-BtJwUbfF.js → nextflow-DD5C8nqX.js} +1 -1
  93. package/dist/web/assets/{nginx-j4gyIhHE.js → nginx-Ca7B__x_.js} +1 -1
  94. package/dist/web/assets/{nim-ClH_gjP5.js → nim-B8FogsDw.js} +1 -1
  95. package/dist/web/assets/notification-store-Yvy1I8gd.js +1 -0
  96. package/dist/web/assets/{number-overlay-editor-C1EqJnWq.js → number-overlay-editor-DG9xJwEG.js} +1 -1
  97. package/dist/web/assets/{overview-panel-vTeeJYVZ.js → overview-panel-s53bnl0q.js} +1 -1
  98. package/dist/web/assets/packet-RMMSAZCW-Z5jWjFCV.js +1 -0
  99. package/dist/web/assets/{panel-store-BSnkjgHt.js → panel-store-B4rijFKN.js} +1 -1
  100. package/dist/web/assets/{pdf-preview-CqFGRY0Z.js → pdf-preview-DYt3aBzM.js} +1 -1
  101. package/dist/web/assets/{perl-C9H7X7CT.js → perl-BR78hS8R.js} +1 -1
  102. package/dist/web/assets/{php-Bx2U-cQ_.js → php-DXBOMC9z.js} +1 -1
  103. package/dist/web/assets/pie-UPGHQEXC-Bq7UMi8P.js +1 -0
  104. package/dist/web/assets/{postgres-viewer-DHwcQucn.js → postgres-viewer-BvoWSuoZ.js} +3 -3
  105. package/dist/web/assets/{process-table-BGRJNlpn.js → process-table-BYwKigiD.js} +1 -1
  106. package/dist/web/assets/{project-store--nvQiy75.js → project-store-BuY7rxn_.js} +1 -1
  107. package/dist/web/assets/{pug-Cw74sKsE.js → pug-CvTwVVKV.js} +1 -1
  108. package/dist/web/assets/{qml-BXD94Eqz.js → qml-CPSoZ1-B.js} +1 -1
  109. package/dist/web/assets/radar-KQ55EAFF-BLo4BOTD.js +1 -0
  110. package/dist/web/assets/{razor-DZ0-Ge0S.js → razor-BUA1YKtF.js} +1 -1
  111. package/dist/web/assets/{rst-Dtdh0QUj.js → rst-BJsq7ISz.js} +1 -1
  112. package/dist/web/assets/{ruby-BC51BW2Q.js → ruby-DSDMeYf5.js} +1 -1
  113. package/dist/web/assets/{run-in-terminal-Sd3KyjN4.js → run-in-terminal-C9xpskFn.js} +1 -1
  114. package/dist/web/assets/{sas-BN8i4qOU.js → sas-B1nJOjbN.js} +1 -1
  115. package/dist/web/assets/{scroll-area-0gljZ6lF.js → scroll-area-DBcG1fQo.js} +1 -1
  116. package/dist/web/assets/{scss-H-QtA7Rz.js → scss-BZFyRiQn.js} +1 -1
  117. package/dist/web/assets/{send-to-chat-u6m8l-rH.js → send-to-chat-BIg70MUZ.js} +1 -1
  118. package/dist/web/assets/{settings-store-CHY6Kzin.js → settings-store-GV5pkkke.js} +2 -2
  119. package/dist/web/assets/{settings-tab-IY6K1MiZ.js → settings-tab-BePvIcjd.js} +1 -1
  120. package/dist/web/assets/settings-tab-Br-lJSPa.js +1 -0
  121. package/dist/web/assets/{shaderlab-CalNsj_x.js → shaderlab-laINRXBo.js} +1 -1
  122. package/dist/web/assets/{shellsession-BFrcoR8x.js → shellsession-BpOOvWVR.js} +1 -1
  123. package/dist/web/assets/{soy-CNbku7vP.js → soy-BW4d91Sa.js} +1 -1
  124. package/dist/web/assets/{sparql-BN_orcVp.js → sparql-BsvvyoHn.js} +1 -1
  125. package/dist/web/assets/{sql-query-editor-C6pC3I8l.js → sql-query-editor-qQce5QJ6.js} +1 -1
  126. package/dist/web/assets/{sqlite-viewer-DTr5PzUb.js → sqlite-viewer-yhc0YNvu.js} +1 -1
  127. package/dist/web/assets/{stata-C6a5Ijzq.js → stata-K-dZInUt.js} +1 -1
  128. package/dist/web/assets/{surrealql-ClplI_HY.js → surrealql-CpNp2sgf.js} +1 -1
  129. package/dist/web/assets/{svelte-DNm-UNXB.js → svelte-BG6iBA8R.js} +1 -1
  130. package/dist/web/assets/{switch-DKvKya9y.js → switch-_NcrktLe.js} +1 -1
  131. package/dist/web/assets/system-monitor-body-D8Z5QXBB.js +2 -0
  132. package/dist/web/assets/system-monitor-tab-BclYXFTe.js +1 -0
  133. package/dist/web/assets/{system-monitor-window-content-BUqRsPK2.js → system-monitor-window-content-CaOhD0AU.js} +1 -1
  134. package/dist/web/assets/{tab-host-window-content-BnqGPu8a.js → tab-host-window-content-f_Rc5rJK.js} +1 -1
  135. package/dist/web/assets/{tab-store-CJuJRapl.js → tab-store-tFnyPmm4.js} +1 -1
  136. package/dist/web/assets/team-member-sheet-QDHoYCs0.js +2 -0
  137. package/dist/web/assets/{team-member-window-content-T4Q5JI-G.js → team-member-window-content-B1jkKkDi.js} +1 -1
  138. package/dist/web/assets/{templ-CSdqVobu.js → templ-gxNKXmt3.js} +1 -1
  139. package/dist/web/assets/{terminal-tab-Bb2rZegQ.js → terminal-tab-UvwM0sty.js} +3 -3
  140. package/dist/web/assets/{tex-DzSJ4kcZ.js → tex-C0ON27g5.js} +1 -1
  141. package/dist/web/assets/{tool-cards-lhqhrDTT.js → tool-cards-jB7GT-wj.js} +4 -4
  142. package/dist/web/assets/treemap-KZPCXAKY-dyrE6SW2.js +1 -0
  143. package/dist/web/assets/{ts-tags-C28w3bTg.js → ts-tags-BX_CTVgQ.js} +1 -1
  144. package/dist/web/assets/{twig-i5jY3QXB.js → twig-CwL7XnU0.js} +1 -1
  145. package/dist/web/assets/{use-blob-url-Dsq9OjTh.js → use-blob-url-DcRcjNTE.js} +1 -1
  146. package/dist/web/assets/use-coarse-long-press-BmI_GVW5.js +1 -0
  147. package/dist/web/assets/{use-monaco-theme-BZvlsoBv.js → use-monaco-theme--9tOOkDA.js} +1 -1
  148. package/dist/web/assets/{use-open-team-member-DkiEjFYE.js → use-open-team-member-1hRsHLKg.js} +1 -1
  149. package/dist/web/assets/{use-websocket-B8R50f7f.js → use-websocket-rxJLbFqy.js} +1 -1
  150. package/dist/web/assets/{vendor-mermaid-By4AVvJY.js → vendor-mermaid-CHTa6D69.js} +1 -1
  151. package/dist/web/assets/video-preview-DMhnf2Gi.js +1 -0
  152. package/dist/web/assets/{vue-Ceyet_lv.js → vue-Bykm6wSS.js} +1 -1
  153. package/dist/web/assets/{vue-html-GuU7g_hg.js → vue-html-CETdK_iV.js} +1 -1
  154. package/dist/web/assets/{vue-vine-CxXoaJr2.js → vue-vine-DiJb6fO5.js} +1 -1
  155. package/dist/web/assets/{window-store-CsEW6jiE.js → window-store-CQ1lghvv.js} +1 -1
  156. package/dist/web/assets/{xml-CbqOVhkP.js → xml-BNw8J5YW.js} +1 -1
  157. package/dist/web/assets/{xsl-KfAmCauy.js → xsl-CsG9L31b.js} +1 -1
  158. package/dist/web/index.html +46 -45
  159. package/dist/web/sw.js +1 -1
  160. package/docs/architecture/ai-chat-and-providers.md +309 -0
  161. package/docs/architecture/data-and-storage.md +356 -0
  162. package/docs/architecture/extensions.md +496 -0
  163. package/docs/architecture/integrations.md +214 -0
  164. package/docs/architecture/workspace-and-ui.md +391 -0
  165. package/docs/claude-agent-sdk-reference.md +1 -1
  166. package/docs/code-patterns.md +361 -0
  167. package/docs/code-standards.md +8 -358
  168. package/docs/codebase-subsystems.md +364 -0
  169. package/docs/codebase-summary.md +34 -379
  170. package/docs/deployment-guide.md +280 -490
  171. package/docs/design-guidelines.md +1 -1
  172. package/docs/lessons-learned.md +27 -10
  173. package/docs/project-changelog.md +18 -806
  174. package/docs/project-overview-pdr.md +117 -111
  175. package/docs/project-roadmap.md +89 -133
  176. package/docs/system-architecture.md +77 -1826
  177. package/package.json +2 -2
  178. package/src/cli/commands/autostart.ts +2 -2
  179. package/src/cli/commands/config-cmd.ts +12 -3
  180. package/src/cli/commands/status.ts +3 -2
  181. package/src/cli/commands/stop.ts +32 -4
  182. package/src/server/index.ts +17 -3
  183. package/src/server/routes/chat-unread.ts +36 -0
  184. package/src/server/routes/named-tunnel.ts +132 -0
  185. package/src/server/routes/tunnel.ts +13 -0
  186. package/src/server/ws/chat.ts +5 -2
  187. package/src/services/autostart-register.ts +47 -29
  188. package/src/services/cloud.service.ts +26 -1
  189. package/src/services/config-secret-keys.ts +48 -0
  190. package/src/services/config.service.ts +1 -1
  191. package/src/services/db.service.ts +62 -12
  192. package/src/services/extension-rpc-handlers.ts +9 -1
  193. package/src/services/file-watcher/watch-tree.ts +67 -33
  194. package/src/services/file-watcher.service.ts +28 -10
  195. package/src/services/fs-credential-path-guard.ts +103 -0
  196. package/src/services/fs-path-guard.service.ts +14 -66
  197. package/src/services/named-tunnel/cloudflare-dns-api.ts +40 -0
  198. package/src/services/named-tunnel/cloudflare-zone-api.ts +28 -0
  199. package/src/services/named-tunnel/cloudflared-cert.ts +95 -0
  200. package/src/services/named-tunnel/cloudflared-exec.ts +50 -0
  201. package/src/services/named-tunnel/cloudflared-login-helpers.ts +98 -0
  202. package/src/services/named-tunnel/cloudflared-login.service.ts +182 -0
  203. package/src/services/named-tunnel/hostname-rules.ts +58 -0
  204. package/src/services/named-tunnel/login-output-parser.ts +36 -0
  205. package/src/services/named-tunnel/named-tunnel-args.ts +110 -0
  206. package/src/services/named-tunnel/named-tunnel-config.ts +67 -0
  207. package/src/services/named-tunnel/named-tunnel-probe-state.ts +95 -0
  208. package/src/services/named-tunnel/named-tunnel-readiness.ts +59 -0
  209. package/src/services/named-tunnel/named-tunnel-runtime.ts +42 -0
  210. package/src/services/named-tunnel/named-tunnel-setup-confirm.ts +98 -0
  211. package/src/services/named-tunnel/named-tunnel-setup.service.ts +191 -0
  212. package/src/services/supervisor-state.ts +67 -2
  213. package/src/services/supervisor.ts +454 -157
  214. package/src/services/tunnel-registry-parse.ts +27 -0
  215. package/src/services/tunnel-registry.service.ts +2 -15
  216. package/src/services/tunnel.service.ts +12 -3
  217. package/src/types/config.ts +31 -0
  218. package/src/web/app.tsx +5 -0
  219. package/src/web/components/chat/chat-history-bar.tsx +95 -98
  220. package/src/web/components/chat/chat-toolbar-overflow-menu.tsx +57 -0
  221. package/src/web/components/chat/session-debug-dialog.tsx +35 -27
  222. package/src/web/components/layout/cloud-share-named-tunnel-row.tsx +111 -0
  223. package/src/web/components/layout/cloud-share-popover.tsx +56 -14
  224. package/src/web/components/shared/connection-lost-overlay.tsx +44 -5
  225. package/src/web/components/tunnels/named-tunnel/hostname-validation.ts +14 -0
  226. package/src/web/components/tunnels/named-tunnel/named-tunnel-copy.ts +96 -0
  227. package/src/web/components/tunnels/named-tunnel/named-tunnel-hostname-field.tsx +51 -0
  228. package/src/web/components/tunnels/named-tunnel/named-tunnel-login-step.tsx +105 -0
  229. package/src/web/components/tunnels/named-tunnel/named-tunnel-section.tsx +159 -0
  230. package/src/web/components/tunnels/named-tunnel/named-tunnel-setup-content.tsx +197 -0
  231. package/src/web/components/tunnels/named-tunnel/named-tunnel-setup-popup.tsx +57 -0
  232. package/src/web/components/tunnels/named-tunnel/named-tunnel-step-reducer.ts +191 -0
  233. package/src/web/components/tunnels/named-tunnel/use-named-tunnel-setup.ts +212 -0
  234. package/src/web/components/tunnels/tunnel-manager-tab.tsx +4 -0
  235. package/src/web/hooks/use-global-events.ts +3 -1
  236. package/src/web/lib/api-named-tunnel.ts +54 -0
  237. package/src/web/lib/last-known-local-url.ts +23 -0
  238. package/src/web/stores/notification-store.ts +20 -1
  239. package/.spike/cdp-client.ts +0 -116
  240. package/.spike/cleanup-ppm-workspace.mjs +0 -44
  241. package/.spike/group-protected-probe.ts +0 -21
  242. package/.spike/pip-eval.ts +0 -17
  243. package/.spike/pip-page-helpers.js +0 -119
  244. package/.spike/pip-results-editor-glue.json +0 -105
  245. package/.spike/pip-results-editor.json +0 -158
  246. package/.spike/pip-results-input-isolation.json +0 -28
  247. package/.spike/pip-results-key-probe.json +0 -58
  248. package/.spike/pip-results-listener-survival.json +0 -98
  249. package/.spike/pip-results-listeners.json +0 -36
  250. package/.spike/pip-results-pagehide.json +0 -92
  251. package/.spike/pip-results-resize.json +0 -104
  252. package/.spike/pip-results-terminal-debug.json +0 -99
  253. package/.spike/pip-results-terminal-v2.json +0 -191
  254. package/.spike/pip-results-terminal.json +0 -220
  255. package/.spike/pip-results-xterm-trace.json +0 -73
  256. package/.spike/pip-spike-common.ts +0 -83
  257. package/.spike/pip-spike-editor-glue.ts +0 -82
  258. package/.spike/pip-spike-editor.ts +0 -129
  259. package/.spike/pip-spike-input-isolation.ts +0 -38
  260. package/.spike/pip-spike-key-probe.ts +0 -34
  261. package/.spike/pip-spike-listener-survival.ts +0 -54
  262. package/.spike/pip-spike-listeners.ts +0 -19
  263. package/.spike/pip-spike-pagehide.ts +0 -59
  264. package/.spike/pip-spike-resize.ts +0 -42
  265. package/.spike/pip-spike-setup.ts +0 -63
  266. package/.spike/pip-spike-terminal-debug.ts +0 -81
  267. package/.spike/pip-spike-terminal-v2.ts +0 -139
  268. package/.spike/pip-spike-terminal.ts +0 -169
  269. package/.spike/pip-spike-xterm-trace.ts +0 -36
  270. package/.spike/probe-drag-memo-error.mjs +0 -67
  271. package/.spike/read-dev-db.ts +0 -15
  272. package/.spike/s.err +0 -63
  273. package/.spike/scratch-editor-target.ts +0 -7
  274. package/.spike/smoke-unified-chrome-pip.mjs +0 -353
  275. package/.spike/tunnel.err +0 -63
  276. package/.spike/vite-restart.err +0 -663
  277. package/.spike/w.err +0 -571
  278. package/dist/web/assets/api-client-DTZEgjBQ.js +0 -1
  279. package/dist/web/assets/api-settings-kd1j4iR8.js +0 -1
  280. package/dist/web/assets/architecture-PBZL5I3N-8dCMT9r7.js +0 -1
  281. package/dist/web/assets/chat-tab-E3bf_V8X.js +0 -15
  282. package/dist/web/assets/code-editor-BUlM2gXk.js +0 -10
  283. package/dist/web/assets/explorer-body-9aBmyVpZ.js +0 -2
  284. package/dist/web/assets/explorer-window-content-DRtqoSPA.js +0 -1
  285. package/dist/web/assets/gitGraph-HDMCJU4V-2e_8dfbs.js +0 -1
  286. package/dist/web/assets/glide-data-grid-C4_zIneN.js +0 -138
  287. package/dist/web/assets/index-BImUaigO.js +0 -52
  288. package/dist/web/assets/index-CSfi6DSU.css +0 -2
  289. package/dist/web/assets/info-3K5VOQVL-BZi1Gha1.js +0 -1
  290. package/dist/web/assets/keybindings-store-CzV2sPls.js +0 -1
  291. package/dist/web/assets/markdown-renderer-CcbR33VG.js +0 -1
  292. package/dist/web/assets/mobile-explorer-sheet-SIwQXlwA.js +0 -1
  293. package/dist/web/assets/notification-store-DV5QtUTg.js +0 -1
  294. package/dist/web/assets/packet-RMMSAZCW-o5htEcin.js +0 -1
  295. package/dist/web/assets/pie-UPGHQEXC-BXAIFSAD.js +0 -1
  296. package/dist/web/assets/radar-KQ55EAFF-Dbt2Aebl.js +0 -1
  297. package/dist/web/assets/settings-tab-Dic6TKkU.js +0 -1
  298. package/dist/web/assets/system-monitor-body-iwGiCns9.js +0 -2
  299. package/dist/web/assets/system-monitor-tab-DdXQhEel.js +0 -1
  300. package/dist/web/assets/team-member-sheet-LkAFSCvb.js +0 -2
  301. package/dist/web/assets/treemap-KZPCXAKY-DUbnl9dz.js +0 -1
  302. package/dist/web/assets/video-preview-m0-3p7QZ.js +0 -1
  303. /package/dist/web/assets/{abap-C6nB04tn.js → abap-DGlrX_8G.js} +0 -0
  304. /package/dist/web/assets/{actionscript-3-Vx4rw2sC.js → actionscript-3-CUqRtUJE.js} +0 -0
  305. /package/dist/web/assets/{ada-Ccd8vM20.js → ada-CY3Spa33.js} +0 -0
  306. /package/dist/web/assets/{andromeeda-DnBX5xMg.js → andromeeda-Lxs2TJn7.js} +0 -0
  307. /package/dist/web/assets/{apache-B-9_sx0g.js → apache-DfxgGdgM.js} +0 -0
  308. /package/dist/web/assets/{apex-_wPVBYoL.js → apex-QVDF1dnI.js} +0 -0
  309. /package/dist/web/assets/{api-client-aQb5hHE5.js → api-client-oY1tC3tM.js} +0 -0
  310. /package/dist/web/assets/{applescript-CcvD-qr0.js → applescript-pwJ8QXh-.js} +0 -0
  311. /package/dist/web/assets/{apply-theme-BeLRfsSu.js → apply-theme-B_bMVL6a.js} +0 -0
  312. /package/dist/web/assets/{ara-C40Ztoms.js → ara-mPjeX5YX.js} +0 -0
  313. /package/dist/web/assets/{asciidoc-CybYkJV4.js → asciidoc-Bf7LsDkI.js} +0 -0
  314. /package/dist/web/assets/{asm-9eOKwzR0.js → asm-rRKC1OUx.js} +0 -0
  315. /package/dist/web/assets/{aurora-x-B5ZH4t7t.js → aurora-x-DwQr0DkG.js} +0 -0
  316. /package/dist/web/assets/{awk-Dqilob-2.js → awk-Bpt768fN.js} +0 -0
  317. /package/dist/web/assets/{ayu-dark-CPgRhf5r.js → ayu-dark-D9lwQHMs.js} +0 -0
  318. /package/dist/web/assets/{ayu-light-Do06Q52f.js → ayu-light-B4-ptrU5.js} +0 -0
  319. /package/dist/web/assets/{ayu-mirage-_BhxcrxY.js → ayu-mirage-DAyRzH5Q.js} +0 -0
  320. /package/dist/web/assets/{ballerina-DDwK54QW.js → ballerina-Cgdpj1HC.js} +0 -0
  321. /package/dist/web/assets/{bat-BGyGlzGk.js → bat-4FrN36S2.js} +0 -0
  322. /package/dist/web/assets/{beancount-CRWBdapI.js → beancount-DkcxQER3.js} +0 -0
  323. /package/dist/web/assets/{berry-DbSFn2gO.js → berry-Dnuut-Ml.js} +0 -0
  324. /package/dist/web/assets/{bibtex-QpsV9gm9.js → bibtex-CCDwmbuA.js} +0 -0
  325. /package/dist/web/assets/{bicep-CxS8CUve.js → bicep-BC0ryoGM.js} +0 -0
  326. /package/dist/web/assets/{bird2-CuZhQzYR.js → bird2-C50V_A-0.js} +0 -0
  327. /package/dist/web/assets/{c-9bnDqE3g.js → c-Ddorhq0U.js} +0 -0
  328. /package/dist/web/assets/{c3-JMZTrOhA.js → c3-DdIf5r9E.js} +0 -0
  329. /package/dist/web/assets/{cadence-DsDNayJS.js → cadence-s9pd1Wng.js} +0 -0
  330. /package/dist/web/assets/{can-open-in-ppm-BJfpynya.js → can-open-in-ppm-C6hZV1OP.js} +0 -0
  331. /package/dist/web/assets/{catppuccin-frappe-DYIKXXBe.js → catppuccin-frappe-CzJNTyu-.js} +0 -0
  332. /package/dist/web/assets/{catppuccin-latte-IYYOnUJ8.js → catppuccin-latte-BNpt-m7s.js} +0 -0
  333. /package/dist/web/assets/{catppuccin-macchiato-BrJ_7mfS.js → catppuccin-macchiato-FYGkfsJ5.js} +0 -0
  334. /package/dist/web/assets/{catppuccin-mocha-gzSu7v7-.js → catppuccin-mocha-it2g5D1q.js} +0 -0
  335. /package/dist/web/assets/{clarity-DLzsC0Hb.js → clarity-BVFBTjMe.js} +0 -0
  336. /package/dist/web/assets/{clipboard-7fw0Shic.js → clipboard-BWznymz7.js} +0 -0
  337. /package/dist/web/assets/{clojure-DS1BvoTt.js → clojure-BSYvXMI8.js} +0 -0
  338. /package/dist/web/assets/{cmake-CDvsJwYp.js → cmake-DGEqH-Np.js} +0 -0
  339. /package/dist/web/assets/{codeowners-BjsYiflJ.js → codeowners-D8FCOxWg.js} +0 -0
  340. /package/dist/web/assets/{codeql-CG-7ARat.js → codeql-COV0eluG.js} +0 -0
  341. /package/dist/web/assets/{common-lisp-DSO1Lbh9.js → common-lisp-xHnZUlgt.js} +0 -0
  342. /package/dist/web/assets/{coq-DYdh3oP_.js → coq-Cs_2i3Xg.js} +0 -0
  343. /package/dist/web/assets/{csharp-DxEBz5s0.js → csharp-B1ONB4PT.js} +0 -0
  344. /package/dist/web/assets/{css-dal3Q-8C.js → css-BgGQbvrZ.js} +0 -0
  345. /package/dist/web/assets/{csv-CpqjMGiA.js → csv-CNHmQBzs.js} +0 -0
  346. /package/dist/web/assets/{csv-parser-3umBA4NY.js → csv-parser-DWR24J17.js} +0 -0
  347. /package/dist/web/assets/{cue-DinoJ_5k.js → cue-ZXAKzwIy.js} +0 -0
  348. /package/dist/web/assets/{cypher-DzxqmkUW.js → cypher-4PL5bmT5.js} +0 -0
  349. /package/dist/web/assets/{d-BxNwJuEC.js → d-CEsV3RT2.js} +0 -0
  350. /package/dist/web/assets/{dark-plus-Clmv3V-0.js → dark-plus-NtFnYSDz.js} +0 -0
  351. /package/dist/web/assets/{dart-BWVtXD35.js → dart-CKHn4mDf.js} +0 -0
  352. /package/dist/web/assets/{data-grid-types-B4n51Fck.js → data-grid-types-CxU8oo-j.js} +0 -0
  353. /package/dist/web/assets/{dax-DsImuWgJ.js → dax-Cmkj1I_M.js} +0 -0
  354. /package/dist/web/assets/{desktop-B0jJuG2r.js → desktop-DJLalvPQ.js} +0 -0
  355. /package/dist/web/assets/{diff-CWqAAxoE.js → diff-BnS2wpj6.js} +0 -0
  356. /package/dist/web/assets/{dist-C0eNNfbt.js → dist-CuIdRyUB.js} +0 -0
  357. /package/dist/web/assets/{dist-B-EXdSYE.js → dist-uYjs3Wv6.js} +0 -0
  358. /package/dist/web/assets/{docker-CYFCJdIL.js → docker-CovNy7ml.js} +0 -0
  359. /package/dist/web/assets/{dotenv-CKDUjURg.js → dotenv-Gh4w3I6B.js} +0 -0
  360. /package/dist/web/assets/{dracula-CSoPspHE.js → dracula-NF0tAHXl.js} +0 -0
  361. /package/dist/web/assets/{dracula-soft-BuFjw5L1.js → dracula-soft-Cj_qBurK.js} +0 -0
  362. /package/dist/web/assets/{dream-maker-B6PdDRZu.js → dream-maker-CRuZPcl7.js} +0 -0
  363. /package/dist/web/assets/{emacs-lisp-CMcXvD0G.js → emacs-lisp-BACmC9qj.js} +0 -0
  364. /package/dist/web/assets/{everforest-dark-cU8-wYzi.js → everforest-dark-Dd9av4QG.js} +0 -0
  365. /package/dist/web/assets/{everforest-light-KhorllqK.js → everforest-light-C-jsss-B.js} +0 -0
  366. /package/dist/web/assets/{external-link-B8BynhvY.js → external-link-B6Hl0U4X.js} +0 -0
  367. /package/dist/web/assets/{fennel-BCELZK87.js → fennel-BJA9XnL8.js} +0 -0
  368. /package/dist/web/assets/{file-exclamation-point-CZ4DiR75.js → file-exclamation-point-JzhTU2TX.js} +0 -0
  369. /package/dist/web/assets/{fish-BQc0y_jy.js → fish-CKlhNSc2.js} +0 -0
  370. /package/dist/web/assets/{fluent-BTINnwF6.js → fluent-wfglRk5D.js} +0 -0
  371. /package/dist/web/assets/{folder-symlink-B8XrtvQK.js → folder-symlink-Dx1hOk8X.js} +0 -0
  372. /package/dist/web/assets/{format-bytes-WVcFxJuT.js → format-bytes-utwHMTry.js} +0 -0
  373. /package/dist/web/assets/{fortran-free-form-BQim9wDz.js → fortran-free-form-BlXCdid3.js} +0 -0
  374. /package/dist/web/assets/{gdscript-03w5u8un.js → gdscript-BwAVG6Et.js} +0 -0
  375. /package/dist/web/assets/{gdshader-Dp2daNzU.js → gdshader-DPc_T7ib.js} +0 -0
  376. /package/dist/web/assets/{genie-CoNcjPiD.js → genie-B-zZSLCX.js} +0 -0
  377. /package/dist/web/assets/{gherkin-NrPOSPQL.js → gherkin-CJ0ajpGs.js} +0 -0
  378. /package/dist/web/assets/{github-dark-z4RE9ZqA.js → github-dark-Dz8ZkzSP.js} +0 -0
  379. /package/dist/web/assets/{github-dark-default-DOKw-1cI.js → github-dark-default-CNUYo_kp.js} +0 -0
  380. /package/dist/web/assets/{github-dark-dimmed-DJRNMkEA.js → github-dark-dimmed-241z_Ycx.js} +0 -0
  381. /package/dist/web/assets/{github-dark-high-contrast-Bj7jJ_Gs.js → github-dark-high-contrast-7r6yZZYH.js} +0 -0
  382. /package/dist/web/assets/{github-light-B4k_yMFu.js → github-light-C8gmZn-D.js} +0 -0
  383. /package/dist/web/assets/{github-light-default-BHc-Uzhs.js → github-light-default-GAEgq1eA.js} +0 -0
  384. /package/dist/web/assets/{github-light-high-contrast-CHisIywL.js → github-light-high-contrast-3z91352E.js} +0 -0
  385. /package/dist/web/assets/{gleam-CfbypZ4q.js → gleam-C7vxW5zd.js} +0 -0
  386. /package/dist/web/assets/{gn-YoAjyhJa.js → gn-CyJIXwHP.js} +0 -0
  387. /package/dist/web/assets/{gnuplot-xVkc1f1c.js → gnuplot-CqLbGgPd.js} +0 -0
  388. /package/dist/web/assets/{go-GPCwP3Gu.js → go-DdDcK9aX.js} +0 -0
  389. /package/dist/web/assets/{groovy-Crh4Yww9.js → groovy-UYHggEqH.js} +0 -0
  390. /package/dist/web/assets/{gruvbox-dark-hard-BluUFuDS.js → gruvbox-dark-hard-B4ierkJn.js} +0 -0
  391. /package/dist/web/assets/{gruvbox-dark-medium-Cxk1FWQp.js → gruvbox-dark-medium-DYwkDSZ6.js} +0 -0
  392. /package/dist/web/assets/{gruvbox-dark-soft-CHXMiFmj.js → gruvbox-dark-soft-CVL4P-Lz.js} +0 -0
  393. /package/dist/web/assets/{gruvbox-light-hard-B6eKPjAD.js → gruvbox-light-hard-BJ0LewUZ.js} +0 -0
  394. /package/dist/web/assets/{gruvbox-light-medium-pDwMm1ut.js → gruvbox-light-medium-CaqqjeGJ.js} +0 -0
  395. /package/dist/web/assets/{gruvbox-light-soft-Cxu6kHqK.js → gruvbox-light-soft-ByKMoVNr.js} +0 -0
  396. /package/dist/web/assets/{haskell-C6JKHjbK.js → haskell-BilYRVPp.js} +0 -0
  397. /package/dist/web/assets/{haxe-BuBNdF0a.js → haxe-Brs9Bj1s.js} +0 -0
  398. /package/dist/web/assets/{hcl-DZpDdGj2.js → hcl-ClrZpol-.js} +0 -0
  399. /package/dist/web/assets/{hjson-CBkhYRuo.js → hjson-9PvHnYMX.js} +0 -0
  400. /package/dist/web/assets/{hlsl-C5nMxnp9.js → hlsl-BbBk4vqV.js} +0 -0
  401. /package/dist/web/assets/{horizon-VAFvA6R6.js → horizon-E5Py0cny.js} +0 -0
  402. /package/dist/web/assets/{horizon-bright-BC0xn7T3.js → horizon-bright-DVCsNGEk.js} +0 -0
  403. /package/dist/web/assets/{houston-BxrUivmz.js → houston-JdFEax9Y.js} +0 -0
  404. /package/dist/web/assets/{hy-DLtOXoaH.js → hy-W_W3tLKT.js} +0 -0
  405. /package/dist/web/assets/{image-gallery-Gnf7TdCR.js → image-gallery-5IURd6db.js} +0 -0
  406. /package/dist/web/assets/{imba-BdpFXM2W.js → imba-CfAqJz7T.js} +0 -0
  407. /package/dist/web/assets/{ini-BInJO_T0.js → ini-C_3gvKWs.js} +0 -0
  408. /package/dist/web/assets/{java-Dxuddnkb.js → java-CKqtXZ-j.js} +0 -0
  409. /package/dist/web/assets/{javascript-CVamJfLY.js → javascript-C7gSEfae.js} +0 -0
  410. /package/dist/web/assets/{json-BLZ0ozYk.js → json-BoN6e11T.js} +0 -0
  411. /package/dist/web/assets/{json5-BnXzmMKs.js → json5-CgE7C8HW.js} +0 -0
  412. /package/dist/web/assets/{jsonc-CSgkSga7.js → jsonc-DjyoattY.js} +0 -0
  413. /package/dist/web/assets/{jsonl-CY5W2nF2.js → jsonl-lI82wGSw.js} +0 -0
  414. /package/dist/web/assets/{jsonnet-CEJYH3sF.js → jsonnet-CszEI8va.js} +0 -0
  415. /package/dist/web/assets/{jssm-CsJc7Uhk.js → jssm-CZXDlszb.js} +0 -0
  416. /package/dist/web/assets/{jsx-jCiRaHU7.js → jsx-BeRz0eEz.js} +0 -0
  417. /package/dist/web/assets/{kanagawa-dragon-DfoA_GxX.js → kanagawa-dragon-BOmnUiyd.js} +0 -0
  418. /package/dist/web/assets/{kanagawa-lotus-BOLYJpWd.js → kanagawa-lotus-ffU_P5w-.js} +0 -0
  419. /package/dist/web/assets/{kanagawa-wave-DfKlbT1G.js → kanagawa-wave-DKTJZrMu.js} +0 -0
  420. /package/dist/web/assets/{kdl-CmssIFTi.js → kdl-BWECJveH.js} +0 -0
  421. /package/dist/web/assets/{kotlin-BRsNgp6x.js → kotlin-DpVwBCSt.js} +0 -0
  422. /package/dist/web/assets/{kusto-T8X9jUab.js → kusto-BgVqjUZA.js} +0 -0
  423. /package/dist/web/assets/{laserwave-DkJMVJ8Z.js → laserwave-CEVCi8em.js} +0 -0
  424. /package/dist/web/assets/{lean-C65KGVPq.js → lean-CGyfRhLJ.js} +0 -0
  425. /package/dist/web/assets/{less-exIPdDlf.js → less-B0_H10Ku.js} +0 -0
  426. /package/dist/web/assets/{lib-mC1NZfuw.js → lib-hrC3bruJ.js} +0 -0
  427. /package/dist/web/assets/{libesm-DSutUtl1.js → libesm-DVpFmwJu.js} +0 -0
  428. /package/dist/web/assets/{light-plus-DiHUXAZt.js → light-plus-DqzMqPID.js} +0 -0
  429. /package/dist/web/assets/{llvm-CJBnEzFM.js → llvm-9ucnfNiF.js} +0 -0
  430. /package/dist/web/assets/{loader-circle-gSPVxfvH.js → loader-circle-Dpqcv0eS.js} +0 -0
  431. /package/dist/web/assets/{lock-Did-87UV.js → lock-DldbT31x.js} +0 -0
  432. /package/dist/web/assets/{log-DxMyUMuP.js → log-m6A2dOSj.js} +0 -0
  433. /package/dist/web/assets/{logo-CC9NKzca.js → logo-ByPcsC9P.js} +0 -0
  434. /package/dist/web/assets/{luau-Bw10I6zf.js → luau-DFCo8nBn.js} +0 -0
  435. /package/dist/web/assets/{make-C_6M90m6.js → make-C90w3MeA.js} +0 -0
  436. /package/dist/web/assets/{markdown-bR9_R-LF.js → markdown-DT0uywZG.js} +0 -0
  437. /package/dist/web/assets/{material-theme-BUx2Qujn.js → material-theme-BVUO93tJ.js} +0 -0
  438. /package/dist/web/assets/{material-theme-darker-CRJrPgKm.js → material-theme-darker-xXgGDwnF.js} +0 -0
  439. /package/dist/web/assets/{material-theme-lighter-CUAYppPa.js → material-theme-lighter-BjStPzWB.js} +0 -0
  440. /package/dist/web/assets/{material-theme-ocean-DuINF1fg.js → material-theme-ocean-wFmSiKjy.js} +0 -0
  441. /package/dist/web/assets/{material-theme-palenight-W6_icGCj.js → material-theme-palenight-e-0CtRoe.js} +0 -0
  442. /package/dist/web/assets/{matlab-rfqn_b3z.js → matlab-BNaNQAUH.js} +0 -0
  443. /package/dist/web/assets/{mdx-Bh1B_YOJ.js → mdx-DfpVWAqO.js} +0 -0
  444. /package/dist/web/assets/{mermaid-Dxf6Ya2k.js → mermaid-Bpq7wFCP.js} +0 -0
  445. /package/dist/web/assets/{min-dark-CivZ2L0h.js → min-dark-CL2Y0WH6.js} +0 -0
  446. /package/dist/web/assets/{min-light-B1Ykqtma.js → min-light-DOgr_IdP.js} +0 -0
  447. /package/dist/web/assets/{mipsasm-DynHaM0d.js → mipsasm-C9ie2zlB.js} +0 -0
  448. /package/dist/web/assets/{mojo-Clw5PbGH.js → mojo-Md2A2sJy.js} +0 -0
  449. /package/dist/web/assets/{monitor-Dv8vn_6O.js → monitor-4vWfqzuN.js} +0 -0
  450. /package/dist/web/assets/{monokai-DFIooFZT.js → monokai-nbXIEySB.js} +0 -0
  451. /package/dist/web/assets/{moonbit-DnBSZWGM.js → moonbit-CJ-T-s4A.js} +0 -0
  452. /package/dist/web/assets/{move-CCcL2PfL.js → move-DwEehLIK.js} +0 -0
  453. /package/dist/web/assets/{narrat-BDarg5Lk.js → narrat-CuF4sIKr.js} +0 -0
  454. /package/dist/web/assets/{nextflow-groovy-DrZOeCNW.js → nextflow-groovy-1dYhfPfq.js} +0 -0
  455. /package/dist/web/assets/{night-owl-BnZZCK7v.js → night-owl-gZS5mfzY.js} +0 -0
  456. /package/dist/web/assets/{night-owl-light-CEwBsVHS.js → night-owl-light-DDAster5.js} +0 -0
  457. /package/dist/web/assets/{nix-amCzOPMR.js → nix-BlbEYs2c.js} +0 -0
  458. /package/dist/web/assets/{nord-BIs2BC6q.js → nord-BRiPb8Vy.js} +0 -0
  459. /package/dist/web/assets/{nushell-Y02fo4yw.js → nushell-DgWicB1i.js} +0 -0
  460. /package/dist/web/assets/{objective-c-7xOZtWW1.js → objective-c-D8mPZ42Y.js} +0 -0
  461. /package/dist/web/assets/{objective-cpp-eVtjUvVB.js → objective-cpp-B0pNXzuj.js} +0 -0
  462. /package/dist/web/assets/{ocaml-Bi6ZwqG4.js → ocaml-lQd7aK5d.js} +0 -0
  463. /package/dist/web/assets/{odin-8xf1Y0S9.js → odin-CxtIOBjm.js} +0 -0
  464. /package/dist/web/assets/{one-dark-pro-hVv-_y_b.js → one-dark-pro-T_UFnWfe.js} +0 -0
  465. /package/dist/web/assets/{one-light-CJJ3MtHt.js → one-light-LBVqwyV-.js} +0 -0
  466. /package/dist/web/assets/{openscad-B2HcywLk.js → openscad-C5dnS6J7.js} +0 -0
  467. /package/dist/web/assets/{pascal-C7fllV_7.js → pascal-CmWCWQML.js} +0 -0
  468. /package/dist/web/assets/{pkl-qvLC1IWP.js → pkl-BWWOtDQk.js} +0 -0
  469. /package/dist/web/assets/{plastic-BT1wHZv2.js → plastic-ekhupckF.js} +0 -0
  470. /package/dist/web/assets/{play-4MZi1Axp.js → play-CpCAoQRZ.js} +0 -0
  471. /package/dist/web/assets/{plsql-1MsmdmJD.js → plsql-BPsDHXx4.js} +0 -0
  472. /package/dist/web/assets/{plus-BhMZqFsN.js → plus-BR0qewJI.js} +0 -0
  473. /package/dist/web/assets/{po-BigskytD.js → po-BX2FiuW2.js} +0 -0
  474. /package/dist/web/assets/{poimandres-DuklniF7.js → poimandres-DzXOdZcN.js} +0 -0
  475. /package/dist/web/assets/{polar-e2pjN_sp.js → polar-DDRXgJzG.js} +0 -0
  476. /package/dist/web/assets/{portal-container-context-Cm5HipFr.js → portal-container-context-a399Hd9F.js} +0 -0
  477. /package/dist/web/assets/{postcss-DtAeYjWw.js → postcss-BHW6XBhx.js} +0 -0
  478. /package/dist/web/assets/{powerquery-Cr2PtehI.js → powerquery-B89c2NBb.js} +0 -0
  479. /package/dist/web/assets/{powershell-BxFTGLJ4.js → powershell-Dvxrd3Tu.js} +0 -0
  480. /package/dist/web/assets/{prisma-COWJiwdZ.js → prisma-lMK8EFLU.js} +0 -0
  481. /package/dist/web/assets/{prolog-DFvGKRx6.js → prolog-D0YrtMG4.js} +0 -0
  482. /package/dist/web/assets/{proto-CcK80lFt.js → proto-J0mM25aw.js} +0 -0
  483. /package/dist/web/assets/{puppet-BF60bZ4F.js → puppet-CUT0xkhh.js} +0 -0
  484. /package/dist/web/assets/{purescript-zL_69MzU.js → purescript-CoJWSGRp.js} +0 -0
  485. /package/dist/web/assets/{python-CIwKhfb_.js → python-BBrmuz6P.js} +0 -0
  486. /package/dist/web/assets/{qmldir-CXNe04Lo.js → qmldir-CUtzs4Q7.js} +0 -0
  487. /package/dist/web/assets/{qss-C8lAWe6G.js → qss-Dm1RZ8aL.js} +0 -0
  488. /package/dist/web/assets/{r-CL5ZVL3_.js → r-BGP7qZTe.js} +0 -0
  489. /package/dist/web/assets/{racket-BBfh0uh0.js → racket-K_6U1lqJ.js} +0 -0
  490. /package/dist/web/assets/{raku-o6E8R5Q3.js → raku-bNSiZeW_.js} +0 -0
  491. /package/dist/web/assets/{react-CBTnT4sY.js → react-X4jUntEf.js} +0 -0
  492. /package/dist/web/assets/{red-GomRF2Xp.js → red-uVeIEF0f.js} +0 -0
  493. /package/dist/web/assets/{refresh-cw-B06yaBrW.js → refresh-cw-B9iv7csb.js} +0 -0
  494. /package/dist/web/assets/{reg-_ffDIvx9.js → reg-DSm9GWjh.js} +0 -0
  495. /package/dist/web/assets/{regexp-Bl5sF65W.js → regexp-CljRm_j_.js} +0 -0
  496. /package/dist/web/assets/{rel-DgMdqDuj.js → rel-d3JcopZg.js} +0 -0
  497. /package/dist/web/assets/{resolve-theme-CRt_7wpd.js → resolve-theme-DLKmm-lE.js} +0 -0
  498. /package/dist/web/assets/{riscv-8b3-Ye4X.js → riscv-CJmaELjT.js} +0 -0
  499. /package/dist/web/assets/{ron-DrmU1KHP.js → ron-D0g9B1rW.js} +0 -0
  500. /package/dist/web/assets/{rose-pine-C_-E2tF1.js → rose-pine-DOrD2BSH.js} +0 -0
  501. /package/dist/web/assets/{rose-pine-dawn-DEfhNlFH.js → rose-pine-dawn-CzZQ-LCF.js} +0 -0
  502. /package/dist/web/assets/{rose-pine-moon-BdvX3gdn.js → rose-pine-moon-CdmsYp7C.js} +0 -0
  503. /package/dist/web/assets/{rosmsg-B6GhGpd5.js → rosmsg-CmDth6pO.js} +0 -0
  504. /package/dist/web/assets/{rotate-ccw-COXu_9oj.js → rotate-ccw-DnuPzJRE.js} +0 -0
  505. /package/dist/web/assets/{rust-DmC97M1-.js → rust-DGdP6jiR.js} +0 -0
  506. /package/dist/web/assets/{sass-B0tJOHLM.js → sass-Dkgt2FKZ.js} +0 -0
  507. /package/dist/web/assets/{save-CtIGOjmx.js → save-DxonD4y1.js} +0 -0
  508. /package/dist/web/assets/{scala-n8zaFOXv.js → scala-BQLTON6C.js} +0 -0
  509. /package/dist/web/assets/{scheme-BKD9ztBU.js → scheme-DKlxUGCi.js} +0 -0
  510. /package/dist/web/assets/{sdbl-D8gB5-rS.js → sdbl-C3iZJQeZ.js} +0 -0
  511. /package/dist/web/assets/{send-BlyNJAzy.js → send-B-t5Mz26.js} +0 -0
  512. /package/dist/web/assets/{shallow-DYo6goJ4.js → shallow-jwPzEunk.js} +0 -0
  513. /package/dist/web/assets/{shellscript-BfXlf_Ao.js → shellscript-BRu-ZQAx.js} +0 -0
  514. /package/dist/web/assets/{shield-check-B0iGUiOK.js → shield-check-CdTiK1j2.js} +0 -0
  515. /package/dist/web/assets/{shield-off-BNLWBhcq.js → shield-off-DuetkXKM.js} +0 -0
  516. /package/dist/web/assets/{slack-dark-CylEddse.js → slack-dark-qkm_u2zz.js} +0 -0
  517. /package/dist/web/assets/{slack-ochin-w8wg8vuC.js → slack-ochin-BP8_8e4m.js} +0 -0
  518. /package/dist/web/assets/{smalltalk-hiAXA64u.js → smalltalk-Bnz4gt07.js} +0 -0
  519. /package/dist/web/assets/{snazzy-light-BwlV3Xty.js → snazzy-light-fbPZg5io.js} +0 -0
  520. /package/dist/web/assets/{solarized-dark-vmNGdykz.js → solarized-dark-CM0vTRoi.js} +0 -0
  521. /package/dist/web/assets/{solarized-light-DGv_0JXq.js → solarized-light-C4_W9mvs.js} +0 -0
  522. /package/dist/web/assets/{solidity-Y7QSH0B1.js → solidity-Bz6v1PoD.js} +0 -0
  523. /package/dist/web/assets/{splunk-BtgpLjHi.js → splunk-DyNxu-0i.js} +0 -0
  524. /package/dist/web/assets/{sql-CRHYhOia.js → sql-DXRL1gw1.js} +0 -0
  525. /package/dist/web/assets/{ssh-config-DOqSs3au.js → ssh-config-2z1QHuOG.js} +0 -0
  526. /package/dist/web/assets/{stylus-crCAEaBT.js → stylus-D4I-VaeY.js} +0 -0
  527. /package/dist/web/assets/{swift-eE3rT7TC.js → swift-C_2G-tIc.js} +0 -0
  528. /package/dist/web/assets/{synthwave-84-BWy14LBX.js → synthwave-84-osBjChRP.js} +0 -0
  529. /package/dist/web/assets/{system-verilog-DC0-DZM4.js → system-verilog-zQP2qPNU.js} +0 -0
  530. /package/dist/web/assets/{systemd-to5p6N8I.js → systemd-UGfjRSBM.js} +0 -0
  531. /package/dist/web/assets/{table-Bbc783ko.js → table-FLU8ei8b.js} +0 -0
  532. /package/dist/web/assets/{talonscript-DoTcU8wm.js → talonscript-C1XrFPwo.js} +0 -0
  533. /package/dist/web/assets/{tasl-cNZvUs95.js → tasl-B5raVn43.js} +0 -0
  534. /package/dist/web/assets/{tcl-mZE8sZH8.js → tcl-3-vbeMIc.js} +0 -0
  535. /package/dist/web/assets/{terraform-CqHPpIfu.js → terraform-a8VXZDm9.js} +0 -0
  536. /package/dist/web/assets/{text-wrap-CBT4Gxtg.js → text-wrap-B05VGRa-.js} +0 -0
  537. /package/dist/web/assets/{tokyo-night-Tp2rTIZd.js → tokyo-night-4SRhf-Hz.js} +0 -0
  538. /package/dist/web/assets/{toml-CU_vscgn.js → toml-B4N0i8wT.js} +0 -0
  539. /package/dist/web/assets/{trash-2-Bk4yYlck.js → trash-2-CTXlTflF.js} +0 -0
  540. /package/dist/web/assets/{triangle-alert-B8EYecpe.js → triangle-alert-BRq0VAfd.js} +0 -0
  541. /package/dist/web/assets/{tsv-ik7iFB9D.js → tsv-DA5k9Lvw.js} +0 -0
  542. /package/dist/web/assets/{tsx-BMvvMKiv.js → tsx-D9SZ8owC.js} +0 -0
  543. /package/dist/web/assets/{turtle-DBqKCq9o.js → turtle-BTHTvyY_.js} +0 -0
  544. /package/dist/web/assets/{typescript-DXJDmMZZ.js → typescript-DYzV9p5L.js} +0 -0
  545. /package/dist/web/assets/{typespec-CBseCMtZ.js → typespec-BC15eh7F.js} +0 -0
  546. /package/dist/web/assets/{typst-4oY25U9y.js → typst-BJUqzA6D.js} +0 -0
  547. /package/dist/web/assets/{use-is-mobile-D1weanbj.js → use-is-mobile-DFWViA4S.js} +0 -0
  548. /package/dist/web/assets/{utils-BNRH507E.js → utils-C9OjCrou.js} +0 -0
  549. /package/dist/web/assets/{v-BXaZ_1oy.js → v-50Lps6oA.js} +0 -0
  550. /package/dist/web/assets/{vala-BImWJE7z.js → vala-8wiUvvrD.js} +0 -0
  551. /package/dist/web/assets/{vb-CLfj2_sy.js → vb-BlgPLt6B.js} +0 -0
  552. /package/dist/web/assets/{vendor-xterm-_yyu5n32.js → vendor-xterm-BZOrwF_F.js} +0 -0
  553. /package/dist/web/assets/{verilog-BWa8Ed2b.js → verilog-CD9pVW5p.js} +0 -0
  554. /package/dist/web/assets/{vesper-BGj1cg6m.js → vesper-BrivW4PT.js} +0 -0
  555. /package/dist/web/assets/{vhdl-mByK7mlx.js → vhdl-Bunxfa7N.js} +0 -0
  556. /package/dist/web/assets/{viml-CugmlW5g.js → viml-DndUb2qM.js} +0 -0
  557. /package/dist/web/assets/{vitesse-black-vPdpy9TL.js → vitesse-black-BurZSkxW.js} +0 -0
  558. /package/dist/web/assets/{vitesse-dark-BuQK3dUh.js → vitesse-dark-8UShspzC.js} +0 -0
  559. /package/dist/web/assets/{vitesse-light-B3nz1XL9.js → vitesse-light-DghCAZ90.js} +0 -0
  560. /package/dist/web/assets/{vyper-DH_GTIHG.js → vyper-b-Clr-8u.js} +0 -0
  561. /package/dist/web/assets/{wasm-DfVbVJlW.js → wasm-C5v2T06Y.js} +0 -0
  562. /package/dist/web/assets/{wasm-C-LF9GjX.js → wasm-CpcKStkw.js} +0 -0
  563. /package/dist/web/assets/{wenyan-CzQkHyHx.js → wenyan-Dz2srLZR.js} +0 -0
  564. /package/dist/web/assets/{wgsl-Du_M1DW9.js → wgsl-CeD1-dRb.js} +0 -0
  565. /package/dist/web/assets/{wikitext-BWN_w5S7.js → wikitext-CyeS-9FH.js} +0 -0
  566. /package/dist/web/assets/{wit-BR13v5HD.js → wit-Kr-q-qBQ.js} +0 -0
  567. /package/dist/web/assets/{wolfram-BoXxp_Xl.js → wolfram-BKm8bmln.js} +0 -0
  568. /package/dist/web/assets/{x-nhriOX9o.js → x-YDu4m2Iq.js} +0 -0
  569. /package/dist/web/assets/{yaml-DpR_EF-d.js → yaml-2XSxomjM.js} +0 -0
  570. /package/dist/web/assets/{zenscript-C-EdUtUd.js → zenscript-CKIS34vf.js} +0 -0
  571. /package/dist/web/assets/{zig-BD4eA5nU.js → zig-DdHGNllX.js} +0 -0
@@ -3,78 +3,56 @@
3
3
  ## Prerequisites
4
4
 
5
5
  ### System Requirements
6
- - **OS:** Linux or macOS (Windows support planned for v3)
6
+ - **OS:** macOS, Linux or Windows (all three are supported targets)
7
7
  - **RAM:** 512 MB minimum, 2 GB recommended
8
- - **Disk:** 500 MB for binary + dependencies
9
- - **Network:** localhost only (single-machine deployment)
8
+ - **Disk:** ~500 MB for the binary, plus ~15 MB for the cloudflared binary PPM downloads on first start
9
+ - **Network:** localhost is enough; internet access is needed for the tunnel and for AI providers
10
10
 
11
11
  ### Required Software
12
- - **Bun:** v1.3.6 or later (https://bun.sh)
13
- - **Git:** v2.0+ (for git operations in chat/CLI)
14
- - **Node.js or Bun:** For running npm/node commands in terminal
12
+ - **Bun** v1.3.6+ (https://bun.sh) — **only** for the `bunx`/`bun add -g`/from-source paths. The
13
+ released binary bundles its own runtime and needs nothing installed.
14
+ - **Git** v2.0+ for the git features
15
+ - **Claude Code** (`claude` CLI, logged in) — for AI chat via the Claude Agent SDK
15
16
 
16
17
  ### Optional
17
- - **ngrok or similar:** For exposing to network (not recommended for production)
18
- - **systemd or launchd:** For daemon management
18
+ - `@openai/codex` or `cursor-agent` on PATH each registers an extra AI provider when present
19
+ - `ffmpeg` on-the-fly transcoding for video formats the browser cannot play
20
+ - `psql` / a PostgreSQL server — for the Postgres side of the database viewer
19
21
 
20
22
  ---
21
23
 
22
24
  ## Installation
23
25
 
24
- ### Option 1: Build from Source (Development)
26
+ ### Option 1: Installer script (recommended)
25
27
 
26
- #### Prerequisites
28
+ **macOS / Linux:**
27
29
  ```bash
28
- # Check Bun is installed
29
- bun --version # Should be 1.3.6+
30
-
31
- # Clone repository
32
- git clone https://github.com/hienlh/ppm.git
33
- cd ppm
34
- ```
35
-
36
- #### Install & Build
37
- ```bash
38
- # Install dependencies
39
- bun install
40
-
41
- # Build frontend + CLI binary
42
- bun run build
43
-
44
- # Output: dist/ppm (compiled binary)
30
+ curl -fsSL https://ppm.sh/install | sh
45
31
  ```
46
32
 
47
- #### Run
48
- ```bash
49
- # Run directly from source (development)
50
- bun run start
51
-
52
- # Or use compiled binary
53
- ./dist/ppm start
33
+ **Windows (PowerShell):**
34
+ ```powershell
35
+ irm https://ppm.sh/install.ps1 | iex
54
36
  ```
55
37
 
56
- ---
38
+ Downloads the matching release archive, unpacks it to `~/.ppm/bin` (override with `PPM_INSTALL_DIR`)
39
+ and adds it to PATH. Re-run to upgrade, or use `ppm upgrade`.
57
40
 
58
- ### Option 2: Pre-built Binary (Production)
41
+ ### Option 2: Via Bun
59
42
 
60
- #### Download
61
43
  ```bash
62
- # Download latest release from GitHub Releases
63
- wget https://github.com/hienlh/ppm/releases/download/v2.0/ppm-macos-x64
64
- chmod +x ppm-macos-x64
65
-
66
- # Or for Linux
67
- wget https://github.com/hienlh/ppm/releases/download/v2.0/ppm-linux-x64
68
- chmod +x ppm-linux-x64
44
+ bunx @hienlh/ppm start # run without installing
45
+ bun add -g @hienlh/ppm # or install globally
69
46
  ```
70
47
 
71
- #### Run
72
- ```bash
73
- # Copy to PATH for global access
74
- sudo cp ppm-macos-x64 /usr/local/bin/ppm
48
+ ### Option 3: Build from source (development)
75
49
 
76
- # Verify installation
77
- ppm --version
50
+ ```bash
51
+ git clone https://github.com/hienlh/ppm.git
52
+ cd ppm
53
+ bun install
54
+ bun run build # frontend + compiled binary → dist/ppm
55
+ ./dist/ppm start
78
56
  ```
79
57
 
80
58
  ---
@@ -84,321 +62,243 @@ ppm --version
84
62
  ### Initial Setup
85
63
 
86
64
  ```bash
87
- # Generate config and scan for git repositories
88
- ppm init
89
-
90
- # Output: ~/.ppm/ppm.db (SQLite database)
91
- # Auto-generates auth token
65
+ ppm init # interactive wizard
66
+ ppm init -y # non-interactive: defaults + auto-generated password
92
67
  ```
93
68
 
69
+ Writes `~/.ppm/ppm.db` (SQLite) and generates an auth token. `ppm start` runs the wizard
70
+ automatically if no config exists.
71
+
94
72
  ### Dev vs Production Config
95
73
 
96
- Config is stored in **SQLite** databases:
74
+ | Profile | Database | Conventional port |
75
+ |---|---|---|
76
+ | Production | `~/.ppm/ppm.db` | 3210 (what `ppm init` writes) |
77
+ | Development | `~/.ppm/ppm.dev.db` | 8081 |
97
78
 
98
- - **Production:** `~/.ppm/ppm.db` port **8080** (default)
99
- - **Development:** `~/.ppm/ppm.dev.db` port **8081**
79
+ `bun dev:server` selects the dev database via the `dev` profile; `ppm start --profile dev` does the
80
+ same for a compiled binary. On a new machine run `ppm init`, then `ppm config set port 8081` for dev.
100
81
 
101
- `bun dev:server` automatically uses the dev database. On a new machine, run `ppm init` then `ppm config set port 8081` for dev.
82
+ > Both databases live in the same directory, and so does `.server-port`. Running `dev:server` while
83
+ > production is up can therefore steal the tunnel's route — stop one before starting the other.
102
84
 
103
85
  ### Config Structure (SQLite)
104
86
 
105
- Config is stored in the `config` table as key-value pairs. Equivalent settings:
87
+ Config lives in the `config` table as dotted key/value pairs. The shape is defined by
88
+ `DEFAULT_CONFIG` in `src/types/config.ts` — that struct is the source of truth:
106
89
 
107
90
  ```
108
- port = 8080
109
- host = 0.0.0.0
110
- auth.enabled = true
111
- auth.token = "auto-generated-random-token"
112
- providers.default = "claude-agent-sdk"
91
+ port 8080 ← struct default; `ppm init` writes 3210
92
+ host 0.0.0.0
93
+ theme.style / theme.mode aurora / system
94
+ auth.enabled / auth.token true / auto-generated
95
+ ai.default_provider claude
96
+ ai.providers.claude.model claude-opus-5
97
+ ai.providers.claude.effort high
98
+ ai.providers.claude.permission_mode bypassPermissions
113
99
  ```
114
100
 
115
- Projects are stored in a separate `projects` table with `name` and `path` columns.
101
+ Projects, accounts, sessions, schedules, usage and audit logs each live in their own table.
102
+
103
+ Never build a `~/.ppm` path by hand in service code — import `getPpmDir()` from
104
+ `src/services/ppm-dir.ts` so `PPM_HOME` can redirect it in tests.
116
105
 
117
106
  ### Customize Configuration
118
107
 
119
- #### Change Port
120
108
  ```bash
121
- # Edit ppm.yaml manually
109
+ # Port
122
110
  ppm config set port 3000
111
+ ppm start -p 3000 # or per-start
123
112
 
124
- # Or start with custom port (CLI flag)
125
- ppm start --port 3000
126
- ```
127
-
128
- #### Add/Remove Projects
129
- ```bash
130
- # Add project
113
+ # Projects
131
114
  ppm projects add my-project /path/to/my-project
132
-
133
- # List projects
134
115
  ppm projects list
135
-
136
- # Remove project
137
116
  ppm projects remove my-project
138
- ```
139
117
 
140
- #### Set AI Provider
141
- ```bash
142
- # Use mock provider (for testing)
143
- ppm config set providers.default mock
118
+ # AI provider / model
119
+ ppm config set ai.default_provider claude # claude | codex | cursor
120
+ ppm config set ai.providers.claude.model claude-opus-5
144
121
 
145
- # Switch back to SDK (default)
146
- ppm config set providers.default claude-agent-sdk
147
- ```
148
-
149
- #### Change Authentication Token
150
- ```bash
151
- # Generate new random token
152
- ppm config set auth.token "$(openssl rand -hex 32)"
122
+ # Auth
123
+ ppm config set auth.enabled true
153
124
  ```
154
125
 
155
126
  ---
156
127
 
157
128
  ## Running the Server
158
129
 
159
- ### Foreground Mode (Development)
130
+ `ppm start` always runs as a **background daemon under a supervisor**, and always brings up a
131
+ Cloudflare Quick Tunnel. There is no foreground mode.
160
132
 
161
133
  ```bash
162
- ppm start
134
+ ppm start # daemon + tunnel; blocks until the URL is known, then exits 0
135
+ ppm start -p 4000 # custom port
136
+ ppm start --profile dev # use ppm.dev.db
163
137
 
164
- # Output:
165
- # PPM server listening on http://localhost:8080
166
- # Token: <token from config>
167
- # Projects: 2
138
+ ppm status # human-readable
139
+ ppm status --json # machine-readable `.shareUrl` is the public URL
140
+ ppm logs -f # follow ~/.ppm/ppm.log
141
+ ppm restart # reload, keeping the tunnel URL
168
142
  ```
169
143
 
170
- Server runs in foreground. Press `Ctrl+C` to stop.
144
+ Startup prints `➜ Local`, `➜ Share` and a QR code for the share URL. It waits up to 35s for the
145
+ tunnel; if the URL has not appeared it warns and tells you to check `ppm status`.
171
146
 
172
- ### Daemon Mode (Production)
147
+ ### Stopping: `stop` vs `down`
173
148
 
174
- **Daemon is now the default** `ppm start` runs in background. Use `--foreground/-f` to run with logs visible (for debugging).
149
+ | Command | Server | Supervisor | Tunnel / Cloud link |
150
+ |---|---|---|---|
151
+ | `ppm stop` | stopped | **stays alive** (`stopped` state) | **stays up** |
152
+ | `ppm down` (= `ppm stop --kill`) | stopped | stopped | stopped |
153
+ | `ppm stop --all` | stopped | stopped | kills every PPM + cloudflared process, tracked or not |
175
154
 
176
- ```bash
177
- # Start as background daemon (default)
178
- ppm start
179
-
180
- # Tunnel and public URL are enabled automatically on start
181
- ppm start
155
+ The split exists so a restart does not rotate the public URL. Use `down` for a real shutdown; use
156
+ `stop --all` only when something is wedged — it kills by scan, not by tracked PID.
182
157
 
183
- # Start in foreground (debugging, shows logs)
184
- ppm start --foreground
158
+ ### Logs
185
159
 
186
- # Server status stored in ~/.ppm/status.json
187
- cat ~/.ppm/status.json
160
+ The daemon writes to `~/.ppm/ppm.log` (inside `getPpmDir()`). `ppm logs -n 200`, `ppm logs -f` and
161
+ `ppm logs --clear` read and manage it. There is no separate logging config.
188
162
 
189
- # Check if running
190
- ps aux | grep ppm
163
+ ---
191
164
 
192
- # Stop daemon
193
- ppm stop
165
+ ## Start at Boot
194
166
 
195
- # Graceful shutdown: SIGTERM sent, tunnel stopped, cleanup files removed
196
- ```
167
+ Use the built-in command rather than hand-writing a service file:
197
168
 
198
- **Status File Format (v2+):**
199
- ```json
200
- {
201
- "pid": 12345,
202
- "port": 8080,
203
- "host": "0.0.0.0",
204
- "shareUrl": "https://abc-123.trycloudflare.com"
205
- }
169
+ ```bash
170
+ ppm autostart enable
171
+ ppm autostart status
172
+ ppm autostart disable
206
173
  ```
207
174
 
208
- **Backward Compatibility:** If `~/.ppm/status.json` doesn't exist, `ppm stop` falls back to reading `~/.ppm/ppm.pid`.
209
-
210
- ### Public URL Sharing via Cloudflare Tunnel
175
+ It generates the right artifact per OS:
211
176
 
212
- **Feature:** `ppm start` automatically enables a public URL via Cloudflare Quick Tunnel.
177
+ | OS | Artifact |
178
+ |---|---|
179
+ | macOS | `~/Library/LaunchAgents/com.hienlh.ppm.plist` |
180
+ | Linux | `~/.config/systemd/user/ppm.service` (`Type=notify`) |
181
+ | Windows | Task Scheduler task `PPM`, registered from an XML task definition at logon |
213
182
 
214
- **How It Works:**
215
- 1. `ppm start` spawns a background daemon
216
- 2. Daemon downloads cloudflared binary to `~/.ppm/bin/` if missing (shows download progress)
217
- 3. Tunnel spawns as a child process
218
- 4. Tunnel URL extracted from stderr (e.g., `https://abc-123.trycloudflare.com`)
219
- 5. URL saved to `~/.ppm/status.json` for easy access
220
- 6. Parent displays public URL in terminal output
183
+ `ppm start` enables autostart on first run and migrates a stale systemd unit, so in most cases you
184
+ never call this directly. On Windows the task is created from XML rather than plain `schtasks
185
+ /SC ONLOGON` that flag cannot target a single user's logon without an all-users change, and it
186
+ would otherwise impose a 72-hour run limit.
221
187
 
222
- **Requirements:**
223
- - Internet connectivity (tunnel uses Cloudflare's infrastructure)
224
- - ~15 MB disk space for cloudflared binary (downloaded once, cached)
188
+ ---
225
189
 
226
- **Security Warning:**
227
- If `auth.enabled` is false, PPM displays warning:
228
- ```
229
- ⚠ Warning: auth is disabled — your IDE is publicly accessible!
230
- Enable auth: run 'ppm config set auth.enabled true' before using tunnel.
231
- ```
190
+ ## Public URL Sharing via Cloudflare Tunnel
232
191
 
233
- Recommended: Always enable auth before sharing your URL.
192
+ 1. `ppm start` spawns the supervisor and server
193
+ 2. cloudflared is downloaded to `~/.ppm/bin/` on first use (~15 MB, cached)
194
+ 3. The tunnel runs as a child process; its URL is parsed from stderr
195
+ 4. The URL is written to `~/.ppm/status.json` and printed with a QR code
234
196
 
235
- **Example:**
236
- ```bash
237
- # Start with auto-enabled tunnel and auth
238
- ppm start # Safe: public URL + auth required
197
+ **The quick-tunnel URL rotates on every fresh tunnel.** For a stable address, either link the machine
198
+ to PPM Cloud (`ppm cloud login`) for a permanent alias, or set up a named tunnel on a domain you
199
+ already have on Cloudflare see the next section.
239
200
 
240
- # Start without auth (not recommended)
241
- ppm start # Warning: anyone can access your IDE (no password)
201
+ **Security:** if `auth.enabled` is false while the tunnel is up, PPM warns that the IDE is publicly
202
+ reachable. Always keep auth on when sharing. The session token is required on the WebSocket
203
+ handshake too, not just on HTTP.
242
204
 
243
- # Stop the server (tunnel also stopped)
244
- ppm stop # Tunnel process stopped automatically
245
- ```
205
+ Per-port forwarding for local dev servers is separate: the dock's Cloudflare Tunnels panel drives
206
+ `/api/tunnels`, which spawns one quick tunnel per port.
246
207
 
247
- **Cleanup:**
248
- - `ppm stop` gracefully shuts down the tunnel
249
- - Cloudflared process killed via SIGTERM
250
- - No dangling tunnels left behind
208
+ ---
251
209
 
252
- ### Via systemd (Linux)
210
+ ## Stable Public URL with Your Own Domain
253
211
 
254
- Create `/etc/systemd/system/ppm.service`:
212
+ A named tunnel pins PPM to `https://<prefix>.<your-zone>` — the same hostname across restarts,
213
+ hibernate, and crashes, unlike the quick tunnel's rotating `*.trycloudflare.com` URL. It requires:
255
214
 
256
- ```ini
257
- [Unit]
258
- Description=PPM Web IDE Server
259
- After=network.target
215
+ - A domain already added as a zone in your Cloudflare account.
216
+ - `auth.enabled` set to `true` — a stable, guessable hostname must never be reachable by an
217
+ unauthenticated request, so the setup popup stays hidden and every mutating endpoint 403s while
218
+ auth is off.
260
219
 
261
- [Service]
262
- Type=simple
263
- User=<username>
264
- WorkingDirectory=/home/<username>
265
- ExecStart=/usr/local/bin/ppm start
266
- Restart=always
267
- RestartSec=10
220
+ ### Setup flow
268
221
 
269
- [Install]
270
- WantedBy=multi-user.target
271
- ```
222
+ A first-run popup asks whether you have a domain on Cloudflare. Answering yes opens a Cloudflare
223
+ login link — copy it to a phone or another browser if this machine has no browser of its own. The
224
+ login stays open while you finish it: after 60 seconds idle you get a "still logging in?" prompt
225
+ (the login keeps running), and after 5 minutes with no login it times out and lets you retry with a
226
+ fresh link. Once logged in, PPM reads the zone from the new credential and proposes a hostname
227
+ (`ppm.<zone>` by default) — you can pick a different prefix, but it must be exactly one label under
228
+ the zone (no apex record, no `www`; Cloudflare's free certificate only covers one subdomain level,
229
+ and anything deeper would serve a TLS error).
272
230
 
273
- Then:
274
- ```bash
275
- sudo systemctl daemon-reload
276
- sudo systemctl enable ppm
277
- sudo systemctl start ppm
231
+ The Tunnel Manager section (in the app, alongside the quick-tunnel controls) is where the flow lives
232
+ permanently — the popup only covers first-run:
278
233
 
279
- # Check status
280
- sudo systemctl status ppm
234
+ - **Disable** switches back to the quick tunnel. The named-tunnel configuration is kept (not deleted)
235
+ so re-enabling doesn't require logging in again.
236
+ - **Re-login** ("Log in again") is what to use when the domain's zone changes, or whenever PPM
237
+ reports the Cloudflare credential looks stale (wrong account, unreadable file). It moves the
238
+ existing credential aside (`cert.pem` → `cert.pem.bak-<timestamp>`) rather than deleting it, then
239
+ starts a fresh login — never edit or delete `~/.cloudflared/cert.pem` by hand.
281
240
 
282
- # View logs
283
- sudo journalctl -u ppm -f
284
- ```
241
+ ### Troubleshooting
285
242
 
286
- ### Via launchd (macOS)
287
-
288
- Create `~/Library/LaunchAgents/com.ppm.server.plist`:
289
-
290
- ```xml
291
- <?xml version="1.0" encoding="UTF-8"?>
292
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
293
- <plist version="1.0">
294
- <dict>
295
- <key>Label</key>
296
- <string>com.ppm.server</string>
297
- <key>ProgramArguments</key>
298
- <array>
299
- <string>/usr/local/bin/ppm</string>
300
- <string>start</string>
301
- </array>
302
- <key>RunAtLoad</key>
303
- <true/>
304
- <key>KeepAlive</key>
305
- <true/>
306
- <key>StandardOutPath</key>
307
- <string>/tmp/ppm.log</string>
308
- <key>StandardErrorPath</key>
309
- <string>/tmp/ppm-error.log</string>
310
- </dict>
311
- </plist>
312
- ```
243
+ **"Hostname unreachable" warning** — shown when the DNS record for your named tunnel stops
244
+ resolving (for example, the CNAME was deleted in the Cloudflare dashboard outside PPM). PPM restarts
245
+ the tunnel connector once to rule out a transient failure; if the hostname is still unreachable after
246
+ that it stops retrying and leaves the warning up rather than restarting forever. Recreate the DNS
247
+ record in Cloudflare (or use Re-login if the whole zone changed) to clear it.
313
248
 
314
- Then:
315
- ```bash
316
- launchctl load ~/Library/LaunchAgents/com.ppm.server.plist
317
- launchctl status com.ppm.server
318
- ```
249
+ **Setup finishes but says "pending" / asks you to run `ppm restart`** — the setup call always
250
+ succeeds once cloudflared provisions the tunnel; picking it up without a full restart needs a
251
+ supervisor version that understands the `retunnel` command. On an older supervisor (from before a
252
+ PPM upgrade), run `ppm restart` once to finish applying it.
319
253
 
320
254
  ---
321
255
 
322
256
  ## Environment Variables
323
257
 
324
- ### Optional Configuration via ENV
325
-
326
- Instead of `ppm.yaml`, configure via environment variables:
327
-
328
- ```bash
329
- export PPM_PORT=8080
330
- export PPM_HOST=0.0.0.0
331
- export PPM_AUTH_TOKEN="my-secure-token"
332
- export PPM_DEFAULT_PROVIDER="claude-agent-sdk"
333
- export PPM_DB_PATH="/etc/ppm/ppm.db" # Custom database location
258
+ Only these are read by PPM:
334
259
 
335
- ppm start
336
- ```
260
+ | Variable | Read by | Purpose |
261
+ |---|---|---|
262
+ | `PPM_HOME` | `src/services/ppm-dir.ts` | Override the `~/.ppm` directory. Used for test isolation. |
263
+ | `PPM_CLAUDE_CLI` | Claude provider / CLI resolver | Explicit path to the `claude` binary when discovery fails |
264
+ | `PPM_SKILLS_DIR` | `slash-discovery` | Extra directory to discover skills from |
265
+ | `PPM_TERMINAL` | `ppm cloud` | Set to `1` to force terminal-mode output |
266
+ | `PPM_INSTALL_DIR` | `scripts/install.sh` / `install.ps1` | Install location (default `~/.ppm/bin`) |
267
+ | `PPM_DEV_API` | `vite.config.ts` | Dev-server proxy target (default `http://localhost:8081`) |
337
268
 
338
- ### For Claude Integration
269
+ There is **no** `PPM_PORT`, `PPM_HOST`, `PPM_DB_PATH` or `PPM_DEFAULT_PROVIDER` — all of those are
270
+ config keys, set with `ppm config set`.
339
271
 
340
- If using Claude Agent SDK:
341
- ```bash
342
- export ANTHROPIC_API_KEY="sk-ant-..." # Your Anthropic API key
343
- ppm start
344
- ```
272
+ ### AI provider environment
345
273
 
346
- **Note:** On Windows, SDK uses CLI fallback (`claude` binary) for Bun subprocess pipe buffering issues. Ensure `claude` is in PATH.
274
+ The SDK authenticates through the logged-in `claude` CLI; an `ANTHROPIC_API_KEY` is not required.
275
+ Note that a *project's* `.env` containing `ANTHROPIC_API_KEY` can break SDK tool execution, so the
276
+ provider neutralizes those variables for spawned tools. See `lessons-learned.md`.
347
277
 
348
278
  ---
349
279
 
350
280
  ## Build & Deployment Commands
351
281
 
352
- ### Full Build Pipeline
353
-
354
282
  ```bash
355
- # 1. Install dependencies
356
283
  bun install
357
-
358
- # 2. Type check
359
- bun run typecheck
360
-
361
- # 3. Build frontend
362
- bun run build:web
363
-
364
- # 4. Compile CLI binary (single executable)
365
- bun run build
366
-
367
- # Output: dist/ppm (~50-150 MB depending on platform)
368
-
369
- # 5. Test (optional, currently partial coverage)
284
+ bun run typecheck # bunx tsc --noEmit
285
+ bun run build:web # frontend only
286
+ bun run build # frontend + compiled binary → dist/ppm
370
287
  bun test
371
288
  ```
372
289
 
373
290
  ### Output Artifacts
374
291
 
375
- After `bun run build`:
376
-
377
292
  ```
378
293
  dist/
379
- ├── ppm # Compiled CLI binary (executable)
380
- └── web/ # Frontend assets (embedded in binary)
294
+ ├── ppm # compiled binary (embeds the runtime)
295
+ └── web/ # frontend assets served by the binary
381
296
  ├── index.html
382
- ├── assets/
383
- │ ├── index-*.js # Main JS bundle
384
- │ ├── index-*.css # Tailwind styles
385
- │ └── ... # Other chunks
297
+ ├── assets/ # JS/CSS chunks
386
298
  └── manifest.json # PWA manifest
387
299
  ```
388
300
 
389
- ### Size Optimization
390
-
391
- ```bash
392
- # Check bundle size before/after
393
- bun run build:web
394
- du -sh dist/web/assets/
395
-
396
- # Typical sizes:
397
- # - JS bundles: 200-300 KB gzipped
398
- # - CSS: 100-150 KB gzipped
399
- # - Total frontend: 400-500 KB gzipped
400
- # - CLI binary: 80-120 MB (includes runtime)
401
- ```
301
+ Typical sizes: frontend ~400–500 KB gzipped; binary ~80–120 MB (the runtime dominates).
402
302
 
403
303
  ---
404
304
 
@@ -466,160 +366,130 @@ Every step is idempotent — safe to re-run if it fails partway (e.g. npm alread
466
366
 
467
367
  ---
468
368
 
469
- ## First-Time Setup Checklist
369
+ ## Upgrading
470
370
 
471
371
  ```bash
472
- # 1. Install Bun
473
- curl -fsSL https://bun.sh/install | bash
474
- source ~/.bashrc # or ~/.zshrc
475
-
476
- # 2. Clone/build PPM
477
- git clone https://github.com/hienlh/ppm.git
478
- cd ppm
479
- bun install
480
- bun run build
481
-
482
- # 3. Initialize config
483
- ./dist/ppm init
484
- # Follow prompts to add projects
372
+ ppm upgrade --check # see whether a newer version exists
373
+ ppm upgrade # download, verify and swap the binary in place
374
+ ```
485
375
 
486
- # 4. Start server
487
- ./dist/ppm start
488
- # Output: http://localhost:8080 + token
376
+ The supervisor also polls for new versions and surfaces a one-click upgrade banner in the UI. For
377
+ Bun installs, `bun update -g @hienlh/ppm` works as well; for installer-script installs, re-running
378
+ the installer is equivalent.
489
379
 
490
- # 5. Open browser
491
- # Navigate to http://localhost:8080
492
- # Enter token from step 4
493
- # Select project and start using
380
+ Config carries over — `~/.ppm/ppm.db` is untouched by an upgrade. Back it up first if you want a
381
+ guaranteed rollback point:
494
382
 
495
- # 6. Verify functionality
496
- # - Browse files in file explorer
497
- # - Open terminal and run commands
498
- # - Chat with Claude (requires ANTHROPIC_API_KEY)
383
+ ```bash
384
+ cp ~/.ppm/ppm.db ~/.ppm/ppm.db.backup
499
385
  ```
500
386
 
501
387
  ---
502
388
 
503
- ## Troubleshooting
504
-
505
- ### Port Already in Use
389
+ ## First-Time Setup Checklist
506
390
 
507
391
  ```bash
508
- # Check what's using port 8080
509
- lsof -i :8080
510
- # Kill process
511
- kill -9 <PID>
392
+ # 1. Install
393
+ curl -fsSL https://ppm.sh/install | sh
512
394
 
513
- # Or use different port
514
- ppm start --port 3000
515
- ```
395
+ # 2. Initialize (interactive: port, password, scan dir, AI settings)
396
+ ppm init
516
397
 
517
- ### Permission Denied (File Operations)
398
+ # 3. Start prints Local + Share URLs and a QR code
399
+ ppm start
518
400
 
519
- ```bash
520
- # Ensure PPM has read/write access to project directory
521
- chmod -R u+rw /path/to/project
401
+ # 4. Open the printed URL, enter the access password
522
402
 
523
- # Or run PPM with appropriate user
524
- sudo -u <username> ppm start
403
+ # 5. Verify: browse files, open a terminal, run a git status, send a chat message
525
404
  ```
526
405
 
527
- ### Git Commands Failing
528
-
529
- ```bash
530
- # Verify git is installed
531
- git --version
406
+ ---
532
407
 
533
- # Verify project is git repository
534
- cd /path/to/project
535
- git status
408
+ ## Troubleshooting
536
409
 
537
- # If not a repo
538
- git init
410
+ ### Port already in use
411
+ ```bash
412
+ ppm status # is PPM itself already running?
413
+ lsof -i :3210 # macOS/Linux
414
+ netstat -ano | findstr :3210 # Windows
415
+ ppm start -p 4000 # or just move
539
416
  ```
417
+ If PPM was killed uncleanly the port can stay wedged by an orphaned child. `ppm stop --all` clears
418
+ tracked and untracked PPM/cloudflared processes; on Windows a zombie-port reaper also runs at start.
540
419
 
541
- ### Terminal Not Working
542
-
420
+ ### Server won't start
543
421
  ```bash
544
- # Verify shell is available
545
- which bash zsh
546
-
547
- # Check PTY support (Linux/macOS only)
548
- # Windows may require WSL or special configuration
422
+ ppm status --json
423
+ ppm logs -n 200 # the daemon logs to ~/.ppm/ppm.log
424
+ ppm config get port
425
+ ppm down && ppm start # full restart, including the supervisor
549
426
  ```
550
427
 
551
- ### Chat/Claude Not Responding
552
-
428
+ ### Tunnel URL missing or unreachable
553
429
  ```bash
554
- # Check API key is set
555
- echo $ANTHROPIC_API_KEY
556
-
557
- # Verify network connectivity
558
- curl https://api.anthropic.com
559
-
560
- # Check provider is working
561
- ppm chat send "test message" 2>&1
430
+ ppm status # shareUrl present?
431
+ ls ~/.ppm/bin/cloudflared # binary downloaded?
432
+ ppm down && ppm start # re-establish; the URL will change
562
433
  ```
434
+ A resolver that filters `*.trycloudflare.com` (some VPN/DNS setups) will make a *valid* URL look
435
+ dead — test the same URL from another network before assuming the tunnel failed.
563
436
 
564
- ### Server Won't Start
565
-
437
+ ### Chat not responding
566
438
  ```bash
567
- # Check status (v2+)
568
- cat ~/.ppm/status.json
569
-
570
- # Verify server is running
571
- ps aux | grep ppm
572
-
573
- # View logs (foreground mode only)
574
- ppm start --foreground # Shows real-time logs
439
+ claude --version # is Claude Code installed and logged in?
440
+ ppm logs -f # provider errors are logged here
441
+ ```
442
+ If the CLI cannot be found, set `PPM_CLAUDE_CLI=/path/to/claude`. If the project has an `.env` with
443
+ `ANTHROPIC_API_KEY`, see the SDK note above.
575
444
 
576
- # Verify config is valid YAML
577
- ppm config get port
445
+ ### Terminal not working
446
+ ```bash
447
+ which bash zsh # macOS/Linux
448
+ ```
449
+ Windows uses ConPTY via `@skitee3000/bun-pty`; macOS and Linux use Bun's native PTY. Both are behind
450
+ one `PtyHandle` interface in `terminal.service.ts`.
578
451
 
579
- # Clear cache and restart
580
- rm -rf ~/.ppm/cache
581
- ppm start
452
+ ### Git commands failing
453
+ ```bash
454
+ git --version
455
+ cd /path/to/project && git status # is it actually a repo?
582
456
  ```
583
457
 
584
- **Note:** Daemon mode doesn't write to a log file by default. Use `ppm start --foreground` to see logs for debugging, or set up systemd with log redirection (see "Via systemd" section above).
458
+ ### Permission denied on file operations
459
+ Confirm the PPM process user can read/write the project directory. PPM refuses paths outside its
460
+ allowed scope by design — protected system roots and the PPM directory itself are shielded, so a
461
+ 403 on `~/.ppm` is expected behaviour, not a bug.
585
462
 
586
463
  ---
587
464
 
588
465
  ## Security Checklist
589
466
 
590
- ### Before Production Deployment
591
-
592
- - [ ] Change default auth token: `ppm config set auth.token "$(openssl rand -hex 32)"`
593
- - [ ] Verify only necessary projects are in `ppm.yaml`
594
- - [ ] Set appropriate file permissions: `chmod 600 ~/.ppm/ppm.db`
595
- - [ ] Keep Bun updated: `bun upgrade`
596
- - [ ] Keep dependencies updated: `bun update`
597
- - [ ] Review firewall rules (localhost only recommended)
598
- - [ ] Disable password-less sudo if running as daemon
599
- - [ ] Use HTTPS if exposing to network (via reverse proxy, e.g., nginx)
600
- - [ ] Regularly backup `ppm.yaml` and project data
467
+ - [ ] Keep `auth.enabled` true — mandatory whenever the tunnel is up
468
+ - [ ] Rotate the token if it leaks: `ppm config set auth.token "$(openssl rand -hex 32)"`
469
+ - [ ] Restrict the config DB: `chmod 600 ~/.ppm/ppm.db` (it holds account credentials)
470
+ - [ ] Review which projects are registered: `ppm projects list`
471
+ - [ ] Keep the proxy auth key secret if the API proxy is enabled
472
+ - [ ] Keep Bun and PPM updated: `bun upgrade`, `ppm upgrade`
473
+ - [ ] Prefer the tunnel over opening a firewall port
601
474
 
602
- ### Network Exposure (Not Recommended)
475
+ ### Direct network exposure (not recommended)
603
476
 
604
- If you must expose to network:
477
+ The tunnel is the supported path. If you must expose the port directly, terminate TLS in front:
605
478
 
606
479
  ```nginx
607
- # nginx reverse proxy with SSL
608
- upstream ppm {
609
- server localhost:8080;
610
- }
480
+ upstream ppm { server localhost:3210; }
611
481
 
612
482
  server {
613
483
  listen 443 ssl http2;
614
484
  server_name ppm.example.com;
615
485
 
616
- ssl_certificate /etc/letsencrypt/live/ppm.example.com/fullchain.pem;
486
+ ssl_certificate /etc/letsencrypt/live/ppm.example.com/fullchain.pem;
617
487
  ssl_certificate_key /etc/letsencrypt/live/ppm.example.com/privkey.pem;
618
488
 
619
489
  location / {
620
490
  proxy_pass http://ppm;
621
491
  proxy_http_version 1.1;
622
- proxy_set_header Upgrade $http_upgrade;
492
+ proxy_set_header Upgrade $http_upgrade; # WebSocket
623
493
  proxy_set_header Connection "upgrade";
624
494
  proxy_set_header Host $host;
625
495
  proxy_set_header X-Real-IP $remote_addr;
@@ -627,140 +497,60 @@ server {
627
497
  }
628
498
  ```
629
499
 
630
- Then access via `https://ppm.example.com` with SSL certificate.
631
-
632
500
  ---
633
501
 
634
- ## Upgrade Instructions
635
-
636
- ### From v1 to v2
502
+ ## Monitoring
637
503
 
504
+ ### Health check (no auth)
638
505
  ```bash
639
- # 1. Backup existing config
640
- cp ~/.ppm/ppm.db ~/.ppm/ppm.db.backup
641
-
642
- # 2. Stop running server
643
- ppm stop
644
- # Or Ctrl+C if foreground
645
-
646
- # 3. Download/build v2 binary
647
- # (See "Installation" section above)
506
+ curl http://localhost:3210/api/health
507
+ # {"ok":true,"data":{"status":"running"}}
648
508
 
649
- # 4. Verify new binary works
650
- ./dist/ppm --version
651
- # Should output: v2.0.0
652
-
653
- # 5. Start new version
654
- ./dist/ppm start
655
-
656
- # 6. Test in browser
657
- # All projects and auth token should carry over
509
+ curl http://localhost:3210/api/info
510
+ # version, device_name, tunnel_active — used by the login screen
658
511
  ```
659
512
 
660
- ### Rollback to v1 (If Needed)
513
+ ### Host metrics
514
+ `/api/system/resources*` streams CPU, memory, disk, network, GPU and per-process data over SSE, in a
515
+ light and a full tier with leases. It is the backend for the System Monitor window and is behind
516
+ PPM auth. On Windows a single long-lived PowerShell collector serves every tick — never spawn one
517
+ per tick.
661
518
 
519
+ ### Daemon state
662
520
  ```bash
663
- # 1. Stop v2 server
664
- ppm stop
665
-
666
- # 2. Switch back to v1 binary
667
- # cp path/to/v1/ppm ./ppm-v1
668
- # ./ppm-v1 start
669
-
670
- # 3. Restore backup if config changed
671
- # cp ~/.ppm/ppm.db.backup ~/.ppm/ppm.db
521
+ ppm status --json # pid, port, host, shareUrl, tunnel state
522
+ cat ~/.ppm/status.json # same file the supervisor writes
523
+ ppm logs -f
672
524
  ```
673
525
 
674
526
  ---
675
527
 
676
528
  ## Performance Tuning
677
529
 
678
- ### Increase File Descriptor Limit (Linux)
679
-
680
- ```bash
681
- # Check current limit
682
- ulimit -n
683
-
684
- # Increase to 4096 (temporary)
685
- ulimit -n 4096
686
-
687
- # Permanent: edit /etc/security/limits.conf
688
- # Add: * soft nofile 4096
689
- # * hard nofile 4096
690
- ```
691
-
692
- ### Memory Management
693
-
530
+ ### File descriptor limit (Linux)
694
531
  ```bash
695
- # Monitor memory usage
696
- # Linux
697
- ps aux | grep ppm
698
- free -h
699
-
700
- # macOS
701
- ps aux | grep ppm
702
- vm_stat | grep page
703
-
704
- # If using too much memory:
705
- # 1. Reduce number of open projects
706
- # 2. Clear browser cache
707
- # 3. Restart server
532
+ ulimit -n # check
533
+ ulimit -n 4096 # raise for this shell
534
+ # permanent: /etc/security/limits.conf * soft nofile 4096 / * hard nofile 4096
708
535
  ```
709
536
 
710
- ### Network Latency
537
+ ### File watching
538
+ PPM never registers a recursive watch on a project root — on Linux that is one inotify watch per
539
+ subdirectory, `node_modules` included. Ignored directories are pruned at registration time in
540
+ `src/services/file-watcher/watch-tree.ts`. If you add watch surfaces, keep that invariant or you
541
+ will exhaust the inotify limit.
711
542
 
712
- ```bash
713
- # Test WebSocket latency
714
- # From browser console:
715
- console.time('ws');
716
- ws.send({type: 'message', content: 'ping'});
717
- // Measure response time
718
- ```
543
+ ### Memory
544
+ Long chat sessions are the usual growth source; the transcript is windowed rather than fully
545
+ materialized. If memory climbs, check for orphaned transcode or tunnel children with the System
546
+ Monitor, filtered to PPM's own processes.
719
547
 
720
548
  ---
721
549
 
722
- ## Monitoring
723
-
724
- ### Health Check Endpoint
725
-
726
- ```bash
727
- # Health check (no auth required)
728
- curl http://localhost:8080/api/health
729
-
730
- # Output: { ok: true, data: { status: "healthy" } }
731
- ```
732
-
733
- ### Activity Logging
734
-
735
- PPM logs to stdout in foreground mode. In daemon mode, configure:
736
-
737
- ```yaml
738
- # ppm.yaml
739
- logging:
740
- level: info # debug, info, warn, error
741
- file: ~/.ppm/server.log
742
- rotation: daily
743
- retention: 7 # days
744
- ```
745
-
746
- ### Metrics Collection
747
-
748
- For monitoring integrations (Prometheus, DataDog):
749
-
750
- ```bash
751
- # Future: /api/metrics endpoint
752
- # Currently not implemented; planned for v2.1
753
- ```
754
-
755
- ---
756
-
757
- ## Support & Troubleshooting
758
-
759
- ### Getting Help
760
-
761
- 1. **GitHub Issues:** https://github.com/hienlh/ppm/issues
762
- 2. **Logs:** Run `ppm start --foreground` to see real-time logs; check `~/.ppm/status.json` for daemon status
763
- 3. **Configuration:** Validate `ppm.yaml` syntax
764
- 4. **Dependencies:** Ensure Bun, Git, Node are installed and up-to-date
765
- 5. **Tunnel Issues:** Check `~/.ppm/bin/cloudflared` exists; re-download if corrupted
550
+ ## Support
766
551
 
552
+ 1. **Bug report:** `ppm report` pre-fills a GitHub issue with environment info and recent logs
553
+ 2. **Issues:** https://github.com/hienlh/ppm/issues
554
+ 3. **Logs:** `ppm logs -f` (`~/.ppm/ppm.log`)
555
+ 4. **Status:** `ppm status --json`
556
+ 5. **Known traps:** [`lessons-learned.md`](lessons-learned.md)