@bakapiano/ccsm 0.13.0 → 0.15.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 (53) hide show
  1. package/CLAUDE.md +474 -475
  2. package/README.md +189 -190
  3. package/bin/ccsm.js +194 -194
  4. package/lib/cliActivity.js +118 -0
  5. package/lib/codexSeed.js +147 -0
  6. package/lib/config.js +211 -188
  7. package/lib/folders.js +105 -105
  8. package/lib/localCliSessions.js +489 -489
  9. package/lib/persistedSessions.js +144 -142
  10. package/lib/webTerminal.js +224 -224
  11. package/lib/workspace.js +230 -230
  12. package/package.json +57 -57
  13. package/public/css/base.css +99 -99
  14. package/public/css/cards.css +183 -183
  15. package/public/css/feedback.css +303 -303
  16. package/public/css/forms.css +405 -405
  17. package/public/css/layout.css +160 -160
  18. package/public/css/modal.css +190 -190
  19. package/public/css/responsive.css +10 -10
  20. package/public/css/sidebar.css +613 -608
  21. package/public/css/terminals.css +294 -294
  22. package/public/css/tokens.css +81 -81
  23. package/public/css/wco.css +98 -98
  24. package/public/css/widgets.css +1628 -1628
  25. package/public/index.html +111 -105
  26. package/public/js/api.js +296 -280
  27. package/public/js/components/AdoptModal.js +343 -343
  28. package/public/js/components/App.js +35 -35
  29. package/public/js/components/DirectoryPicker.js +203 -203
  30. package/public/js/components/EntityFormModal.js +141 -141
  31. package/public/js/components/Modal.js +51 -51
  32. package/public/js/components/OfflineBanner.js +93 -93
  33. package/public/js/components/PageTitleBar.js +13 -13
  34. package/public/js/components/Picker.js +179 -179
  35. package/public/js/components/Popover.js +55 -55
  36. package/public/js/components/Sidebar.js +299 -299
  37. package/public/js/components/TerminalView.js +314 -314
  38. package/public/js/components/useDragSort.js +67 -67
  39. package/public/js/dialog.js +67 -67
  40. package/public/js/icons.js +177 -177
  41. package/public/js/main.js +132 -132
  42. package/public/js/pages/AboutPage.js +165 -165
  43. package/public/js/pages/ConfigurePage.js +505 -475
  44. package/public/js/pages/LaunchPage.js +369 -369
  45. package/public/js/pages/SessionsPage.js +101 -97
  46. package/public/js/state.js +231 -231
  47. package/scripts/dev.js +44 -11
  48. package/scripts/install.js +158 -137
  49. package/scripts/restart-helper.js +91 -0
  50. package/scripts/upgrade-helper.js +155 -0
  51. package/server.js +1278 -1232
  52. package/lib/cliSessionWatcher.js +0 -249
  53. package/public/manifest.webmanifest +0 -15
