ompchamber 1.2.1 → 2.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 (223) hide show
  1. package/README.md +131 -147
  2. package/dist/client/index.html +4 -2
  3. package/dist/client/static/css/index.5f630421b7.css +2 -0
  4. package/dist/client/static/js/77.0d81c74cf0.js +139 -0
  5. package/dist/client/static/js/async/1k.973e8e21fc.js +2 -0
  6. package/dist/client/static/js/async/{3y.3186ecdd63.js → 3y.3530b824ad.js} +6 -6
  7. package/dist/client/static/js/async/{q.b453193538.js → 4m.928a1dde85.js} +10 -10
  8. package/dist/client/static/js/async/66.5dfa29f957.js +93 -0
  9. package/dist/client/static/js/async/7g.a7814350c3.js +1 -0
  10. package/dist/client/static/js/async/ar.9303e5f2e8.js +2 -0
  11. package/dist/client/static/js/async/{cx.9c8268d542.js → cx.3cb0242a3a.js} +1 -1
  12. package/dist/client/static/js/async/e.93214d622b.js +79 -0
  13. package/dist/client/static/js/async/g.74ff36419f.js +2 -0
  14. package/dist/client/static/js/async/{m.2e1ea3db9e.js.LICENSE.txt → g.74ff36419f.js.LICENSE.txt} +5 -0
  15. package/dist/client/static/js/async/h1.393f066d09.js +1 -0
  16. package/dist/client/static/js/async/jl.874d352278.js +1 -0
  17. package/dist/client/static/js/async/{k.d16cd09ae7.js → k.3210286401.js} +1 -1
  18. package/dist/client/static/js/async/{m.2e1ea3db9e.js → m.eb2e6752e2.js} +3 -3
  19. package/dist/client/static/js/async/m.eb2e6752e2.js.LICENSE.txt +11 -0
  20. package/dist/client/static/js/async/mt.0352e976d8.js +1 -0
  21. package/dist/client/static/js/async/{oc.eb22093f05.js → oc.b73042e8bd.js} +1 -1
  22. package/dist/client/static/js/async/{og.53f068804c.js → og.8eb577893a.js} +1 -1
  23. package/dist/client/static/js/async/px.fc6877924b.js +1 -0
  24. package/dist/client/static/js/async/q.33d6779f98.js +21 -0
  25. package/dist/client/static/js/async/{q5.88b50ffa95.js → q5.97dc1481b6.js} +1 -1
  26. package/dist/client/static/js/async/s.0f395cdda5.js +94 -0
  27. package/dist/client/static/js/async/{tr.2a0d2b7600.js → tr.e878658140.js} +1 -1
  28. package/dist/client/static/js/async/vt.42416b707d.js +1 -0
  29. package/dist/client/static/js/async/x1.da8687159b.js +90 -0
  30. package/dist/client/static/js/async/xe.da8dcc2015.js +2 -0
  31. package/dist/client/static/js/async/xe.da8dcc2015.js.LICENSE.txt +11 -0
  32. package/dist/client/static/js/async/{xn.6360379f71.js → xn.6510c0abe2.js} +2 -2
  33. package/dist/client/static/js/async/yg.35bebd6d0c.js +149 -0
  34. package/dist/client/static/js/async/yv.d99d829136.js +1 -0
  35. package/dist/client/static/js/index.c05535dbde.js +38 -0
  36. package/package.json +3 -3
  37. package/src/client/components/common/ComposerTextarea.tsx +9 -1
  38. package/src/client/components/common/MarkdownRenderer.tsx +50 -12
  39. package/src/client/components/mobile/mobile-right-sidebar/FullEditor.tsx +9 -3
  40. package/src/client/components/settings/Modal.tsx +11 -2
  41. package/src/client/components/settings/categories/AppearanceSettings.tsx +7 -30
  42. package/src/client/components/settings/categories/ProviderSettings.tsx +2 -0
  43. package/src/client/components/settings/categories/appearance-settings/ThemeCard.tsx +61 -0
  44. package/src/client/components/settings/categories/appearance-settings/ThemeGrid.tsx +80 -0
  45. package/src/client/components/settings/categories/chat-settings/TitleSection.tsx +1 -1
  46. package/src/client/components/settings/categories/provider-settings/AddProviderModal.tsx +43 -6
  47. package/src/client/components/settings/categories/provider-settings/ModelConfigModal.tsx +54 -54
  48. package/src/client/components/workspace/SearchPanel.tsx +16 -3
  49. package/src/client/components/workspace/btw-panel/AskCard.tsx +11 -6
  50. package/src/client/components/workspace/btw-panel/Messages.tsx +105 -51
  51. package/src/client/components/workspace/btw-panel/index.tsx +124 -45
  52. package/src/client/components/workspace/chat-timeline/AiMessageFooter.tsx +30 -14
  53. package/src/client/components/workspace/chat-timeline/ComposerDock.tsx +10 -1
  54. package/src/client/components/workspace/chat-timeline/GeneratingIndicator.tsx +8 -2
  55. package/src/client/components/workspace/chat-timeline/MessageItem.tsx +27 -16
  56. package/src/client/components/workspace/chat-timeline/MessageList.tsx +11 -0
  57. package/src/client/components/workspace/chat-timeline/RunFooter.tsx +8 -0
  58. package/src/client/components/workspace/chat-timeline/chat-input/index.tsx +12 -1
  59. package/src/client/components/workspace/chat-timeline/index.tsx +7 -2
  60. package/src/client/components/workspace/chat-timeline/tool-renderers/ask-panel/QuestionBlock.tsx +42 -15
  61. package/src/client/components/workspace/chat-timeline/tool-renderers/ask-panel/index.tsx +13 -1
  62. package/src/client/components/workspace/chat-timeline/tool-renderers/extension-dialog/index.tsx +13 -4
  63. package/src/client/components/workspace/editor/index.tsx +11 -2
  64. package/src/client/components/workspace/file-explorer/GitRepoDropdown.tsx +15 -41
  65. package/src/client/components/workspace/file-explorer/index.tsx +86 -16
  66. package/src/client/components/workspace/git-panel/index.tsx +60 -78
  67. package/src/client/components/workspace/terminal-panel/Header.tsx +16 -1
  68. package/src/client/components/workspace/terminal-panel/RealtimeXtermView.tsx +5 -5
  69. package/src/client/components/workspace/terminal-panel/index.tsx +6 -2
  70. package/src/client/components/workspace/terminal-panel/mount.ts +2 -2
  71. package/src/client/data/theme/terminal.ts +50 -52
  72. package/src/client/hooks/chat/btw/index.ts +139 -18
  73. package/src/client/hooks/chat/btw/intercept.ts +8 -8
  74. package/src/client/hooks/chat/btw/mode.ts +111 -16
  75. package/src/client/hooks/chat/composer/index.ts +10 -4
  76. package/src/client/hooks/chat/timeline/access-mode.ts +41 -0
  77. package/src/client/hooks/chat/timeline/ask-frames.test.ts +87 -0
  78. package/src/client/hooks/chat/timeline/ask-frames.ts +20 -1
  79. package/src/client/hooks/chat/timeline/auto-scroll.ts +13 -4
  80. package/src/client/hooks/chat/timeline/index.ts +8 -20
  81. package/src/client/hooks/chat/timeline/queue.ts +66 -9
  82. package/src/client/hooks/chat/timeline/scroll.test.ts +260 -0
  83. package/src/client/hooks/chat/timeline/scroll.ts +93 -20
  84. package/src/client/hooks/chat/timeline/session-load.ts +7 -1
  85. package/src/client/hooks/chat/timeline/session-pagination.test.ts +167 -0
  86. package/src/client/hooks/chat/timeline/session-pagination.ts +37 -11
  87. package/src/client/hooks/settings/providers.ts +34 -3
  88. package/src/client/hooks/ui/open-file.ts +7 -1
  89. package/src/client/hooks/ui/theme.ts +82 -57
  90. package/src/client/hooks/workspace/file-tabs.ts +5 -1
  91. package/src/client/hooks/workspace/repo-scope/index.ts +119 -0
  92. package/src/client/hooks/workspace/repo-scope/store.test.ts +161 -0
  93. package/src/client/hooks/workspace/repo-scope/store.ts +201 -0
  94. package/src/client/hooks/workspace/search-stream.ts +24 -5
  95. package/src/client/main.tsx +6 -0
  96. package/src/client/tailwind.css +19 -56
  97. package/src/server/lib/btw/child.server.ts +41 -0
  98. package/src/server/lib/btw/lifecycle.server.ts +254 -0
  99. package/src/server/lib/btw/prompt.ts +13 -5
  100. package/src/server/lib/btw/registry.server.ts +13 -4
  101. package/src/server/lib/btw/runtime.server.ts +149 -156
  102. package/src/server/lib/btw/schema.server.ts +27 -0
  103. package/src/server/lib/btw/service.server.ts +106 -5
  104. package/src/server/lib/btw/store.server.ts +57 -6
  105. package/src/server/lib/db/schema.ts +4 -0
  106. package/src/server/lib/db/settings-store.test.ts +65 -0
  107. package/src/server/lib/db/settings-store.ts +25 -0
  108. package/src/server/lib/fs/atomic-write.ts +42 -4
  109. package/src/server/lib/fs/config-lock.ts +74 -0
  110. package/src/server/lib/fs/git-ignore.ts +55 -5
  111. package/src/server/lib/fs/ripgrep.ts +119 -0
  112. package/src/server/lib/lifecycle/identity.ts +10 -64
  113. package/src/server/lib/lifecycle/proc/darwin.ts +238 -0
  114. package/src/server/lib/lifecycle/proc/index.ts +38 -0
  115. package/src/server/lib/lifecycle/proc/linux.ts +80 -0
  116. package/src/server/lib/lifecycle/proc/ps.ts +86 -0
  117. package/src/server/lib/lifecycle/proc/types.ts +33 -0
  118. package/src/server/lib/lifecycle/proc/win32.ts +53 -0
  119. package/src/server/lib/models/provider-registry.server.ts +2 -2
  120. package/src/server/lib/models/registry.server.ts +1 -1
  121. package/src/server/lib/omp/config/behavior.ts +17 -17
  122. package/src/server/lib/omp/config/disabled-providers.ts +84 -35
  123. package/src/server/lib/omp/config/document.ts +128 -0
  124. package/src/server/lib/omp/config/extensions.ts +11 -10
  125. package/src/server/lib/omp/config/mcp.ts +4 -57
  126. package/src/server/lib/omp/config/model-overrides.ts +123 -0
  127. package/src/server/lib/omp/config/models-config.ts +92 -0
  128. package/src/server/lib/omp/config/models-validation.ts +159 -0
  129. package/src/server/lib/omp/config/path-scoped.ts +74 -0
  130. package/src/server/lib/omp/config/providers.ts +241 -211
  131. package/src/server/lib/omp/config/roles.ts +6 -14
  132. package/src/server/lib/omp/core/auth-credentials.ts +1 -1
  133. package/src/server/lib/omp/rpc/frame-fold.test.ts +124 -0
  134. package/src/server/lib/omp/rpc/frame-fold.ts +43 -24
  135. package/src/server/lib/omp/rpc/lifecycle.test.ts +41 -0
  136. package/src/server/lib/omp/rpc/manager.ts +21 -21
  137. package/src/server/lib/omp/rpc/pending-ui-dialogs.ts +11 -7
  138. package/src/server/lib/omp/rpc/session-commands.ts +17 -29
  139. package/src/server/lib/omp/rpc/session-registry.ts +5 -66
  140. package/src/server/lib/omp/rpc/web-state.ts +0 -6
  141. package/src/server/lib/omp/session/auto-title.server.test.ts +109 -11
  142. package/src/server/lib/omp/session/auto-title.server.ts +95 -20
  143. package/src/server/lib/omp/session/sidebar-data.server.ts +11 -6
  144. package/src/server/lib/queue/delivery-dispatch.server.test.ts +162 -0
  145. package/src/server/lib/queue/delivery-harness.ts +88 -0
  146. package/src/server/lib/queue/delivery.server.test.ts +78 -149
  147. package/src/server/lib/queue/delivery.server.ts +105 -13
  148. package/src/server/lib/queue/store.server.ts +30 -5
  149. package/src/server/lib/terminal/foreground.test.ts +164 -0
  150. package/src/server/lib/terminal/foreground.ts +34 -6
  151. package/src/server/lib/terminal/history.ts +8 -7
  152. package/src/server/plugins/compress.ts +33 -5
  153. package/src/server/plugins/ssr.ts +14 -7
  154. package/src/server/routes/btw/topics.ts +89 -2
  155. package/src/server/routes/fs/git.ts +5 -6
  156. package/src/server/routes/fs/search.ts +17 -26
  157. package/src/server/routes/sessions/queue.ts +17 -4
  158. package/src/server/routes/settings/index.ts +2 -0
  159. package/src/server/routes/settings/model-override.ts +69 -0
  160. package/src/server/routes/settings/provider-models.ts +35 -12
  161. package/src/server/routes/settings/providers.ts +31 -1
  162. package/src/server/routes/settings/root.ts +8 -3
  163. package/src/shared/lib/chat/btw/client.ts +34 -0
  164. package/src/shared/lib/chat/timeline/tool-phrases.ts +7 -0
  165. package/src/shared/lib/code/shiki-themes.ts +9 -5
  166. package/src/shared/lib/fs/file-tree.ts +17 -12
  167. package/src/shared/lib/markdown/autolink.test.ts +32 -0
  168. package/src/shared/lib/markdown/autolink.ts +50 -0
  169. package/src/shared/lib/markdown/document-urls.test.ts +68 -0
  170. package/src/shared/lib/markdown/document-urls.ts +118 -0
  171. package/src/shared/lib/markdown/marked.ts +27 -15
  172. package/src/shared/lib/markdown/mermaid.ts +2 -2
  173. package/src/shared/lib/models/catalog.ts +1 -1
  174. package/src/shared/lib/omp/session/schema-migrations.ts +30 -0
  175. package/src/shared/lib/omp/session/stream-state.server.test.ts +54 -0
  176. package/src/shared/lib/omp/session/stream-state.server.ts +70 -21
  177. package/src/shared/lib/settings/client.ts +10 -4
  178. package/src/shared/lib/settings/diff.test.ts +31 -0
  179. package/src/shared/lib/settings/diff.ts +37 -0
  180. package/src/shared/lib/theme/catalog.test.ts +168 -0
  181. package/src/shared/lib/theme/catalog.ts +98 -0
  182. package/src/shared/lib/theme/color.ts +88 -0
  183. package/src/shared/lib/theme/css.ts +70 -0
  184. package/src/shared/lib/theme/palettes/chamber.ts +61 -0
  185. package/src/shared/lib/theme/palettes/dark.ts +313 -0
  186. package/src/shared/lib/theme/palettes/light.ts +313 -0
  187. package/src/shared/types/btw.ts +83 -4
  188. package/src/shared/types/index.ts +1 -0
  189. package/src/shared/types/settings/provider.ts +8 -1
  190. package/src/shared/types/settings/state.ts +10 -4
  191. package/src/shared/types/theme.ts +48 -0
  192. package/dist/client/static/css/index.b938f4a693.css +0 -2
  193. package/dist/client/static/js/77.8022a800b5.js +0 -139
  194. package/dist/client/static/js/async/1k.a411fe5b43.js +0 -2
  195. package/dist/client/static/js/async/66.86544ad741.js +0 -93
  196. package/dist/client/static/js/async/7g.db82aca7ba.js +0 -1
  197. package/dist/client/static/js/async/ar.ad5c8822a8.js +0 -2
  198. package/dist/client/static/js/async/e.6443e739a2.js +0 -79
  199. package/dist/client/static/js/async/g.ee41bfed7f.js +0 -2
  200. package/dist/client/static/js/async/h1.d7091cef78.js +0 -1
  201. package/dist/client/static/js/async/jl.4911fa3383.js +0 -1
  202. package/dist/client/static/js/async/mt.853be2b5aa.js +0 -1
  203. package/dist/client/static/js/async/ot.84c71b308f.js +0 -2
  204. package/dist/client/static/js/async/px.783b6f91f2.js +0 -1
  205. package/dist/client/static/js/async/q8.7f1b48e9cd.js +0 -21
  206. package/dist/client/static/js/async/q8.7f1b48e9cd.js.LICENSE.txt +0 -6
  207. package/dist/client/static/js/async/s.aad2ecebc6.js +0 -94
  208. package/dist/client/static/js/async/vt.20406a5604.js +0 -1
  209. package/dist/client/static/js/async/x1.fe8af17016.js +0 -90
  210. package/dist/client/static/js/async/xn.6360379f71.js.LICENSE.txt +0 -6
  211. package/dist/client/static/js/async/yg.5a94e1fc8a.js +0 -149
  212. package/dist/client/static/js/async/yv.2fa22f009a.js +0 -1
  213. package/dist/client/static/js/index.5fe7a2cb64.js +0 -34
  214. package/src/client/components/workspace/btw-panel/Composer.tsx +0 -183
  215. package/src/client/components/workspace/btw-panel/attachments.ts +0 -80
  216. /package/dist/client/static/js/{77.8022a800b5.js.LICENSE.txt → 77.0d81c74cf0.js.LICENSE.txt} +0 -0
  217. /package/dist/client/static/js/async/{g.ee41bfed7f.js.LICENSE.txt → 1k.973e8e21fc.js.LICENSE.txt} +0 -0
  218. /package/dist/client/static/js/async/{3y.3186ecdd63.js.LICENSE.txt → 3y.3530b824ad.js.LICENSE.txt} +0 -0
  219. /package/dist/client/static/js/async/{ot.84c71b308f.js.LICENSE.txt → 4m.928a1dde85.js.LICENSE.txt} +0 -0
  220. /package/dist/client/static/js/async/{q.b453193538.js.LICENSE.txt → ar.9303e5f2e8.js.LICENSE.txt} +0 -0
  221. /package/dist/client/static/js/async/{1k.a411fe5b43.js.LICENSE.txt → q.33d6779f98.js.LICENSE.txt} +0 -0
  222. /package/dist/client/static/js/async/{ar.ad5c8822a8.js.LICENSE.txt → xn.6510c0abe2.js.LICENSE.txt} +0 -0
  223. /package/dist/client/static/js/{index.5fe7a2cb64.js.LICENSE.txt → index.c05535dbde.js.LICENSE.txt} +0 -0
