@bakapiano/ccsm 0.4.0 → 0.5.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 +58 -3
- package/lib/favorites.js +73 -0
- package/lib/sessions.js +48 -8
- package/package.json +1 -1
- package/public/app.js +567 -276
- package/public/index.html +373 -163
- package/public/styles.css +1193 -125
- package/server.js +59 -9
package/public/index.html
CHANGED
|
@@ -3,181 +3,391 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
-
<title>ccsm
|
|
6
|
+
<title>ccsm</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
9
|
+
<link
|
|
10
|
+
rel="stylesheet"
|
|
11
|
+
href="https://fonts.googleapis.com/css2?family=Geist:wght@300..700&family=JetBrains+Mono:wght@400..600&display=swap"
|
|
12
|
+
/>
|
|
7
13
|
<link rel="stylesheet" href="/styles.css" />
|
|
8
14
|
</head>
|
|
9
15
|
<body>
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
<button id="finderBtn" class="btn btn-accent" title="Open a new Claude Code session pointed at the session-manager data folder">
|
|
23
|
-
ask claude to find a session
|
|
24
|
-
</button>
|
|
25
|
-
</div>
|
|
26
|
-
</header>
|
|
27
|
-
|
|
28
|
-
<main>
|
|
29
|
-
<section class="panel">
|
|
30
|
-
<header class="panel-header">
|
|
31
|
-
<h2>live sessions</h2>
|
|
32
|
-
<span id="sessionsMeta" class="muted"></span>
|
|
33
|
-
</header>
|
|
34
|
-
<div class="table-wrap">
|
|
35
|
-
<table id="sessionsTable" class="data-table">
|
|
36
|
-
<thead>
|
|
37
|
-
<tr>
|
|
38
|
-
<th></th>
|
|
39
|
-
<th>title</th>
|
|
40
|
-
<th>cwd</th>
|
|
41
|
-
<th>updated</th>
|
|
42
|
-
<th>started</th>
|
|
43
|
-
<th>pid</th>
|
|
44
|
-
<th></th>
|
|
45
|
-
</tr>
|
|
46
|
-
</thead>
|
|
47
|
-
<tbody></tbody>
|
|
48
|
-
</table>
|
|
16
|
+
<div class="app">
|
|
17
|
+
<!-- ─────────── Sidebar ─────────── -->
|
|
18
|
+
<aside class="sidebar" id="sidebar" data-collapsed="false">
|
|
19
|
+
<div class="sidebar-brand">
|
|
20
|
+
<span class="brand-mark" aria-hidden="true">
|
|
21
|
+
<svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
22
|
+
<path d="M3 6h2l1 12h12l1-12h2"/>
|
|
23
|
+
<path d="M9 10v4"/>
|
|
24
|
+
<path d="M15 10v4"/>
|
|
25
|
+
</svg>
|
|
26
|
+
</span>
|
|
27
|
+
<span class="brand-name">ccsm<span class="brand-dot">.</span></span>
|
|
49
28
|
</div>
|
|
50
|
-
</section>
|
|
51
29
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
30
|
+
<nav class="sidebar-nav" role="tablist" aria-label="Sections">
|
|
31
|
+
<button class="nav-item" data-tab="sessions" role="tab" aria-selected="true">
|
|
32
|
+
<span class="nav-icon" aria-hidden="true">
|
|
33
|
+
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
|
34
|
+
<line x1="3" y1="6" x2="21" y2="6"/>
|
|
35
|
+
<line x1="3" y1="12" x2="21" y2="12"/>
|
|
36
|
+
<line x1="3" y1="18" x2="14" y2="18"/>
|
|
37
|
+
</svg>
|
|
38
|
+
</span>
|
|
39
|
+
<span class="nav-label">Sessions</span>
|
|
40
|
+
<span class="nav-badge" id="navCount-sessions">0</span>
|
|
41
|
+
</button>
|
|
42
|
+
<button class="nav-item" data-tab="launch" role="tab" aria-selected="false">
|
|
43
|
+
<span class="nav-icon" aria-hidden="true">
|
|
44
|
+
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
|
45
|
+
<path d="M7 17L17 7"/>
|
|
46
|
+
<path d="M9 7h8v8"/>
|
|
47
|
+
</svg>
|
|
48
|
+
</span>
|
|
49
|
+
<span class="nav-label">Launch</span>
|
|
50
|
+
</button>
|
|
51
|
+
<button class="nav-item" data-tab="configure" role="tab" aria-selected="false">
|
|
52
|
+
<span class="nav-icon" aria-hidden="true">
|
|
53
|
+
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
|
54
|
+
<circle cx="12" cy="12" r="3"/>
|
|
55
|
+
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33h0a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51h0a1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82v0a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
|
|
56
|
+
</svg>
|
|
57
|
+
</span>
|
|
58
|
+
<span class="nav-label">Configure</span>
|
|
59
|
+
</button>
|
|
60
|
+
</nav>
|
|
61
|
+
|
|
62
|
+
<div class="sidebar-divider"></div>
|
|
63
|
+
|
|
64
|
+
<div class="sidebar-utility">
|
|
65
|
+
<button class="util-item" id="refreshBtn" title="refresh">
|
|
66
|
+
<span class="nav-icon" aria-hidden="true">
|
|
67
|
+
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
|
68
|
+
<polyline points="23 4 23 10 17 10"/>
|
|
69
|
+
<polyline points="1 20 1 14 7 14"/>
|
|
70
|
+
<path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/>
|
|
71
|
+
</svg>
|
|
72
|
+
</span>
|
|
73
|
+
<span class="nav-label">Refresh</span>
|
|
74
|
+
</button>
|
|
75
|
+
<button class="util-item util-accent" id="finderBtn" title="open a Claude session pointed at ccsm data">
|
|
76
|
+
<span class="nav-icon" aria-hidden="true">
|
|
77
|
+
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
|
78
|
+
<circle cx="11" cy="11" r="7"/>
|
|
79
|
+
<line x1="21" y1="21" x2="16.65" y2="16.65"/>
|
|
80
|
+
</svg>
|
|
81
|
+
</span>
|
|
82
|
+
<span class="nav-label">Ask Claude</span>
|
|
83
|
+
</button>
|
|
71
84
|
</div>
|
|
72
|
-
</section>
|
|
73
85
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
<button id="snapshotSaveBtn" class="btn">save snapshot now</button>
|
|
81
|
-
<button id="snapshotRestoreBtn" class="btn btn-primary">restore latest snapshot</button>
|
|
82
|
-
<select id="historySelect" class="select" title="restore a historical snapshot">
|
|
83
|
-
<option value="">history…</option>
|
|
84
|
-
</select>
|
|
85
|
-
<button id="historyRestoreBtn" class="btn">restore selected</button>
|
|
86
|
+
<div class="sidebar-foot">
|
|
87
|
+
<button class="collapse-toggle" id="collapseBtn" aria-label="collapse sidebar">
|
|
88
|
+
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
|
89
|
+
<polyline points="15 18 9 12 15 6"/>
|
|
90
|
+
</svg>
|
|
91
|
+
</button>
|
|
86
92
|
</div>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<h2>new session</h2>
|
|
96
|
-
<span class="muted">picks an unused workspace under workDir, clones missing repos, opens a fresh wt window with <code>claude</code></span>
|
|
97
|
-
</header>
|
|
98
|
-
<div class="panel-body">
|
|
99
|
-
<div class="row gap" id="repoPicker"></div>
|
|
100
|
-
<div class="row gap" style="margin-top: 8px;">
|
|
101
|
-
<label for="workspaceSelect">workspace:</label>
|
|
102
|
-
<select id="workspaceSelect" class="select">
|
|
103
|
-
<option value="">(auto — find or create unused)</option>
|
|
104
|
-
</select>
|
|
105
|
-
<button id="newSessionBtn" class="btn btn-primary">launch new session</button>
|
|
93
|
+
</aside>
|
|
94
|
+
|
|
95
|
+
<!-- ─────────── Main ─────────── -->
|
|
96
|
+
<main class="main">
|
|
97
|
+
<header class="page-head">
|
|
98
|
+
<div class="page-head-inner">
|
|
99
|
+
<h1 class="page-title" id="pageTitle">Sessions</h1>
|
|
100
|
+
<p class="page-subtitle" id="pageSubtitle">Live and recently-closed Claude Code sessions on this machine.</p>
|
|
106
101
|
</div>
|
|
107
|
-
<div
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
</details>
|
|
114
|
-
</section>
|
|
115
|
-
|
|
116
|
-
<section class="panel">
|
|
117
|
-
<header class="panel-header"><h2>config</h2></header>
|
|
118
|
-
<div class="panel-body grid-2">
|
|
119
|
-
<label>port (restart server to apply)
|
|
120
|
-
<input id="cfgPort" type="number" />
|
|
121
|
-
</label>
|
|
122
|
-
<label>work dir
|
|
123
|
-
<input id="cfgWorkDir" type="text" />
|
|
124
|
-
</label>
|
|
125
|
-
<label>snapshot interval (ms)
|
|
126
|
-
<input id="cfgInterval" type="number" min="5000" />
|
|
127
|
-
</label>
|
|
128
|
-
<label>history kept
|
|
129
|
-
<input id="cfgKeep" type="number" min="1" />
|
|
130
|
-
</label>
|
|
131
|
-
<label>claude command
|
|
132
|
-
<input id="cfgClaudeCommand" type="text" placeholder="claude" />
|
|
133
|
-
</label>
|
|
134
|
-
<label>terminal
|
|
135
|
-
<select id="cfgTerminal" class="select"></select>
|
|
136
|
-
</label>
|
|
137
|
-
<label>command shell (for wt; lets PowerShell aliases / functions resolve)
|
|
138
|
-
<select id="cfgCommandShell" class="select">
|
|
139
|
-
<option value="pwsh">pwsh (PowerShell 7)</option>
|
|
140
|
-
<option value="powershell">powershell (Windows PowerShell 5.1)</option>
|
|
141
|
-
<option value="none">none — run command directly via wt</option>
|
|
142
|
-
</select>
|
|
143
|
-
</label>
|
|
144
|
-
<label class="full" style="flex-direction: row; align-items: center; gap: 8px;">
|
|
145
|
-
<input id="cfgAutoFocus" type="checkbox" />
|
|
146
|
-
<span style="color: var(--text);">auto-focus newly launched window</span>
|
|
147
|
-
</label>
|
|
148
|
-
<label>browser open mode (on server start)
|
|
149
|
-
<select id="cfgBrowserMode" class="select">
|
|
150
|
-
<option value="app">app — Edge/Chrome chromeless window</option>
|
|
151
|
-
<option value="tab">tab — default browser, normal tab</option>
|
|
152
|
-
<option value="none">off — don't open anything</option>
|
|
153
|
-
</select>
|
|
154
|
-
</label>
|
|
155
|
-
<label class="full">finder prompt
|
|
156
|
-
<textarea id="cfgFinderPrompt" rows="3"></textarea>
|
|
157
|
-
</label>
|
|
158
|
-
<div class="full">
|
|
159
|
-
<div class="row" style="justify-content: space-between; align-items: center;">
|
|
160
|
-
<strong>repos</strong>
|
|
161
|
-
<button id="addRepoBtn" class="btn small">+ add repo</button>
|
|
162
|
-
</div>
|
|
163
|
-
<table id="reposTable" class="data-table">
|
|
164
|
-
<thead>
|
|
165
|
-
<tr>
|
|
166
|
-
<th>name</th><th>url</th><th>default selected</th><th></th>
|
|
167
|
-
</tr>
|
|
168
|
-
</thead>
|
|
169
|
-
<tbody></tbody>
|
|
170
|
-
</table>
|
|
102
|
+
<div class="page-head-meta">
|
|
103
|
+
<span class="ph-stat"><span class="ph-key">Port</span> <span class="ph-val" id="hdPort">—</span></span>
|
|
104
|
+
<span class="ph-divider">·</span>
|
|
105
|
+
<span class="ph-stat"><span class="ph-key">Terminal</span> <span class="ph-val" id="hdTerminal">—</span></span>
|
|
106
|
+
<span class="ph-divider">·</span>
|
|
107
|
+
<span class="ph-stat"><span class="ph-key">Now</span> <span class="ph-val" id="hdTime">—</span></span>
|
|
171
108
|
</div>
|
|
109
|
+
</header>
|
|
110
|
+
|
|
111
|
+
<div class="content">
|
|
112
|
+
<!-- ─── Sessions tab ─── -->
|
|
113
|
+
<section class="tab-panel" data-panel="sessions" data-active>
|
|
114
|
+
<div class="page-actions">
|
|
115
|
+
<span class="page-actions-hint">Looking through your past conversations?</span>
|
|
116
|
+
<button class="action primary" id="finderInlineBtn" title="open a Claude session with context on the ccsm data dir">
|
|
117
|
+
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
118
|
+
<circle cx="11" cy="11" r="7"/>
|
|
119
|
+
<line x1="21" y1="21" x2="16.65" y2="16.65"/>
|
|
120
|
+
</svg>
|
|
121
|
+
Ask Claude to find a session
|
|
122
|
+
</button>
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<article class="card" id="favoritesCard">
|
|
126
|
+
<header class="card-head">
|
|
127
|
+
<div class="card-titles">
|
|
128
|
+
<h2 class="card-title">
|
|
129
|
+
<svg class="title-icon" viewBox="0 0 24 24" width="15" height="15" fill="currentColor" stroke="none" aria-hidden="true">
|
|
130
|
+
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>
|
|
131
|
+
</svg>
|
|
132
|
+
Favorites
|
|
133
|
+
</h2>
|
|
134
|
+
<p class="card-meta" id="favoritesMeta">click ☆ on any row to pin sessions here</p>
|
|
135
|
+
</div>
|
|
136
|
+
</header>
|
|
137
|
+
<div class="card-body card-body-flush">
|
|
138
|
+
<div class="table-scroll">
|
|
139
|
+
<table class="data" id="favoritesTable">
|
|
140
|
+
<thead>
|
|
141
|
+
<tr>
|
|
142
|
+
<th>Title</th>
|
|
143
|
+
<th>Working directory</th>
|
|
144
|
+
<th>Branch</th>
|
|
145
|
+
<th class="num">Pinned</th>
|
|
146
|
+
<th class="col-actions"></th>
|
|
147
|
+
</tr>
|
|
148
|
+
</thead>
|
|
149
|
+
<tbody></tbody>
|
|
150
|
+
</table>
|
|
151
|
+
</div>
|
|
152
|
+
<div class="empty" id="favoritesEmpty">No favorites yet. Star a session row to pin it here.</div>
|
|
153
|
+
</div>
|
|
154
|
+
</article>
|
|
155
|
+
|
|
156
|
+
<article class="card">
|
|
157
|
+
<header class="card-head">
|
|
158
|
+
<div class="card-titles">
|
|
159
|
+
<h2 class="card-title">Live sessions</h2>
|
|
160
|
+
<p class="card-meta" id="sessionsMeta">awaiting…</p>
|
|
161
|
+
</div>
|
|
162
|
+
</header>
|
|
163
|
+
<div class="card-body card-body-flush">
|
|
164
|
+
<div class="table-scroll">
|
|
165
|
+
<table class="data" id="sessionsTable">
|
|
166
|
+
<thead>
|
|
167
|
+
<tr>
|
|
168
|
+
<th class="col-mark"></th>
|
|
169
|
+
<th>Title</th>
|
|
170
|
+
<th>Working directory</th>
|
|
171
|
+
<th class="num">Updated</th>
|
|
172
|
+
<th class="num">Started</th>
|
|
173
|
+
<th class="num">PID</th>
|
|
174
|
+
<th class="col-actions"></th>
|
|
175
|
+
</tr>
|
|
176
|
+
</thead>
|
|
177
|
+
<tbody></tbody>
|
|
178
|
+
</table>
|
|
179
|
+
</div>
|
|
180
|
+
<div class="empty" id="sessionsEmpty" hidden>No live sessions detected.</div>
|
|
181
|
+
</div>
|
|
182
|
+
</article>
|
|
183
|
+
|
|
184
|
+
<article class="card">
|
|
185
|
+
<header class="card-head">
|
|
186
|
+
<div class="card-titles">
|
|
187
|
+
<h2 class="card-title">Recently closed</h2>
|
|
188
|
+
<p class="card-meta" id="recentMeta">…</p>
|
|
189
|
+
</div>
|
|
190
|
+
</header>
|
|
191
|
+
<div class="card-body card-body-flush">
|
|
192
|
+
<div class="table-scroll">
|
|
193
|
+
<table class="data" id="recentTable">
|
|
194
|
+
<thead>
|
|
195
|
+
<tr>
|
|
196
|
+
<th>Title</th>
|
|
197
|
+
<th>Working directory</th>
|
|
198
|
+
<th>Branch</th>
|
|
199
|
+
<th class="num">Last activity</th>
|
|
200
|
+
<th class="num">Started</th>
|
|
201
|
+
<th class="col-actions"></th>
|
|
202
|
+
</tr>
|
|
203
|
+
</thead>
|
|
204
|
+
<tbody></tbody>
|
|
205
|
+
</table>
|
|
206
|
+
</div>
|
|
207
|
+
<div class="empty" id="recentEmpty" hidden>Nothing in <code>~/.claude/projects/</code>.</div>
|
|
208
|
+
<footer class="pagination" id="recentPagination" hidden>
|
|
209
|
+
<button class="action subtle small" id="recentPrevBtn" disabled>← Prev</button>
|
|
210
|
+
<span class="pagination-info">Page <strong id="recentPageNum">1</strong> of <strong id="recentPageTotal">1</strong> · <span id="recentTotal">0</span> total</span>
|
|
211
|
+
<button class="action subtle small" id="recentNextBtn" disabled>Next →</button>
|
|
212
|
+
<select id="recentPageSize" class="input" style="max-width: 100px;">
|
|
213
|
+
<option value="10">10 / page</option>
|
|
214
|
+
<option value="15" selected>15 / page</option>
|
|
215
|
+
<option value="25">25 / page</option>
|
|
216
|
+
<option value="50">50 / page</option>
|
|
217
|
+
</select>
|
|
218
|
+
</footer>
|
|
219
|
+
</div>
|
|
220
|
+
</article>
|
|
221
|
+
</section>
|
|
222
|
+
|
|
223
|
+
<!-- ─── Launch tab ─── -->
|
|
224
|
+
<section class="tab-panel" data-panel="launch">
|
|
225
|
+
<article class="card">
|
|
226
|
+
<header class="card-head">
|
|
227
|
+
<div class="card-titles">
|
|
228
|
+
<h2 class="card-title">New session</h2>
|
|
229
|
+
<p class="card-meta">Picks an unused workspace, clones missing repos, opens <code>claude</code> in a fresh terminal.</p>
|
|
230
|
+
</div>
|
|
231
|
+
</header>
|
|
232
|
+
<div class="card-body">
|
|
233
|
+
<div class="form-row">
|
|
234
|
+
<span class="form-label">Repos</span>
|
|
235
|
+
<div class="chip-row" id="repoPicker">
|
|
236
|
+
<span class="muted-text">no repos configured · add some in <strong>Configure</strong></span>
|
|
237
|
+
</div>
|
|
238
|
+
</div>
|
|
239
|
+
<div class="form-row">
|
|
240
|
+
<label class="form-label" for="workspaceSelect">Workspace</label>
|
|
241
|
+
<select id="workspaceSelect" class="input narrow">
|
|
242
|
+
<option value="">auto — find or create unused</option>
|
|
243
|
+
</select>
|
|
244
|
+
<button class="action primary" id="newSessionBtn">Launch new session</button>
|
|
245
|
+
</div>
|
|
246
|
+
<div id="newSessionProgress" class="progress-list"></div>
|
|
247
|
+
<div class="post-result" id="newSessionResult"></div>
|
|
248
|
+
</div>
|
|
249
|
+
</article>
|
|
250
|
+
|
|
251
|
+
<article class="card">
|
|
252
|
+
<header class="card-head">
|
|
253
|
+
<div class="card-titles">
|
|
254
|
+
<h2 class="card-title">Snapshot & restore</h2>
|
|
255
|
+
<p class="card-meta" id="snapshotMeta">…</p>
|
|
256
|
+
</div>
|
|
257
|
+
</header>
|
|
258
|
+
<div class="card-body">
|
|
259
|
+
<div class="row gap-row">
|
|
260
|
+
<button class="action" id="snapshotSaveBtn">Save snapshot now</button>
|
|
261
|
+
<button class="action primary" id="snapshotRestoreBtn">Restore latest</button>
|
|
262
|
+
<span class="divider-dot">·</span>
|
|
263
|
+
<select id="historySelect" class="input narrow">
|
|
264
|
+
<option value="">history…</option>
|
|
265
|
+
</select>
|
|
266
|
+
<button class="action" id="historyRestoreBtn">Restore selected</button>
|
|
267
|
+
</div>
|
|
268
|
+
<details class="snapshot-detail">
|
|
269
|
+
<summary>View snapshot contents</summary>
|
|
270
|
+
<pre id="snapshotPreview" class="preview"></pre>
|
|
271
|
+
</details>
|
|
272
|
+
</div>
|
|
273
|
+
</article>
|
|
274
|
+
|
|
275
|
+
<article class="card">
|
|
276
|
+
<header class="card-head">
|
|
277
|
+
<div class="card-titles">
|
|
278
|
+
<h2 class="card-title">Workspaces on disk</h2>
|
|
279
|
+
<p class="card-meta">Under <code id="workDirDisplay">…</code></p>
|
|
280
|
+
</div>
|
|
281
|
+
</header>
|
|
282
|
+
<div class="card-body">
|
|
283
|
+
<div id="workspaceList" class="workspace-grid"></div>
|
|
284
|
+
</div>
|
|
285
|
+
</article>
|
|
286
|
+
</section>
|
|
287
|
+
|
|
288
|
+
<!-- ─── Configure tab ─── -->
|
|
289
|
+
<section class="tab-panel" data-panel="configure">
|
|
290
|
+
<article class="card">
|
|
291
|
+
<header class="card-head">
|
|
292
|
+
<div class="card-titles">
|
|
293
|
+
<h2 class="card-title">Settings</h2>
|
|
294
|
+
<p class="card-meta">Persisted to <code>~/.ccsm/config.json</code></p>
|
|
295
|
+
</div>
|
|
296
|
+
</header>
|
|
297
|
+
<div class="card-body">
|
|
298
|
+
<div class="config-grid">
|
|
299
|
+
<label class="field">
|
|
300
|
+
<span class="label">Port</span>
|
|
301
|
+
<input id="cfgPort" type="number" />
|
|
302
|
+
<span class="hint">restart server to apply</span>
|
|
303
|
+
</label>
|
|
304
|
+
<label class="field">
|
|
305
|
+
<span class="label">Work directory</span>
|
|
306
|
+
<input id="cfgWorkDir" type="text" />
|
|
307
|
+
</label>
|
|
308
|
+
<label class="field">
|
|
309
|
+
<span class="label">Snapshot interval (ms)</span>
|
|
310
|
+
<input id="cfgInterval" type="number" min="5000" />
|
|
311
|
+
</label>
|
|
312
|
+
<label class="field">
|
|
313
|
+
<span class="label">History kept</span>
|
|
314
|
+
<input id="cfgKeep" type="number" min="1" />
|
|
315
|
+
</label>
|
|
316
|
+
<label class="field">
|
|
317
|
+
<span class="label">Claude command</span>
|
|
318
|
+
<input id="cfgClaudeCommand" type="text" placeholder="claude" />
|
|
319
|
+
<span class="hint">alias / function / exe name</span>
|
|
320
|
+
</label>
|
|
321
|
+
<label class="field">
|
|
322
|
+
<span class="label">Terminal</span>
|
|
323
|
+
<select id="cfgTerminal" class="input"></select>
|
|
324
|
+
</label>
|
|
325
|
+
<label class="field">
|
|
326
|
+
<span class="label">Command shell <span class="hint inline">(wt only)</span></span>
|
|
327
|
+
<select id="cfgCommandShell" class="input">
|
|
328
|
+
<option value="pwsh">pwsh · PowerShell 7</option>
|
|
329
|
+
<option value="powershell">powershell · Windows PowerShell 5.1</option>
|
|
330
|
+
<option value="none">none · run command directly</option>
|
|
331
|
+
</select>
|
|
332
|
+
</label>
|
|
333
|
+
<label class="field">
|
|
334
|
+
<span class="label">Browser open mode</span>
|
|
335
|
+
<select id="cfgBrowserMode" class="input">
|
|
336
|
+
<option value="app">app · Edge/Chrome chromeless</option>
|
|
337
|
+
<option value="tab">tab · default browser</option>
|
|
338
|
+
<option value="none">off · don't open</option>
|
|
339
|
+
</select>
|
|
340
|
+
</label>
|
|
341
|
+
<label class="field toggle">
|
|
342
|
+
<input id="cfgAutoFocus" type="checkbox" />
|
|
343
|
+
<span class="toggle-text">
|
|
344
|
+
<span class="label">Auto-focus on launch</span>
|
|
345
|
+
<span class="hint">raise newly-launched terminal window</span>
|
|
346
|
+
</span>
|
|
347
|
+
</label>
|
|
348
|
+
<label class="field full">
|
|
349
|
+
<span class="label">Finder prompt</span>
|
|
350
|
+
<textarea id="cfgFinderPrompt" rows="3"></textarea>
|
|
351
|
+
<span class="hint">passed as initial prompt to the finder session</span>
|
|
352
|
+
</label>
|
|
353
|
+
|
|
354
|
+
<div class="field full">
|
|
355
|
+
<div class="repos-head">
|
|
356
|
+
<span class="label">Repositories</span>
|
|
357
|
+
<button class="action small" id="addRepoBtn">+ Add repo</button>
|
|
358
|
+
</div>
|
|
359
|
+
<table class="data repos-table" id="reposTable">
|
|
360
|
+
<thead>
|
|
361
|
+
<tr>
|
|
362
|
+
<th>Name</th>
|
|
363
|
+
<th>URL</th>
|
|
364
|
+
<th class="num">Default</th>
|
|
365
|
+
<th class="col-actions"></th>
|
|
366
|
+
</tr>
|
|
367
|
+
</thead>
|
|
368
|
+
<tbody></tbody>
|
|
369
|
+
</table>
|
|
370
|
+
</div>
|
|
371
|
+
|
|
372
|
+
<div class="form-actions full">
|
|
373
|
+
<button class="action primary" id="saveConfigBtn">Save configuration</button>
|
|
374
|
+
<span class="muted-text" id="configSavedAt"></span>
|
|
375
|
+
</div>
|
|
376
|
+
</div>
|
|
377
|
+
</div>
|
|
378
|
+
</article>
|
|
379
|
+
</section>
|
|
172
380
|
</div>
|
|
173
|
-
<div class="panel-body">
|
|
174
|
-
<button id="saveConfigBtn" class="btn btn-primary">save config</button>
|
|
175
|
-
<span id="configSavedAt" class="muted small"></span>
|
|
176
|
-
</div>
|
|
177
|
-
</section>
|
|
178
|
-
</main>
|
|
179
381
|
|
|
180
|
-
|
|
382
|
+
<footer class="footer-status">
|
|
383
|
+
<span class="fs-key">Data</span> <span class="fs-val" id="footData">—</span>
|
|
384
|
+
<span class="fs-divider">·</span>
|
|
385
|
+
<span class="fs-key">Workspaces</span> <span class="fs-val" id="footWorkDir">—</span>
|
|
386
|
+
</footer>
|
|
387
|
+
</main>
|
|
388
|
+
</div>
|
|
389
|
+
|
|
390
|
+
<div id="toast" class="toast" role="status" aria-live="polite"></div>
|
|
181
391
|
|
|
182
392
|
<script src="/app.js" defer></script>
|
|
183
393
|
</body>
|