package/README.md CHANGED
@@ -1,190 +1,189 @@
1
- # ccsm — Claude Code Session Manager
2
-
3
- A single pane over every Claude / Codex / Copilot CLI session on your
4
- machine. Each session runs inside the page (xterm.js + a PTY pool in
5
- the local backend), gets recorded, and re-attaches to the exact
6
- upstream conversation when you click it again.
7
-
8
- [![open](https://img.shields.io/badge/open-bakapiano.github.io%2Fccsm-1a1815?style=flat-square)](https://bakapiano.github.io/ccsm/)
9
-
10
- ```
11
- ┌── browser ─────────────────────────┐
12
- │ https://bakapiano.github.io/ccsm/ ← version router
13
- │ ↓
14
- │ /ccsm/X.Y.Z/ ← per-version frontend (pinned to your backend)
15
- └────────────┬───────────────────────┘
16
- │ fetch /api/* (CORS)
17
- │ ws://localhost:7777/ws/*
18
-
19
- ┌── local backend ───────────────────┐
20
- │ ccsm (npm bin) │
21
- │ ├── /api/sessions /api/sessions/new │
22
- │ ├── /api/sessions/:id/resume │
23
- │ ├── /api/sessions/adopt │
24
- │ ├── /api/version /api/upgrade │
25
- │ ├── /ws/terminal/:id (PTY) │
26
- │ └── /api/health /api/heartbeat │
27
- └────────────────────────────────────┘
28
- ```
29
-
30
- ## What it does
31
-
32
- - **Runs every CLI session in the page.** `claude`, `codex`, `copilot`
33
- or any custom command, in an xterm.js panel. Switch sessions in the
34
- sidebar; the PTY keeps running in the backend.
35
- - **`--resume <uuid>` precision.** ccsm watches the upstream CLI's
36
- transcript dir after spawn and captures its session UUID. Click a
37
- stopped session later → re-spawns with `--resume <uuid>` (or
38
- whatever `resumeIdArgs` template you set per-CLI) so the exact
39
- conversation comes back.
40
- - **Import existing sessions.** Scans `~/.claude` / `~/.codex` /
41
- `~/.copilot` and lets you adopt any session ccsm didn't start.
42
- - **Workspaces + clones.** "New session" picks an unused workspace
43
- under your work-dir, clones selected repos with live `git clone
44
- --progress` streamed to per-repo progress bars, opens a fresh CLI
45
- there. Or pick any existing folder via the file browser.
46
- - **Folders.** Drag sessions into named folders for organisation.
47
- - **In-app upgrade.** About page checks npm for newer versions of
48
- ccsm and offers a one-click upgrade button. Backend self-restarts.
49
-
50
- ## Install
51
-
52
- ```bash
53
- npm i -g @bakapiano/ccsm
54
- ```
55
-
56
- This:
57
- - puts `ccsm` on your PATH
58
- - registers a `ccsm://` URL protocol so the hosted frontend can wake
59
- the backend with one click
60
-
61
- `npx @bakapiano/ccsm` works too for a one-shot trial — the protocol
62
- still gets registered.
63
-
64
- ## Use
65
-
66
- ```bash
67
- ccsm # starts the backend, opens the frontend
68
- ```
69
-
70
- Or just visit **https://bakapiano.github.io/ccsm/** in any browser.
71
- If the backend isn't running, the router shows a "Backend not running"
72
- banner with a **Start ccsm** button — click it, Windows asks once
73
- whether to open the `ccsm://` handler (check "Always allow"), and the
74
- backend spawns silently behind the page. The router auto-reconnects in
75
- 1-2s and redirects to the frontend matching your installed backend
76
- version.
77
-
78
- ### Install as PWA
79
-
80
- In Chrome / Edge, click the install icon in the address bar (or use the
81
- "Install ccsm" button on the **About** tab inside the app). The PWA gets
82
- its own window, its own icon, and Window Controls Overlay so the title
83
- bar blends into the page.
84
-
85
- After installing, clicking the PWA icon is the new entry point — no
86
- terminal needed.
87
-
88
- ## Defaults
89
-
90
- | | |
91
- |---|---|
92
- | Port | `7777` (auto-bumps if taken) |
93
- | Work dir | `~/ccsm-workspaces` (each subdirectory holds one or more repo clones) |
94
- | Built-in CLIs | `claude`, `codex`, `copilot` — add your own via the **Configure** tab |
95
- | Data dir | `~/.ccsm/` (override with `CCSM_HOME=<path>`) — survives upgrades and npx cache wipes |
96
-
97
- All of the above are editable through the **Configure** tab.
98
-
99
- ## Layout
100
-
101
- ```
102
- ccsm/
103
- ├── server.js # Express + WebSocket; API only in prod
104
- ├── bin/ccsm.js # launcher · detaches server, opens browser
105
- ├── scripts/
106
- │ ├── install.js # postinstall · registers ccsm:// (Windows)
107
- │ └── uninstall.js # preuninstall · cleanup
108
- ├── lib/
109
- │ ├── persistedSessions.js # ~/.ccsm/sessions.json — the source of truth
110
- │ ├── folders.js # sidebar tree
111
- │ ├── localCliSessions.js # scan ~/.claude · ~/.codex · ~/.copilot
112
- │ ├── cliSessionWatcher.js # capture upstream session UUID after spawn
113
- │ ├── workspace.js # ws-N allocation + repo clones
114
- │ ├── webTerminal.js # node-pty pool · WebSocket bridge
115
- ├── jsonStore.js · config.js
116
- ├── pages-root/ # → GH Pages / (version router)
117
- └── public/ # → GH Pages /<pkg.version>/ (per-version frontend)
118
-
119
- ~/.ccsm/ # or $CCSM_HOME
120
- ├── config.json
121
- ├── sessions.json # persisted sessions
122
- ├── folders.json
123
- ├── server.log
124
- └── browser-profile/ # Edge/Chrome --user-data-dir
125
- ```
126
-
127
- ## How "wake on click" works
128
-
129
- The hosted frontend lives entirely in the browser sandbox it cannot
130
- spawn processes. So when the backend is down, the OfflineBanner's
131
- **Start ccsm** is a plain `<a href="ccsm://start">`. The OS hands that
132
- off to a per-user URL protocol handler registered at install time:
133
-
134
- ```
135
- HKCU\Software\Classes\ccsm\shell\open\command
136
- → wscript.exe "<LOCALAPPDATA>\ccsm\launcher.vbs" "%1"
137
- ```
138
-
139
- The `.vbs` calls `ccsm.cmd "ccsm://start"` with `WindowStyle = 0`. That
140
- gets to `bin/ccsm.js`, which parses the protocol URL, spawns
141
- `server.js` detached, and exits. Zero windows ever flash.
142
-
143
- First click triggers a one-time Windows dialog ("Open ccsm.cmd?"). Tick
144
- **Always allow** and future clicks are silent.
145
-
146
- ## Lifecycle (when does the backend die)
147
-
148
- | trigger | reaction |
149
- |---|---|
150
- | The auto-opened browser window closes | wait 12s · if any other client heartbeats during that window, stay alive; otherwise gracefulShutdown |
151
- | No heartbeat for 90s | gracefulShutdown |
152
- | `POST /api/shutdown` | gracefulShutdown |
153
- | `POST /api/upgrade` after install | self-respawn + gracefulShutdown |
154
- | SIGINT / SIGTERM | gracefulShutdown |
155
-
156
- ## Dev
157
-
158
- ```bash
159
- git clone https://github.com/bakapiano/ccsm
160
- cd ccsm
161
- npm install
162
- CCSM_NO_BROWSER=1 CCSM_KEEP_ALIVE=1 node server.js
163
- # opens http://localhost:7777 with hot-reload (public/ is served locally
164
- # and SSE pushes a reload event on every file save)
165
- ```
166
-
167
- Dev mode is detected via `__dirname.includes('node_modules')` when
168
- running from a checkout, the backend also serves `public/`. In an
169
- npm-installed copy it's API-only, and you use the hosted frontend.
170
-
171
- ## Versioning (frontend ↔ backend)
172
-
173
- The hosted root (`/ccsm/`) is a tiny static **version router**: it
174
- probes `localhost:7777/api/health`, then redirects you to
175
- `/ccsm/<backend.version>/`. Each release publishes a fresh
176
- per-version subdir; old ones stay forever. No semver-compat logic a
177
- frontend is always 1:1 with the backend it was built against.
178
-
179
- If your backend gets upgraded under a still-loaded page, the
180
- per-version frontend detects the mismatch on its next probe and
181
- bounces you back through the router automatically.
182
-
183
- ## Status
184
-
185
- - Backend: Windows-first. macOS / Linux backend ports planned (URL
186
- protocol registration is the only platform-specific install piece).
187
- - Frontend: cross-platform (pure web).
188
-
189
- See [CLAUDE.md](CLAUDE.md) for design decisions and the non-obvious
190
- gotchas baked into the launcher / session-watcher / lifecycle code.
1
+ # ccsm — Claude Code Session Manager
2
+
3
+ A single pane over every Claude / Codex / Copilot CLI session on your
4
+ machine. Each session runs inside the page (xterm.js + a PTY pool in
5
+ the local backend), gets recorded, and re-attaches to the exact
6
+ upstream conversation when you click it again.
7
+
8
+ [![open](https://img.shields.io/badge/open-bakapiano.github.io%2Fccsm-1a1815?style=flat-square)](https://bakapiano.github.io/ccsm/)
9
+
10
+ ```
11
+ ┌── browser ─────────────────────────┐
12
+ │ https://bakapiano.github.io/ccsm/ ← version router
13
+ │ ↓
14
+ │ /ccsm/X.Y.Z/ ← per-version frontend (pinned to your backend)
15
+ └────────────┬───────────────────────┘
16
+ │ fetch /api/* (CORS)
17
+ │ ws://localhost:7777/ws/*
18
+
19
+ ┌── local backend ───────────────────┐
20
+ │ ccsm (npm bin) │
21
+ │ ├── /api/sessions /api/sessions/new │
22
+ │ ├── /api/sessions/:id/resume │
23
+ │ ├── /api/sessions/adopt │
24
+ │ ├── /api/version /api/upgrade │
25
+ │ ├── /ws/terminal/:id (PTY) │
26
+ │ └── /api/health /api/heartbeat │
27
+ └────────────────────────────────────┘
28
+ ```
29
+
30
+ ## What it does
31
+
32
+ - **Runs every CLI session in the page.** `claude`, `codex`, `copilot`
33
+ or any custom command, in an xterm.js panel. Switch sessions in the
34
+ sidebar; the PTY keeps running in the backend.
35
+ - **`--resume <uuid>` precision.** ccsm watches the upstream CLI's
36
+ transcript dir after spawn and captures its session UUID. Click a
37
+ stopped session later → re-spawns with `--resume <uuid>` (or
38
+ whatever `resumeIdArgs` template you set per-CLI) so the exact
39
+ conversation comes back.
40
+ - **Import existing sessions.** Scans `~/.claude` / `~/.codex` /
41
+ `~/.copilot` and lets you adopt any session ccsm didn't start.
42
+ - **Workspaces + clones.** "New session" picks an unused workspace
43
+ under your work-dir, clones selected repos with live `git clone
44
+ --progress` streamed to per-repo progress bars, opens a fresh CLI
45
+ there. Or pick any existing folder via the file browser.
46
+ - **Folders.** Drag sessions into named folders for organisation.
47
+ - **In-app upgrade.** About page checks npm for newer versions of
48
+ ccsm and offers a one-click upgrade button. Backend self-restarts.
49
+
50
+ ## Install
51
+
52
+ ```bash
53
+ npm i -g @bakapiano/ccsm
54
+ ```
55
+
56
+ This:
57
+ - puts `ccsm` on your PATH
58
+ - registers a `ccsm://` URL protocol so the hosted frontend can wake
59
+ the backend with one click
60
+
61
+ `npx @bakapiano/ccsm` works too for a one-shot trial — the protocol
62
+ still gets registered.
63
+
64
+ ## Use
65
+
66
+ ```bash
67
+ ccsm # starts the backend, opens the frontend
68
+ ```
69
+
70
+ Or just visit **https://bakapiano.github.io/ccsm/** in any browser.
71
+ If the backend isn't running, the router shows a "Backend not running"
72
+ banner with a **Start ccsm** button — click it, Windows asks once
73
+ whether to open the `ccsm://` handler (check "Always allow"), and the
74
+ backend spawns silently behind the page. The router auto-reconnects in
75
+ 1-2s and redirects to the frontend matching your installed backend
76
+ version.
77
+
78
+ ### Install as PWA
79
+
80
+ In Chrome / Edge, click the install icon in the address bar (or use the
81
+ "Install ccsm" button on the **About** tab inside the app). The PWA gets
82
+ its own window, its own icon, and Window Controls Overlay so the title
83
+ bar blends into the page.
84
+
85
+ After installing, clicking the PWA icon is the new entry point — no
86
+ terminal needed.
87
+
88
+ ## Defaults
89
+
90
+ | | |
91
+ |---|---|
92
+ | Port | `7777` (auto-bumps if taken) |
93
+ | Work dir | `~/ccsm-workspaces` (each subdirectory holds one or more repo clones) |
94
+ | Built-in CLIs | `claude`, `codex`, `copilot` — add your own via the **Configure** tab |
95
+ | Data dir | `~/.ccsm/` (override with `CCSM_HOME=<path>`) — survives upgrades and npx cache wipes |
96
+
97
+ All of the above are editable through the **Configure** tab.
98
+
99
+ ## Layout
100
+
101
+ ```
102
+ ccsm/
103
+ ├── server.js # Express + WebSocket; API only in prod
104
+ ├── bin/ccsm.js # launcher · detaches server, opens browser
105
+ ├── scripts/
106
+ │ ├── install.js # postinstall · registers ccsm:// (Windows)
107
+ │ └── uninstall.js # preuninstall · cleanup
108
+ ├── lib/
109
+ │ ├── persistedSessions.js # ~/.ccsm/sessions.json — the source of truth
110
+ │ ├── folders.js # sidebar tree
111
+ │ ├── localCliSessions.js # scan ~/.claude · ~/.codex · ~/.copilot
112
+ │ ├── workspace.js # ws-N allocation + repo clones
113
+ │ ├── webTerminal.js # node-pty pool · WebSocket bridge
114
+ │ ├── jsonStore.js · config.js
115
+ ├── pages-root/ # GH Pages / (version router)
116
+ └── public/ # → GH Pages /<pkg.version>/ (per-version frontend)
117
+
118
+ ~/.ccsm/ # or $CCSM_HOME
119
+ ├── config.json
120
+ ├── sessions.json # persisted sessions
121
+ ├── folders.json
122
+ ├── server.log
123
+ └── browser-profile/ # Edge/Chrome --user-data-dir
124
+ ```
125
+
126
+ ## How "wake on click" works
127
+
128
+ The hosted frontend lives entirely in the browser sandbox — it cannot
129
+ spawn processes. So when the backend is down, the OfflineBanner's
130
+ **Start ccsm** is a plain `<a href="ccsm://start">`. The OS hands that
131
+ off to a per-user URL protocol handler registered at install time:
132
+
133
+ ```
134
+ HKCU\Software\Classes\ccsm\shell\open\command
135
+ → wscript.exe "<LOCALAPPDATA>\ccsm\launcher.vbs" "%1"
136
+ ```
137
+
138
+ The `.vbs` calls `ccsm.cmd "ccsm://start"` with `WindowStyle = 0`. That
139
+ gets to `bin/ccsm.js`, which parses the protocol URL, spawns
140
+ `server.js` detached, and exits. Zero windows ever flash.
141
+
142
+ First click triggers a one-time Windows dialog ("Open ccsm.cmd?"). Tick
143
+ **Always allow** and future clicks are silent.
144
+
145
+ ## Lifecycle (when does the backend die)
146
+
147
+ | trigger | reaction |
148
+ |---|---|
149
+ | The auto-opened browser window closes | wait 12s · if any other client heartbeats during that window, stay alive; otherwise gracefulShutdown |
150
+ | No heartbeat for 90s | gracefulShutdown |
151
+ | `POST /api/shutdown` | gracefulShutdown |
152
+ | `POST /api/upgrade` after install | self-respawn + gracefulShutdown |
153
+ | SIGINT / SIGTERM | gracefulShutdown |
154
+
155
+ ## Dev
156
+
157
+ ```bash
158
+ git clone https://github.com/bakapiano/ccsm
159
+ cd ccsm
160
+ npm install
161
+ CCSM_NO_BROWSER=1 CCSM_KEEP_ALIVE=1 node server.js
162
+ # opens http://localhost:7777 with hot-reload (public/ is served locally
163
+ # and SSE pushes a reload event on every file save)
164
+ ```
165
+
166
+ Dev mode is detected via `__dirname.includes('node_modules')` — when
167
+ running from a checkout, the backend also serves `public/`. In an
168
+ npm-installed copy it's API-only, and you use the hosted frontend.
169
+
170
+ ## Versioning (frontend ↔ backend)
171
+
172
+ The hosted root (`/ccsm/`) is a tiny static **version router**: it
173
+ probes `localhost:7777/api/health`, then redirects you to
174
+ `/ccsm/<backend.version>/`. Each release publishes a fresh
175
+ per-version subdir; old ones stay forever. No semver-compat logic — a
176
+ frontend is always 1:1 with the backend it was built against.
177
+
178
+ If your backend gets upgraded under a still-loaded page, the
179
+ per-version frontend detects the mismatch on its next probe and
180
+ bounces you back through the router automatically.
181
+
182
+ ## Status
183
+
184
+ - Backend: Windows-first. macOS / Linux backend ports planned (URL
185
+ protocol registration is the only platform-specific install piece).
186
+ - Frontend: cross-platform (pure web).
187
+
188
+ See [CLAUDE.md](CLAUDE.md) for design decisions and the non-obvious
189
+ gotchas baked into the launcher / session-watcher / lifecycle code.