package/README.md CHANGED
@@ -1,88 +1,103 @@
1
1
  <p align="center">
2
- <img src="public/icon-512x512.png" alt="OMPChamber" width="180" height="180">
2
+ <img src="public/icon-512x512.png" alt="OMPChamber" width="140" height="140">
3
3
  </p>
4
4
 
5
5
  <h1 align="center">OMPChamber</h1>
6
6
 
7
7
  <p align="center">
8
- Developer web console and diagnostic chamber for <b>AI Oh-My-Pi</b>.<br>
8
+ Browser console and diagnostic chamber for <a href="https://github.com/can1357/oh-my-pi">Oh-My-Pi</a> (<code>omp</code>) agent sessions.<br>
9
9
  Watch, steer and audit autonomous coding sessions from one paper-flat dashboard.
10
10
  </p>
11
11
 
12
12
  <p align="center">
13
- <a href="https://bun.sh"><img alt="Runtime: Bun 1.4" src="https://img.shields.io/badge/runtime-Bun%201.4-000000?logo=bun&logoColor=white"></a>
14
- <a href="https://elysiajs.com"><img alt="Server: Elysia 1.4" src="https://img.shields.io/badge/server-Elysia%201.4-6f42c1"></a>
15
- <a href="https://preactjs.com"><img alt="UI: Preact 10" src="https://img.shields.io/badge/UI-Preact%2010-673ab7?logo=preact&logoColor=white"></a>
16
- <a href="https://rsbuild.dev"><img alt="Build: Rsbuild 2" src="https://img.shields.io/badge/build-Rsbuild%202-eab308"></a>
17
- <a href="package.json"><img alt="Version: 0.5.0" src="https://img.shields.io/badge/version-0.5.0-3f3f46"></a>
13
+ <a href="https://www.npmjs.com/package/ompchamber"><img alt="npm version" src="https://img.shields.io/npm/v/ompchamber?logo=npm&logoColor=white&color=cb3837"></a>
14
+ <a href="https://bun.sh"><img alt="Bun &ge; 1.4" src="https://img.shields.io/badge/Bun-%E2%89%A51.4-000000?logo=bun&logoColor=white"></a>
15
+ <a href="https://elysiajs.com"><img alt="Elysia" src="https://img.shields.io/github/package-json/dependency-version/rajebdev/ompchamber/elysia?color=6f42c1"></a>
16
+ <a href="https://preactjs.com"><img alt="Preact" src="https://img.shields.io/github/package-json/dependency-version/rajebdev/ompchamber/preact?logo=preact&logoColor=white&color=673ab7"></a>
17
+ <a href="https://shiki.style"><img alt="Shiki" src="https://img.shields.io/github/package-json/dependency-version/rajebdev/ompchamber/shiki?color=3f3f46"></a>
18
+ <a href="package.json"><img alt="Version" src="https://img.shields.io/github/package-json/v/rajebdev/ompchamber?label=version&color=3f3f46"></a>
18
19
  </p>
