@bakapiano/ccsm 0.8.4 → 0.10.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.
- package/CLAUDE.md +222 -195
- package/README.md +78 -80
- package/bin/ccsm.js +1 -1
- package/lib/cliSessionWatcher.js +249 -0
- package/lib/config.js +101 -19
- package/lib/folders.js +96 -0
- package/lib/localCliSessions.js +177 -0
- package/lib/persistedSessions.js +134 -0
- package/lib/webTerminal.js +48 -13
- package/lib/workspace.js +26 -4
- package/package.json +4 -4
- package/public/assets/claude-color.svg +1 -0
- package/public/assets/codex-color.svg +1 -0
- package/public/assets/copilot-color.svg +1 -0
- package/public/css/base.css +22 -5
- package/public/css/cards.css +37 -3
- package/public/css/feedback.css +127 -43
- package/public/css/forms.css +133 -10
- package/public/css/layout.css +79 -26
- package/public/css/modal.css +40 -26
- package/public/css/responsive.css +2 -2
- package/public/css/sidebar.css +456 -20
- package/public/css/terminals.css +182 -0
- package/public/css/tokens.css +28 -12
- package/public/css/wco.css +47 -19
- package/public/css/widgets.css +1177 -6
- package/public/index.html +39 -4
- package/public/js/api.js +194 -37
- package/public/js/components/AdoptModal.js +171 -0
- package/public/js/components/App.js +1 -11
- package/public/js/components/DirectoryPicker.js +203 -0
- package/public/js/components/EntityFormModal.js +105 -0
- package/public/js/components/Modal.js +51 -0
- package/public/js/components/OfflineBanner.js +29 -23
- package/public/js/components/PageTitleBar.js +13 -0
- package/public/js/components/Picker.js +179 -0
- package/public/js/components/Popover.js +55 -0
- package/public/js/components/Sidebar.js +244 -26
- package/public/js/components/TerminalView.js +192 -2
- package/public/js/components/useDragSort.js +67 -0
- package/public/js/dialog.js +10 -2
- package/public/js/icons.js +66 -3
- package/public/js/main.js +54 -3
- package/public/js/pages/AboutPage.js +81 -1
- package/public/js/pages/ConfigurePage.js +452 -159
- package/public/js/pages/LaunchPage.js +328 -76
- package/public/js/pages/SessionsPage.js +91 -41
- package/public/js/state.js +179 -35
- package/public/manifest.webmanifest +2 -2
- package/scripts/install.js +1 -1
- package/server.js +763 -407
- package/lib/favorites.js +0 -51
- package/lib/focus.js +0 -369
- package/lib/labels.js +0 -29
- package/lib/launcher.js +0 -219
- package/lib/sessions.js +0 -272
- package/lib/snapshot.js +0 -141
- package/public/js/actions.js +0 -87
- package/public/js/components/Fab.js +0 -11
- package/public/js/components/FavoritesTable.js +0 -81
- package/public/js/components/Footer.js +0 -12
- package/public/js/components/NewSessionModal.js +0 -142
- package/public/js/components/PageHead.js +0 -33
- package/public/js/components/Pagination.js +0 -27
- package/public/js/components/RecentTable.js +0 -68
- package/public/js/components/SessionsTable.js +0 -71
- package/public/js/components/SnapshotPanel.js +0 -77
- package/public/js/components/TitleCell.js +0 -40
- package/public/js/components/WorkspacesGrid.js +0 -41
- package/public/js/pages/TerminalsPage.js +0 -74
package/public/css/terminals.css
CHANGED
|
@@ -91,6 +91,50 @@
|
|
|
91
91
|
flex: 1;
|
|
92
92
|
min-height: 0;
|
|
93
93
|
width: 100%;
|
|
94
|
+
/* IME composition (Chinese/Japanese pinyin) lives in absolutely-positioned
|
|
95
|
+
.xterm-helper-textarea + .composition-view that grow with the composed
|
|
96
|
+
string. Near the right edge they overflow the viewport and trigger a
|
|
97
|
+
horizontal scrollbar that visually "pushes" the layout. Clip here so
|
|
98
|
+
the overflow is silently absorbed instead of expanding the page.
|
|
99
|
+
Do NOT touch the textarea/composition-view's own text properties —
|
|
100
|
+
xterm relies on their single-line behaviour to keep IME events firing
|
|
101
|
+
correctly (forcing pre-wrap / break-all eats compositionupdate events
|
|
102
|
+
in Chromium and Chinese input stops working entirely). */
|
|
103
|
+
overflow: hidden;
|
|
104
|
+
contain: layout;
|
|
105
|
+
}
|
|
106
|
+
/* While the user is composing (IME), pin the helper textarea to the right
|
|
107
|
+
edge of the terminal so it grows leftward instead of pushing the layout
|
|
108
|
+
rightward. Only touches positioning — NOT width / wrap / max-width, which
|
|
109
|
+
would break Chromium's compositionupdate event flow and stop Chinese
|
|
110
|
+
input from working. The class is toggled by TerminalView.js. */
|
|
111
|
+
.terminal-host.is-composing .xterm-helper-textarea {
|
|
112
|
+
left: auto !important;
|
|
113
|
+
right: 0 !important;
|
|
114
|
+
text-align: right;
|
|
115
|
+
/* xterm un-hides the textarea during composition so the user can see the
|
|
116
|
+
composed string inline. We've moved it to the right edge to stop it
|
|
117
|
+
pushing layout — but that means the composed pinyin would now visibly
|
|
118
|
+
appear on the right. Hide its glyphs (caret + text) so the user only
|
|
119
|
+
sees the OS-native IME candidate popup, which floats independently
|
|
120
|
+
and is unaffected. */
|
|
121
|
+
color: transparent !important;
|
|
122
|
+
caret-color: transparent !important;
|
|
123
|
+
background: transparent !important;
|
|
124
|
+
text-shadow: none !important;
|
|
125
|
+
}
|
|
126
|
+
/* xterm also overlays a .composition-view (a small box at the cursor with
|
|
127
|
+
the in-progress string + a gold caret using THEME.cursor). We can't
|
|
128
|
+
display:none it — Chromium needs it in the layout tree to keep the IME
|
|
129
|
+
compositionupdate events flowing — but we can make it visually invisible
|
|
130
|
+
while leaving it laid out. */
|
|
131
|
+
.terminal-host .composition-view {
|
|
132
|
+
opacity: 0 !important;
|
|
133
|
+
color: transparent !important;
|
|
134
|
+
background: transparent !important;
|
|
135
|
+
border-color: transparent !important;
|
|
136
|
+
box-shadow: none !important;
|
|
137
|
+
pointer-events: none;
|
|
94
138
|
}
|
|
95
139
|
/* Don't override xterm's background — its renderer (canvas/WebGL) assumes
|
|
96
140
|
an opaque surface and ghosts on scroll if we force transparent. The
|
|
@@ -110,3 +154,141 @@
|
|
|
110
154
|
}
|
|
111
155
|
|
|
112
156
|
.terminal-empty-page { width: 100%; }
|
|
157
|
+
|
|
158
|
+
/* === v1.0 session pane === */
|
|
159
|
+
|
|
160
|
+
.sessions-empty {
|
|
161
|
+
display: flex;
|
|
162
|
+
align-items: center;
|
|
163
|
+
justify-content: center;
|
|
164
|
+
min-height: 60vh;
|
|
165
|
+
/* Decorative faint hairline grid, only in this empty state — adds
|
|
166
|
+
editorial atmosphere without affecting any real content view. */
|
|
167
|
+
background-image:
|
|
168
|
+
linear-gradient(to right, rgba(216, 212, 198, 0.5) 1px, transparent 1px),
|
|
169
|
+
linear-gradient(to bottom, rgba(216, 212, 198, 0.5) 1px, transparent 1px);
|
|
170
|
+
background-size: 56px 56px;
|
|
171
|
+
background-position: center;
|
|
172
|
+
position: relative;
|
|
173
|
+
}
|
|
174
|
+
.sessions-empty::before,
|
|
175
|
+
.sessions-empty::after {
|
|
176
|
+
content: "";
|
|
177
|
+
position: absolute;
|
|
178
|
+
inset: 0;
|
|
179
|
+
pointer-events: none;
|
|
180
|
+
}
|
|
181
|
+
.sessions-empty::before {
|
|
182
|
+
background: radial-gradient(ellipse at center, transparent 0%, var(--bg) 75%);
|
|
183
|
+
}
|
|
184
|
+
.sessions-empty-card {
|
|
185
|
+
text-align: center;
|
|
186
|
+
padding: var(--s-12) var(--s-10);
|
|
187
|
+
background: var(--bg-elev);
|
|
188
|
+
border: 1px solid var(--border-soft);
|
|
189
|
+
border-radius: 6px;
|
|
190
|
+
max-width: 440px;
|
|
191
|
+
position: relative;
|
|
192
|
+
z-index: 1;
|
|
193
|
+
box-shadow: var(--shadow-lg);
|
|
194
|
+
}
|
|
195
|
+
.sessions-empty-card::before {
|
|
196
|
+
content: "· EMPTY ·";
|
|
197
|
+
display: block;
|
|
198
|
+
font-family: var(--mono);
|
|
199
|
+
font-size: 10px;
|
|
200
|
+
letter-spacing: 0.28em;
|
|
201
|
+
color: var(--ink-faint);
|
|
202
|
+
margin-bottom: var(--s-4);
|
|
203
|
+
}
|
|
204
|
+
.sessions-empty-card h2 {
|
|
205
|
+
margin: 0 0 var(--s-3);
|
|
206
|
+
font-size: 20px;
|
|
207
|
+
font-weight: 600;
|
|
208
|
+
letter-spacing: -0.015em;
|
|
209
|
+
line-height: 1.2;
|
|
210
|
+
color: var(--ink);
|
|
211
|
+
}
|
|
212
|
+
.sessions-empty-card p {
|
|
213
|
+
margin: 0 0 var(--s-5);
|
|
214
|
+
color: var(--ink-mid);
|
|
215
|
+
font-size: 13.5px;
|
|
216
|
+
line-height: 1.55;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.session-pane {
|
|
220
|
+
display: flex;
|
|
221
|
+
flex-direction: column;
|
|
222
|
+
/* Fill the entire content area edge-to-edge — negative horizontal margin
|
|
223
|
+
cancels .main's horizontal padding so the terminal touches the window
|
|
224
|
+
edges (and the sidebar border) with no surrounding chrome. */
|
|
225
|
+
flex: 1;
|
|
226
|
+
min-height: 0;
|
|
227
|
+
height: 100%;
|
|
228
|
+
margin: 0 calc(-1 * var(--s-4));
|
|
229
|
+
/* Cancel the tab-panel gap above so the terminal sits flush under the
|
|
230
|
+
title bar with no white band. */
|
|
231
|
+
margin-top: calc(-1 * var(--s-4));
|
|
232
|
+
background: var(--bg-elev);
|
|
233
|
+
overflow: hidden;
|
|
234
|
+
}
|
|
235
|
+
.session-pane-head {
|
|
236
|
+
display: flex;
|
|
237
|
+
align-items: center;
|
|
238
|
+
gap: var(--s-3);
|
|
239
|
+
padding: var(--s-3) var(--s-4);
|
|
240
|
+
border-bottom: 1px solid var(--border);
|
|
241
|
+
background: var(--bg);
|
|
242
|
+
flex-wrap: wrap;
|
|
243
|
+
}
|
|
244
|
+
.session-pane-title {
|
|
245
|
+
display: flex;
|
|
246
|
+
align-items: center;
|
|
247
|
+
gap: var(--s-2);
|
|
248
|
+
}
|
|
249
|
+
.session-pane-title h2 {
|
|
250
|
+
margin: 0;
|
|
251
|
+
font-size: 14.5px;
|
|
252
|
+
font-weight: 600;
|
|
253
|
+
}
|
|
254
|
+
.session-pane-meta {
|
|
255
|
+
display: flex;
|
|
256
|
+
gap: var(--s-3);
|
|
257
|
+
align-items: center;
|
|
258
|
+
font-size: 11.5px;
|
|
259
|
+
flex: 1;
|
|
260
|
+
overflow: hidden;
|
|
261
|
+
}
|
|
262
|
+
.session-pane-meta .mono {
|
|
263
|
+
font-family: var(--mono);
|
|
264
|
+
color: var(--ink-mid);
|
|
265
|
+
white-space: nowrap;
|
|
266
|
+
overflow: hidden;
|
|
267
|
+
text-overflow: ellipsis;
|
|
268
|
+
max-width: 50%;
|
|
269
|
+
}
|
|
270
|
+
.session-pane-meta .muted {
|
|
271
|
+
color: var(--ink-muted);
|
|
272
|
+
}
|
|
273
|
+
.session-pane-actions {
|
|
274
|
+
display: flex;
|
|
275
|
+
gap: var(--s-2);
|
|
276
|
+
flex-shrink: 0;
|
|
277
|
+
}
|
|
278
|
+
.session-pane-body {
|
|
279
|
+
flex: 1;
|
|
280
|
+
min-height: 0;
|
|
281
|
+
background: #1a1815;
|
|
282
|
+
}
|
|
283
|
+
.session-pane-body .terminal-host {
|
|
284
|
+
height: 100%;
|
|
285
|
+
}
|
|
286
|
+
.session-pane-body .terminal-empty {
|
|
287
|
+
background: var(--bg);
|
|
288
|
+
display: flex;
|
|
289
|
+
flex-direction: column;
|
|
290
|
+
align-items: center;
|
|
291
|
+
justify-content: center;
|
|
292
|
+
gap: var(--s-3);
|
|
293
|
+
height: 100%;
|
|
294
|
+
}
|
package/public/css/tokens.css
CHANGED
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
--sidebar-hover: #f0ece0;
|
|
11
11
|
--sidebar-active: #e8e3d5;
|
|
12
12
|
|
|
13
|
+
/* Neutral UI chrome — borders, footer strip, etc. These are NEVER
|
|
14
|
+
re-derived from the accent so dividers stay calm regardless of
|
|
15
|
+
theme choice. */
|
|
16
|
+
--ui-border: #d8d4c6;
|
|
17
|
+
--ui-border-soft: #e6e2d4;
|
|
18
|
+
--ui-bg: #f0ece0;
|
|
19
|
+
|
|
13
20
|
/* Borders & rules */
|
|
14
21
|
--border: #e8e3d5;
|
|
15
22
|
--border-soft: #ece8da;
|
|
@@ -24,10 +31,10 @@
|
|
|
24
31
|
/* Accent — Claude warm copper. Slightly desaturated from raw #c45f3f so
|
|
25
32
|
solid-fill buttons feel calm against the cream surfaces, while still
|
|
26
33
|
reading as the same brand hue in star icons, focus rings, etc. */
|
|
27
|
-
--accent: #
|
|
28
|
-
--accent-deep: #
|
|
29
|
-
--accent-soft: rgba(
|
|
30
|
-
--accent-softer: rgba(
|
|
34
|
+
--accent: #2f6fa3;
|
|
35
|
+
--accent-deep: #25577f;
|
|
36
|
+
--accent-soft: rgba(47, 111, 163, 0.10);
|
|
37
|
+
--accent-softer: rgba(47, 111, 163, 0.04);
|
|
31
38
|
|
|
32
39
|
/* Status */
|
|
33
40
|
--green: #4a8a4a;
|
|
@@ -36,19 +43,21 @@
|
|
|
36
43
|
--blue: #4a73a5;
|
|
37
44
|
|
|
38
45
|
/* Type */
|
|
39
|
-
--body:
|
|
40
|
-
--
|
|
46
|
+
--body: "Geist", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
47
|
+
--display: "Geist", ui-sans-serif, system-ui, sans-serif;
|
|
48
|
+
--mono: "JetBrains Mono", "Cascadia Mono", "Consolas", monospace;
|
|
41
49
|
|
|
42
50
|
/* Scale */
|
|
43
51
|
--s-1: 4px; --s-2: 8px; --s-3: 12px; --s-4: 16px;
|
|
44
52
|
--s-5: 20px; --s-6: 24px; --s-8: 32px; --s-10: 40px;
|
|
45
53
|
--s-12: 48px; --s-16: 64px;
|
|
46
54
|
|
|
47
|
-
/* Radius
|
|
48
|
-
|
|
49
|
-
--r:
|
|
50
|
-
--r
|
|
51
|
-
--r-
|
|
55
|
+
/* Radius — tightened in v1.0 for a more codex-like crisp feel.
|
|
56
|
+
999px stays in code where pills are intentional (status dots etc). */
|
|
57
|
+
--r-sm: 3px;
|
|
58
|
+
--r: 4px;
|
|
59
|
+
--r-md: 5px;
|
|
60
|
+
--r-lg: 6px;
|
|
52
61
|
|
|
53
62
|
/* Shadow — soft, like print on cream */
|
|
54
63
|
--shadow-sm: 0 1px 0 rgba(26, 24, 21, 0.04);
|
|
@@ -56,8 +65,15 @@
|
|
|
56
65
|
0 1px 0 rgba(26, 24, 21, 0.03);
|
|
57
66
|
--shadow-md: 0 4px 12px -2px rgba(26, 24, 21, 0.08),
|
|
58
67
|
0 1px 0 rgba(26, 24, 21, 0.04);
|
|
68
|
+
--shadow-lg: 0 18px 40px -16px rgba(26, 24, 21, 0.18),
|
|
69
|
+
0 4px 12px -4px rgba(26, 24, 21, 0.10);
|
|
70
|
+
|
|
71
|
+
/* Subtle paper grain — applied as a layered background on .app to give
|
|
72
|
+
surfaces the texture of laid paper rather than flat color. SVG noise
|
|
73
|
+
keeps it crisp at any zoom level. */
|
|
74
|
+
--paper-noise: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.10 0 0 0 0 0.09 0 0 0 0 0.07 0 0 0 0.035 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
|
|
59
75
|
|
|
60
76
|
/* Sidebar geometry */
|
|
61
77
|
--sidebar-w: 232px;
|
|
62
|
-
--sidebar-w-collapsed:
|
|
78
|
+
--sidebar-w-collapsed: 44px;
|
|
63
79
|
}
|
package/public/css/wco.css
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
.sidebar-brand,
|
|
15
|
+
.sidebar-top,
|
|
16
|
+
.page-title-bar,
|
|
15
17
|
.page-head,
|
|
16
18
|
.page-head-inner,
|
|
17
19
|
.page-title,
|
|
@@ -27,17 +29,16 @@ button, a, input, select, textarea, label,
|
|
|
27
29
|
.action, .server-status,
|
|
28
30
|
.star-btn, .rename-btn, .card-fold, .modal-close,
|
|
29
31
|
.chip, .radio, .fab,
|
|
30
|
-
.ph-stat, .ph-divider
|
|
32
|
+
.ph-stat, .ph-divider,
|
|
33
|
+
.page-title-bar-actions,
|
|
34
|
+
.session-title-action {
|
|
31
35
|
-webkit-app-region: no-drag;
|
|
32
36
|
app-region: no-drag;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
/* `user-select: none` on the drag-target text is needed so clicking the
|
|
36
|
-
page title doesn't start a text selection instead of a window drag. But
|
|
37
|
-
we only want this in PWA-like contexts — in a regular browser tab the
|
|
38
|
-
user should still be able to select the title text. Runtime JS adds
|
|
39
|
-
`body.is-app` when not in display-mode:browser; see main.js. */
|
|
40
39
|
body.is-app .sidebar-brand,
|
|
40
|
+
body.is-app .sidebar-top,
|
|
41
|
+
body.is-app .page-title-bar,
|
|
41
42
|
body.is-app .page-head,
|
|
42
43
|
body.is-app .page-head-inner,
|
|
43
44
|
body.is-app .page-title,
|
|
@@ -46,25 +47,52 @@ body.is-app .page-subtitle {
|
|
|
46
47
|
-webkit-user-select: none;
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
/* In an app window,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
/* In an app/PWA window, the OS title bar is hidden and only floating
|
|
51
|
+
close/max/min controls remain in the top-right. The 40px top band of
|
|
52
|
+
ccsm (sidebar-top + page-title-bar) IS that title bar — it's already
|
|
53
|
+
tall enough, sits at y=0 with no extra padding, and gets a drag region
|
|
54
|
+
so the user can grab anywhere along it to move the window. */
|
|
54
55
|
body.is-app .sidebar { padding-top: 0; }
|
|
55
56
|
body.is-app .main { padding-top: 0; }
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
|
|
58
|
+
/* Reserve room on the right of page-title-bar so its action buttons don't
|
|
59
|
+
slide under the floating OS controls. 150px covers Windows controls
|
|
60
|
+
(~46px each × 3) with breathing room; macOS traffic lights are on the
|
|
61
|
+
left so this padding is harmless there. WCO override below uses the
|
|
62
|
+
precise env() value when available. */
|
|
63
|
+
body.is-app .page-title-bar {
|
|
64
|
+
padding-right: calc(var(--s-4) + 150px);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
body.is-app .page-title,
|
|
68
|
+
body.is-app .page-subtitle {
|
|
69
|
+
display: none;
|
|
58
70
|
}
|
|
59
71
|
body.is-app .page-head {
|
|
60
|
-
padding-
|
|
72
|
+
padding-bottom: 0;
|
|
73
|
+
border-bottom: 0;
|
|
74
|
+
align-items: center;
|
|
75
|
+
min-height: 28px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* PWA / WCO / --app= mode: shrink the top band to 32px so its mid-line
|
|
79
|
+
matches the OS-floated close/max/min icons (which sit in a fixed ~32px
|
|
80
|
+
bar at y=0 and can't be moved). Outside app mode we keep the roomier
|
|
81
|
+
40px band — see sidebar.css / layout.css. */
|
|
82
|
+
body.is-app .page-title-bar,
|
|
83
|
+
body.is-app .sidebar-top {
|
|
84
|
+
height: 32px;
|
|
85
|
+
min-height: 32px;
|
|
86
|
+
}
|
|
87
|
+
body.is-app .sidebar-brand,
|
|
88
|
+
body.is-app .sidebar-brand-button,
|
|
89
|
+
body.is-app .collapse-toggle {
|
|
90
|
+
height: 32px;
|
|
91
|
+
min-height: 32px;
|
|
61
92
|
}
|
|
62
93
|
|
|
63
|
-
/* WCO-only · the OS title bar is fully gone, so right-pad the page-head
|
|
64
|
-
so the meta cluster doesn't slide under the floating close/max/min
|
|
65
|
-
controls. `.main`'s own 32px top padding already clears their height. */
|
|
66
94
|
@media (display-mode: window-controls-overlay) {
|
|
67
|
-
.page-
|
|
68
|
-
padding-right: calc(var(--s-
|
|
95
|
+
body.is-app .page-title-bar {
|
|
96
|
+
padding-right: calc(var(--s-4) + 100vw - env(titlebar-area-width, 100vw));
|
|
69
97
|
}
|
|
70
98
|
}
|