19
20
 
20
21
  <p align="center">
21
22
  <a href="AGENTS.md">Architecture</a> ·
22
- <a href="docs/MIGRATION-elysia-preact-rsbuild-bun.md">Migration guide</a> ·
23
- <a href="DESIGN.md">Design spec</a> ·
23
+ <a href="DESIGN.md">Design</a> ·
24
24
  <a href="CHANGELOG.md">Changelog</a> ·
25
25
  <a href="https://github.com/rajebdev/ompchamber/issues">Issues</a>
26
26
  </p>
27
27
 
28
- ---
28
+ ![OMPChamber — session sidebar, streaming timeline and the Files panel](docs/assets/hero-dark.png)
29
29
 
30
- ### [Read the docs →](AGENTS.md)
30
+ ## What it is
31
31
 
32
- ## What is OMPChamber?
33
-
34
- OMPChamber is the browser console for [Oh-My-Pi](https://github.com/rajebdev/ompchamber) (`omp`) agent
35
- sessions. It is not a wrapper around a terminal — it reads omp's own session JSONL, project
36
- registry, config and subagent transcripts, then folds them into one live view.
37
-
38
- One Elysia process serves the API and the client bundle. The agent event stream is a first-class
39
- WebSocket route on that same listener (SSE as fallback), so there is no second server to run and
40
- no proxy to configure.
32
+ The browser view onto a live `omp` install. It is not a terminal wrapper: the chamber reads
33
+ omp's own session JSONL, project registry, config and subagent transcripts, folds them into one
34
+ live view, and writes back through omp's RPC mode.
41
35
 
42
36
  ```bash
43
- bun run src/server/index.ts # API + WebSocket + static client on :3000
37
+ bun run src/server/index.ts # API + WebSocket + static client on :3000
44
38
  ```
45
39
 
46
- Every developer surface is a switchable right-hand panel — files, search, git, terminal, context
47
- telemetry, browser (headless and your own), usage — and each one remembers its own width.
40
+ - **One process.** Elysia serves the API and the client bundle, and the agent event stream is a
41
+ first-class WebSocket route on that same listener (SSE as fallback) — no second server, no proxy.
42
+ - **Two data modes.** `MOCK=false` (the default, also when unset) runs on the real SQLite database
43
+ and your real workspace; `MOCK=true` swaps in bundled demo datasets. Every screenshot and
44
+ recording on this page was captured in `MOCK=true`.
45
+ - **Bun only.** The server imports `bun:sqlite`, and sessions, config and updates shell out to the
46
+ `omp` binary.
48
47
 
49
- ```bash
50
- ompchamber # start the server (default command)
51
- ompchamber serve --lan --prod # expose on 0.0.0.0, serve the production build
52
- ompchamber logs -f -n 200 # follow the server log
53
- ```
48
+ ## Feature tour
49
+
50
+ ![Feature tour — panels, search, terminal, telemetry](docs/assets/tour.gif)
54
51
 
55
- ## Features
56
-
57
- - **Live session timeline** — streaming thinking blocks, tool-call cards with structured
58
- renderers, provider/model metadata, stick-to-bottom scroll and a persistent message queue.
59
- - **In-place undo** — rewind an omp session by truncating its JSONL, guarded by a confirmation
60
- step and reflected in the sidebar immediately.
61
- - **Workspace sidebar** — folder → session tree backed by omp's project registry, with
62
- server-authoritative per-session stream status, search, sort and archive.
63
- - **Editor + diff** — tabbed file editing and git diffs highlighted by Shiki with the
64
- `one-light` / `one-dark-pro` pair across 26+ extra languages.
65
- - **Eight developer panels** — files, search (ripgrep-backed, streaming), git source control,
66
- Bun terminal, context & token telemetry, your browser, headless browser, usage.
67
- - **Full omp settings surface** — OMP Engine config keys, providers, agents, behavior
68
- (`AGENTS.md` / `RULES.md`), slash commands, MCP servers with live connection tests, skills and
69
- the skills catalog, token usage and notifications.
70
- - **Two data modes** — `MOCK=false` (the default, also when unset) runs purely on the real SQLite
71
- database and real workspace files; `MOCK=true` opts into demo datasets for previews.
72
- - **Self-update** — `ompchamber update` installs the latest GitHub release (bun global or git
73
- checkout) and restarts the instance it started; **About → Updates** does the same from the console,
74
- restart included.
52
+ <sub>Full-quality recording (MP4, 27s): [docs/assets/tour.mp4](docs/assets/tour.mp4) · theme cycle in motion: [docs/assets/themes.gif](docs/assets/themes.gif)</sub>
53
+
54
+ | | |
55
+ |---|---|
56
+ | ![Files panel](docs/assets/panel-files.png)<br>**Files** — project tree, opened-file tabs, one repo picker shared with the other panels | ![Search panel](docs/assets/panel-search.png)<br>**Search** — ripgrep-backed streaming results, scoped to the picked repo |
57
+ | ![Source control](docs/assets/panel-git.png)<br>**Source control** — staged/unstaged changes, commits, branches, tracking state | ![Editor and diff](docs/assets/panel-diff.png)<br>**Editor &amp; diff** — split or unified diffs, Shiki highlighting, images as pictures |
58
+ | ![Terminal](docs/assets/panel-terminal.png)<br>**Terminal** — a real PTY (one shell per terminal id, scrollback replayed on reload) | ![Context and telemetry](docs/assets/panel-context.png)<br>**Context &amp; telemetry** — context window use, cache hit rate, cost, per-turn breakdown |
59
+ | ![Usage](docs/assets/panel-usage.png)<br>**Usage** — provider balance, plan windows, per-model token spend | ![Appearance settings](docs/assets/settings-themes.png)<br>**Settings** — appearance, chats, OMP engine, providers, agents, commands, MCP, skills |
60
+ | ![Mobile view — chat, sessions drawer and the panel rail on a phone](docs/assets/mobile.png)<br>**Mobile view** — the same session on a phone: chat, sessions drawer, the full panel rail | ![Light theme](docs/assets/hero-light.png)<br>**Any palette** — 45 light and dark themes, applied to the whole console |
61
+
62
+ - **Chat timeline** — streaming thinking blocks, tool-call cards with a structured renderer per tool
63
+ (bash, LSP, AST edit, hub tasks, mermaid diagrams you can zoom), usage footers, a persistent
64
+ follow-up queue, a jump rail that reaches any user turn, drag-and-drop attachments, one-shot
65
+ auto-titling, and in-place undo that rewinds a session by truncating its JSONL behind a
66
+ confirmation step.
67
+ - **Side questions** (`/btw [question]`) — replaces the composer with a panel that answers from a
68
+ private copy of the session file, so the parent transcript is never written; a topic can be
69
+ promoted into a session of its own, and it runs the same tool cards, thinking and usage rows as
70
+ the chat.
71
+ - **Workspace sidebar** — folder → session tree off omp's project registry, with search, sort,
72
+ archive, per-session stream status and subagent rows.
73
+ - **Eight right-panel views** — files, search, git, terminal, context &amp; telemetry, your browser,
74
+ the agent browser and usage, each remembering its own width per session.
75
+ - **Full omp settings surface** — engine config keys, providers, agents, `AGENTS.md` / `RULES.md`,
76
+ slash commands, MCP servers with live connection tests, skills and the skills catalog, token
77
+ usage and notifications.
78
+ - **Self-update** — `ompchamber update` installs the latest GitHub release, and **About → Updates**
79
+ does the same from the console, restart included.
80
+
81
+ ## Themes
82
+
83
+ ![Six of the 45 palettes](docs/assets/theme-grid.png)
84
+
85
+ 45 palettes in one catalog (`src/shared/lib/theme/`): the chamber's own three (`paper`, `contrast`,
86
+ `one-dark-pro-soft`) and 21 light/dark pairs — Catppuccin, Gruvbox, Tokyo Night, Nord, Dracula,
87
+ Solarized, Kanagawa, Vesper and more. Switching repaints everything, syntax highlighting and
88
+ Mermaid diagrams included, through one writer (`applyDocumentTheme`) that sets `data-theme` and
89
+ announces it.
75
90
 
76
91
  ## Install
77
92
 
78
- OMPChamber is published to npm. It needs a Bun runtime, not Node:
93
+ OMPChamber is published to npm and runs on Bun, not Node:
79
94
 
80
- > **Bun only** — the server imports `bun:sqlite` and `Bun.YAML`, both of which Node cannot load.
81
- > `bun` 1.4 or newer is required.
95
+ > **Bun only** — the server imports `bun:sqlite` and `Bun.YAML`, neither of which Node can load.
96
+ > Bun 1.4 or newer is required.
82
97
 
83
98
  > **omp required** — every live capability (agent sessions, omp config, session state, updates)
84
- > shells out to the `omp` binary, so `serve` refuses to start when it cannot be resolved on `PATH`
85
- > (or via `OMPCHAMBER_OMP_BIN`). `MOCK=true` is the only mode that runs without a real omp install.
99
+ > shells out to the `omp` binary, so `serve` refuses to start when it is not on `PATH` (or set via
100
+ > `OMPCHAMBER_OMP_BIN`). `MOCK=true` is the only mode that runs without a real omp install.
86
101
 
87
102
  ```bash
88
103
  bun add -g ompchamber # puts the `ompchamber` command on your PATH
@@ -90,8 +105,8 @@ ompchamber serve --prod # start the server on :3000
90
105
  ```
91
106
 
92
107
  The published tarball carries the source, the CLI and the prebuilt client bundle, so there is no
93
- build step after install — `serve` runs immediately. `npm install -g ompchamber` works too, because
94
- the `ompchamber` bin is a Bun script: Bun still has to be on `PATH`.
108
+ build step after install. `npm install -g ompchamber` works too — the `ompchamber` bin is a Bun
109
+ script, so Bun still has to be on `PATH`.
95
110
 
96
111
  ### From source
97
112
 
@@ -103,39 +118,28 @@ bun run build # dist/client — the only build artifact
103
118
 
104
119
  bun run start # NODE_ENV=production bun run src/server/index.ts
105
120
  bun link # then: ompchamber status
106
- bun run src/cli/ompchamber.js status
107
121
  ```
108
122
 
109
- > **Serve before you build?** Without `dist/client` the server answers `503` and prints the exact
110
- > command to run — it never fails with a bare `500`.
123
+ > Without `dist/client` the server answers `503` with the exact command to run — never a bare `500`.
111
124
 
112
125
  ### Updating
113
126
 
114
- `ompchamber update` resolves the newest GitHub release, compares it with the version in
115
- `package.json` and replaces the install in place:
116
-
117
127
  ```bash
118
128
  ompchamber update --check # report only: current version, latest release
119
129
  ompchamber update # install it, then restart a running instance
120
130
  ompchamber update --force # reinstall even when already up to date
121
131
  ```
122
132
 
123
- How the install is replaced depends on how it was made. A **bun global** install is refreshed with
124
- `bun add -g ompchamber@<version>`. A **git checkout** of this repository is fast-forwarded to the
125
- release tag and rebuilt (`bun install`, `bun run build`). Uncommitted work is never merged over:
126
- the update refuses and asks you to commit or stash first. An install owned by another package
127
- manager is not touched — the command prints the exact command to run instead.
133
+ A **bun global** install is refreshed with `bun add -g ompchamber@<version>`; a **git checkout** is
134
+ fast-forwarded to the release tag and rebuilt. Uncommitted work is never merged over (the update asks
135
+ you to commit or stash first), and an install owned by another package manager is left alone and told
136
+ which command to run.
128
137
 
129
- The same check runs from the console — **About → Updates**. Its Update button performs the same
130
- install and then restarts the instance serving that console, exactly as `ompchamber update` restarts
131
- the instance it finds: a detached `ompchamber restart --port <port>` is armed a moment after the
132
- response, so the server that answered is replaced without losing the reply, and the console
133
- reconnects on its own.
134
-
135
- A server OMPChamber did not start is never restarted. `bun run dev`, `bun run start`, a manual
136
- `bun src/server/index.ts` and an instance owned by a supervisor (systemd, pm2, a container) all
137
- record themselves as `direct`, so the update leaves them running and says so — their own launcher is
138
- what picks up the new files. `--no-restart` turns the restart off entirely.
138
+ A server OMPChamber did not start is never restarted: `bun run dev`, `bun run start`, a manual
139
+ `bun src/server/index.ts` and instances owned by a supervisor (systemd, pm2, a container) all record
140
+ themselves as `direct`, so the update leaves them running and says so. `--no-restart` turns the
141
+ restart off entirely. The console's **About → Updates** runs the same install and restarts the
142
+ instance serving that console.
139
143
 
140
144
  ## CLI
141
145
 
@@ -152,11 +156,11 @@ what picks up the new files. `--no-restart` turns the restart off entirely.
152
156
 
153
157
  | Option | Purpose |
154
158
  |---|---|
155
- | `-p, --port <port>` | Web server port (default `3000`) |
156
- | `--host <address>` | Bind address (default `127.0.0.1`) |
159
+ | `-p, --port <port>` | Web server port (default `3000`); scopes `status`/`stop`/`restart`/`logs` |
160
+ | `--host <address>` (`--hostname`) | Bind address (default `127.0.0.1`) |
157
161
  | `--lan` | Bind to `0.0.0.0` for LAN access |
158
162
  | `--prod` | Serve the production build instead of the dev server |
159
- | `--foreground` | Run in the foreground (no daemon) |
163
+ | `--foreground` (`--no-daemon`) | Run in the foreground (no daemon) |
160
164
  | `--all` | Apply the command to every running instance |
161
165
  | `-c, --check` | Report whether a newer release exists without installing it |
162
166
  | `--force` | Reinstall even when already up to date |
@@ -167,9 +171,8 @@ what picks up the new files. `--no-restart` turns the restart off entirely.
167
171
  ### Ports and multiple instances
168
172
 
169
173
  One port is served by exactly one process, and `bun run dev`, `ompchamber serve` and the production
170
- server all default to `3000`. **A starting instance never stops another one** — not a CLI server
171
- and not a dev run. If the port is taken by OMPChamber, the newcomer reports who holds it and exits
172
- non-zero so you can pick another port and re-run:
174
+ server all default to `3000`. **A starting instance never stops another one** — if the port is taken
175
+ by OMPChamber, the newcomer reports who holds it and exits non-zero so you can pick another port:
173
176
 
174
177
  ```bash
175
178
  ompchamber serve --port 3001 # CLI flag
@@ -177,40 +180,19 @@ OMPCHAMBER_PORT=3001 ompchamber serve
177
180
  PORT=3001 bun run dev # or: PORT=3001 bun run start
178
181
  ```
179
182
 
180
- - Nothing is ever signalled to free a port. `ompchamber stop --port 3000` is the deliberate way to
181
- free one, and it is per port.
182
- - A process that is **not** OMPChamber is never signalled either: the server exits with an error
183
- naming the port and the `lsof -nP -iTCP:<port> -sTCP:LISTEN` command to identify it.
184
- - The refusal exists because a second bind would *succeed*: Elysia's Bun adapter hardcodes
185
- `reusePort: true`, so two servers would share a port and only the first-bound socket would receive
186
- connections — the newcomer would look healthy while the browser kept talking to the old build.
187
- - `bun run dev` hot reload is unaffected: `--hot` re-evaluates the server entry *inside the running
188
- process*, and a port held by that same process is recognized as its own, so Bun swaps the handler
189
- on the next `listen`. Saving a file neither trips the guard nor resets the reported uptime.
190
-
191
- Running several ports at once is supported. `status`, `stop`, `restart` and `logs` act on **every**
192
- live instance by default, and `--port <port>` narrows them to one. `restart` is the one exception to
193
- "every": an instance started from source is reported and left running, exactly as `ompchamber update`
194
- leaves it — `status`/`stop`/`logs` still see it, and `stop` still ends it:
195
-
196
- ```bash
197
- ompchamber status # every instance: port, pid, mode, launch mode, health, log
198
- ompchamber status --port 3001 # just that one
199
- ompchamber logs -n 200 # one header per instance, sources included
200
- ompchamber logs --port 3001 -f # follow one instance's log
201
- ompchamber stop # stop them all (--all is the explicit spelling)
202
- ompchamber stop --port 3001 # stop just that one
203
- ompchamber restart # restart the CLI-started ones, skip a `bun run dev`
204
- ```
183
+ - Nothing is ever signalled to free a port; `ompchamber stop --port 3000` is the deliberate way.
184
+ - A process that is **not** OMPChamber is never signalled either: the server names the port and
185
+ prints the `lsof -nP -iTCP:<port> -sTCP:LISTEN` command to identify it.
186
+ - `bun run dev` hot reload is unaffected: `--hot` re-evaluates the entry inside the running
187
+ process, and a port held by that process is recognized as its own.
188
+ - `status`, `stop`, `restart` and `logs` act on **every** live instance by default; `--port <port>`
189
+ narrows them to one. `restart` skips instances started from source, as `update` does.
205
190
 
206
- The server writes `~/.ompchamber/run/<port>.json` (`pid`, `host`, `mode`, `launchMode`,
207
- `startedAt`) once it owns the port, which is why `status`/`stop`/`logs` also see servers started by
208
- `bun run dev` or `--foreground` — not just daemon-spawned ones. `launchMode` is `daemon` or
209
- `foreground` for a server the CLI spawned and `direct` for every other launch, and it is derived from
210
- the process's **argv**, never from an environment variable: env is inherited, so a `bun run dev`
211
- started inside an OMPChamber shell would otherwise be mislabelled and replaced by an update. Records
212
- left by a killed server are pruned as soon as their PID stops answering, so a recycled PID is never
213
- reported as an instance.
191
+ The server writes `~/.ompchamber/run/<port>.json` (`pid`, `host`, `mode`, `launchMode`, `startedAt`)
192
+ once it owns the port, which is how `status`/`stop`/`logs` also see servers started by `bun run dev`
193
+ or `--foreground`. `launchMode` is derived from the process's **argv**, never from an environment
194
+ variable — env is inherited, so a `bun run dev` started inside an OMPChamber shell would otherwise be
195
+ replaced by an update. Records left by a killed server are pruned once their PID stops answering.
214
196
 
215
197
  ## Configuration
216
198
 
@@ -232,8 +214,8 @@ Environment variables, read from `.env` (see [`.env.example`](.env.example)):
232
214
  | `SKILLS_API_URL` | `https://skills.sh` | Skills catalog source |
233
215
  | `GITHUB_TOKEN` / `GH_TOKEN` | — | Raise the GitHub API rate limit for update checks |
234
216
 
235
- Runtime state, sessions and settings live in SQLite (`~/.ompchamber/db.sqlite`), which is the
236
- single source of truth for persisted settings.
217
+ Runtime state, sessions and settings live in SQLite (`~/.ompchamber/db.sqlite`), the single source
218
+ of truth for persisted settings.
237
219
 
238
220
  ## Architecture
239
221
 
@@ -256,12 +238,13 @@ Non-obvious invariants worth reading before you edit:
256
238
 
257
239
  - **`src/shared/**` must never import a `node:` builtin or `bun:sqlite`** — it also runs in the
258
240
  browser. Server-only helpers belong in `src/server/lib/**`.
259
- - **Route modules keep the ported Remix shape** (`loader` for GET, `action` for mutations) so
260
- status codes stay identical; `action` owns method dispatch and returns its own `405`.
241
+ - **Route modules keep the ported Remix shape** (`loader` for GET, `action` for mutations) so status
242
+ codes stay identical; `action` owns method dispatch and returns its own `405`.
261
243
  - **Every internal import uses the `@/` alias**, folders mirror component names in kebab-case, and
262
244
  every `.ts`/`.tsx` file stays under 350 lines.
263
245
 
264
- [`AGENTS.md`](AGENTS.md) is the normative reference for all of the above.
246
+ [`AGENTS.md`](AGENTS.md) is the normative reference for all of the above — the invariants behind the
247
+ panels, the BTW subsystem, the PTY terminal and the build/dev loop.
265
248
 
266
249
  ## Development
267
250
 
@@ -273,12 +256,8 @@ bun run dev:client # client only (rsbuild build --watch)
273
256
  ```
274
257
 
275
258
  There is no HMR: the server reloads on save, the client bundle rebuilds, refresh the page.
276
- `dist/client/index.html` is the shell for both dev and prod, so run `dev:client` at least once
277
- after a clean checkout.
278
-
279
- Dev and prod share the default port `3000`: a second starter on an occupied port refuses and exits
280
- with the port options to re-run ([Ports and multiple instances](#ports-and-multiple-instances));
281
- nothing is stopped for you.
259
+ `dist/client/index.html` is the shell for both dev and prod, so run `dev:client` at least once after
260
+ a clean checkout.
282
261
 
283
262
  Verification gates, all mandatory:
284
263
 
@@ -289,29 +268,34 @@ bun run build # production bundl
289
268
  bun test # bun test
290
269
  ```
291
270
 
292
- ## Releasing
293
-
294
- Publishing is driven by **GitHub releases**, never by a push
295
- ([`.github/workflows/publish.yml`](.github/workflows/publish.yml)):
296
-
297
- ```bash
298
- bun pm version minor -m "chore(release): v%s" # bump + commit + tag v0.5.0
299
- git push origin main --tags
300
- # then publish the release on GitHub → the workflow publishes to npm
301
- ```
302
-
303
- The workflow checks out the released tag, installs, verifies the tag against the `package.json`
304
- version, typechecks, runs `bun test`, builds `dist/client`, packs a dry run, then runs `bun publish`.
305
- One thing to set up once:
271
+ The screenshots, GIFs and the MP4 in [`docs/assets`](docs/assets) are captured from a scratch
272
+ checkout running `MOCK=true` (`PORT=3123`) with Playwright, so they contain demo data only — never a
273
+ real workspace.
306
274
 
307
- - GitHub environment **`NPM_TOKEN`** with a secret of the same name — a granular npm access token
308
- with read/write on `ompchamber`, 2FA bypass enabled, and the `publish and stage` action (a
309
- stage-only token is rejected: Bun has no `npm stage publish`). The job declares that environment,
310
- so the token is readable only by the publish workflow; add required reviewers there to gate a
311
- publish behind an approval.
275
+ ## Releasing
312
276
 
313
- A failed publish is retried from **Actions → Publish → Run workflow**, which leaves the release
314
- itself untouched.
277
+ A push to `main` cuts the release — there is no manual version bump
278
+ ([`.github/workflows/release.yml`](.github/workflows/release.yml)):
279
+
280
+ 1. `semantic-release` reads the Conventional Commits since the last tag, decides the next
281
+ version, writes it into `package.json` and a `## [x.y.z]` section of `CHANGELOG.md`, commits
282
+ both, then creates the tag and the GitHub Release. Only `feat`, `fix`, `perf`, `refactor`, `docs`
283
+ and `revert` can move a version (`bumpStrict` in [`release.config.mjs`](release.config.mjs));
284
+ `chore`, `style`, `test`, `build` and `ci` are hidden and bump nothing on their own.
285
+ 2. The same run dispatches [`publish.yml`](.github/workflows/publish.yml), which checks out the tag,
286
+ verifies it against `package.json`, typechecks, runs `bun test`, builds `dist/client`, packs a
287
+ dry run, and runs `bun publish` behind the **`npm` environment** approval gate.
288
+
289
+ Two things to set up once and one to never do:
290
+
291
+ - GitHub environment **`npm`** with a secret `NPM_TOKEN`: a granular npm token with read/write on
292
+ `ompchamber`, 2FA bypass enabled and the `publish and stage` action (a stage-only token is
293
+ rejected — Bun has no `npm stage publish`). Add required reviewers there to gate a publish.
294
+ - A failed publish is retried with `gh workflow run publish.yml -f tag=vX.Y.Z`, which leaves the
295
+ release itself untouched.
296
+ - **Never** write a skip marker (`[skip ci]`, `[ci skip]`, `[no ci]`) into a message pushed to
297
+ `main` — it scans the whole message and silently skips the release run. Only the bot's release
298
+ commit carries one, so that it does not re-trigger the workflow.
315
299
 
316
300
  ## License
317
301
 
@@ -1,8 +1,10 @@
1
1
  <!doctype html>
2
- <html lang="en" data-theme="paper">
2
+ <html lang="en" data-theme="paper" data-theme-variant="light">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
6
+ <!-- The theme's canvas color. The SSR shell rewrites this tag in place;
7
+ a second tag would be ignored, since Chrome reads the first. -->
6
8
  <meta name="theme-color" content="#faf8f3" />
7
9
  <meta name="mobile-web-app-capable" content="yes" />
8
10
  <meta name="apple-mobile-web-app-capable" content="yes" />
@@ -24,7 +26,7 @@
24
26
  href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"
25
27
  />
26
28
  <!--app-head-->
27
- <script defer src="/static/js/markdown-vendor.71e43278b3.js"></script><script defer src="/static/js/shiki-vendor.cb8452ddcd.js"></script><script defer src="/static/js/77.8022a800b5.js"></script><script defer src="/static/js/index.5fe7a2cb64.js"></script><link href="/static/css/index.b938f4a693.css" rel="stylesheet"></head>
29
+ <script defer src="/static/js/markdown-vendor.71e43278b3.js"></script><script defer src="/static/js/shiki-vendor.cb8452ddcd.js"></script><script defer src="/static/js/77.0d81c74cf0.js"></script><script defer src="/static/js/index.c05535dbde.js"></script><link href="/static/css/index.5f630421b7.css" rel="stylesheet"></head>
28
30
  <body>
29
31
  <div id="app"></div>
30
32
  <!--app-bootstrap-->