claude-relay 2.3.0 → 2.4.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 (54) hide show
  1. package/README.md +21 -5
  2. package/bin/cli.js +214 -9
  3. package/lib/cli-sessions.js +270 -0
  4. package/lib/config.js +3 -2
  5. package/lib/daemon.js +45 -1
  6. package/lib/pages.js +8 -1
  7. package/lib/project.js +121 -12
  8. package/lib/public/app.js +411 -87
  9. package/lib/public/css/base.css +41 -7
  10. package/lib/public/css/diff.css +6 -6
  11. package/lib/public/css/filebrowser.css +62 -52
  12. package/lib/public/css/highlight.css +144 -0
  13. package/lib/public/css/input.css +11 -9
  14. package/lib/public/css/menus.css +82 -23
  15. package/lib/public/css/messages.css +183 -35
  16. package/lib/public/css/overlays.css +166 -50
  17. package/lib/public/css/rewind.css +17 -17
  18. package/lib/public/css/sidebar.css +210 -137
  19. package/lib/public/index.html +75 -42
  20. package/lib/public/modules/filebrowser.js +2 -1
  21. package/lib/public/modules/markdown.js +10 -10
  22. package/lib/public/modules/notifications.js +38 -1
  23. package/lib/public/modules/sidebar.js +109 -31
  24. package/lib/public/modules/terminal.js +84 -23
  25. package/lib/public/modules/theme.js +622 -0
  26. package/lib/public/modules/tools.js +247 -4
  27. package/lib/public/modules/utils.js +21 -5
  28. package/lib/public/style.css +1 -0
  29. package/lib/sdk-bridge.js +95 -0
  30. package/lib/server.js +45 -3
  31. package/lib/sessions.js +16 -3
  32. package/lib/themes/ayu-light.json +9 -0
  33. package/lib/themes/catppuccin-latte.json +9 -0
  34. package/lib/themes/catppuccin-mocha.json +9 -0
  35. package/lib/themes/claude-light.json +9 -0
  36. package/lib/themes/claude.json +9 -0
  37. package/lib/themes/dracula.json +9 -0
  38. package/lib/themes/everforest-light.json +9 -0
  39. package/lib/themes/everforest.json +9 -0
  40. package/lib/themes/github-light.json +9 -0
  41. package/lib/themes/gruvbox-dark.json +9 -0
  42. package/lib/themes/gruvbox-light.json +9 -0
  43. package/lib/themes/monokai.json +9 -0
  44. package/lib/themes/nord-light.json +9 -0
  45. package/lib/themes/nord.json +9 -0
  46. package/lib/themes/one-dark.json +9 -0
  47. package/lib/themes/one-light.json +9 -0
  48. package/lib/themes/rose-pine-dawn.json +9 -0
  49. package/lib/themes/rose-pine.json +9 -0
  50. package/lib/themes/solarized-dark.json +9 -0
  51. package/lib/themes/solarized-light.json +9 -0
  52. package/lib/themes/tokyo-night-light.json +9 -0
  53. package/lib/themes/tokyo-night.json +9 -0
  54. package/package.json +2 -1
@@ -49,47 +49,24 @@
49
49
  display: flex;
50
50
  flex-direction: column;
51
51
  padding: 4px 8px;
52
+ flex-shrink: 0;
52
53
  }
53
54
 
54
- /* --- Project Switcher --- */
55
- #project-switcher {
56
- position: relative;
55
+ /* --- Project List --- */
56
+ #project-list-section {
57
57
  padding: 0 4px;
58
- margin-bottom: 12px;
58
+ margin-bottom: 4px;
59
59
  border-bottom: 1px solid var(--border-subtle);
60
60
  }
61
61
 
62
- #project-switcher-btn {
62
+ #project-list-header {
63
63
  display: flex;
64
64
  align-items: center;
65
65
  justify-content: space-between;
66
- width: 100%;
67
- padding: 10px 8px;
68
- border: none;
69
- background: transparent;
70
- color: var(--text);
71
- font-size: 14px;
72
- font-weight: 600;
73
- font-family: inherit;
74
- cursor: pointer;
75
- border-radius: 8px;
76
- transition: background 0.15s, color 0.15s;
66
+ padding: 8px 8px 6px;
77
67
  }
78
68
 
79
- #project-switcher-btn:hover {
80
- background: var(--sidebar-hover);
81
- color: var(--text);
82
- }
83
-
84
- #project-switcher-label {
85
- display: flex;
86
- flex-direction: column;
87
- align-items: flex-start;
88
- min-width: 0;
89
- overflow: hidden;
90
- }
91
-
92
- .ps-title {
69
+ .project-list-title {
93
70
  font-size: 11px;
94
71
  font-weight: 600;
95
72
  color: var(--text-dimmer);
@@ -97,100 +74,61 @@
97
74
  letter-spacing: 0.5px;
98
75
  }
99
76
 
100
- .ps-current {
77
+ #project-list-add {
101
78
  display: flex;
102
79
  align-items: center;
103
- gap: 6px;
80
+ justify-content: center;
81
+ width: 22px;
82
+ height: 22px;
83
+ border: none;
84
+ background: transparent;
85
+ color: var(--text-dimmer);
86
+ cursor: pointer;
87
+ border-radius: 6px;
88
+ transition: background 0.15s, color 0.15s;
104
89
  }
105
90
 
106
- #project-switcher-name {
107
- font-size: 14px;
108
- font-weight: 600;
91
+ #project-list-add:hover {
92
+ background: var(--sidebar-hover);
109
93
  color: var(--text);
110
- overflow: hidden;
111
- text-overflow: ellipsis;
112
- white-space: nowrap;
113
94
  }
114
95
 
115
- .ps-chevron {
96
+ #project-list-add .lucide {
116
97
  width: 14px;
117
98
  height: 14px;
118
- transition: transform 0.2s ease;
119
- flex-shrink: 0;
120
- color: var(--text-dimmer);
121
- }
122
-
123
- #project-switcher.open .ps-chevron {
124
- transform: rotate(180deg);
125
- }
126
-
127
- .ps-count {
128
- font-size: 11px;
129
- font-weight: 700;
130
- background: rgba(218, 119, 86, 0.15);
131
- color: var(--accent);
132
- border-radius: 10px;
133
- padding: 2px 8px;
134
- margin-left: 4px;
135
99
  }
136
100
 
137
- .ps-count:empty {
138
- display: none;
139
- }
140
-
141
- /* --- Project Dropdown --- */
142
- #project-dropdown {
143
- position: absolute;
144
- top: calc(100% + 2px);
145
- left: 4px;
146
- right: 4px;
147
- background: var(--bg-alt);
148
- border: 1px solid var(--border);
149
- border-radius: 10px;
150
- padding: 4px 0;
151
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
152
- z-index: 120;
153
- max-height: 320px;
101
+ #project-list {
102
+ padding: 0 0 6px;
154
103
  overflow-y: auto;
104
+ max-height: 200px;
155
105
  }
156
106
 
157
- #project-dropdown.hidden {
158
- display: none;
159
- }
160
-
161
- .project-dropdown-header {
162
- padding: 8px 12px 6px;
163
- font-size: 11px;
164
- font-weight: 600;
165
- color: var(--text-dimmer);
166
- text-transform: uppercase;
167
- letter-spacing: 0.5px;
168
- }
169
-
170
- .project-dropdown-item {
107
+ .project-list-item {
171
108
  display: flex;
172
109
  align-items: center;
173
110
  gap: 10px;
174
- padding: 10px 12px;
111
+ padding: 7px 8px 7px 10px;
175
112
  cursor: pointer;
176
113
  font-size: 13px;
177
114
  color: var(--text-secondary);
178
115
  text-decoration: none;
179
116
  transition: background 0.15s;
180
117
  border-left: 3px solid transparent;
118
+ border-radius: 0 6px 6px 0;
181
119
  }
182
120
 
183
- .project-dropdown-item:hover {
184
- background: rgba(255, 255, 255, 0.05);
121
+ .project-list-item:hover {
122
+ background: rgba(var(--overlay-rgb), 0.05);
185
123
  }
186
124
 
187
- .project-dropdown-item.current {
188
- background: rgba(218, 119, 86, 0.06);
125
+ .project-list-item.current {
126
+ background: var(--accent-8);
189
127
  border-left-color: var(--accent);
190
128
  color: var(--text);
191
129
  }
192
130
 
193
- .project-dropdown-item.current .pd-name {
131
+ .project-list-item.current .pd-name {
194
132
  font-weight: 600;
195
133
  }
196
134
 
@@ -225,35 +163,22 @@
225
163
  opacity: 0.4;
226
164
  }
227
165
 
228
- .project-dropdown-footer {
229
- border-top: 1px solid var(--border-subtle);
230
- padding: 4px 0;
231
- }
232
-
233
- .project-dropdown-footer button {
234
- display: flex;
235
- align-items: center;
236
- gap: 8px;
237
- width: 100%;
238
- padding: 8px 12px;
239
- font-size: 12px;
240
- font-family: inherit;
241
- color: var(--text-muted);
166
+ .pd-remove {
167
+ display: none;
242
168
  background: none;
243
169
  border: none;
170
+ color: var(--text-muted);
244
171
  cursor: pointer;
245
- transition: background 0.15s, color 0.15s;
246
- }
247
-
248
- .project-dropdown-footer button:hover {
249
- background: rgba(255, 255, 255, 0.05);
250
- color: var(--text-secondary);
172
+ padding: 2px;
173
+ border-radius: 4px;
174
+ flex-shrink: 0;
175
+ line-height: 0;
176
+ transition: color 0.15s, background 0.15s;
251
177
  }
252
178
 
253
- .project-dropdown-footer .lucide {
254
- width: 13px;
255
- height: 13px;
256
- }
179
+ .pd-remove .lucide { width: 14px; height: 14px; }
180
+ .project-list-item:hover .pd-remove { display: block; }
181
+ .pd-remove:hover { color: var(--error); background: rgba(var(--overlay-rgb), 0.06); }
257
182
 
258
183
  /* --- Project Hint (single-project onboarding) --- */
259
184
  #project-hint {
@@ -263,8 +188,8 @@
263
188
  align-items: flex-start;
264
189
  gap: 6px;
265
190
  border-radius: 8px;
266
- background: rgba(218, 119, 86, 0.12);
267
- border: 1px solid rgba(218, 119, 86, 0.2);
191
+ background: var(--accent-12);
192
+ border: 1px solid var(--accent-20);
268
193
  }
269
194
 
270
195
  #project-hint.hidden {
@@ -278,7 +203,7 @@
278
203
  }
279
204
 
280
205
  .project-hint-text code {
281
- background: rgba(218, 119, 86, 0.15);
206
+ background: var(--accent-15);
282
207
  padding: 1px 5px;
283
208
  border-radius: 3px;
284
209
  font-family: "SF Mono", Menlo, Monaco, monospace;
@@ -334,11 +259,36 @@
334
259
  height: 18px;
335
260
  }
336
261
 
262
+ /* --- Sidebar section headers --- */
263
+ .sidebar-section-header {
264
+ padding: 8px 12px 4px;
265
+ }
266
+
267
+ .sidebar-section-title {
268
+ font-size: 11px;
269
+ font-weight: 600;
270
+ color: var(--text-dimmer);
271
+ text-transform: uppercase;
272
+ letter-spacing: 0.5px;
273
+ }
274
+
275
+ /* --- Tools section --- */
276
+ #sidebar-tools {
277
+ flex-shrink: 0;
278
+ border-bottom: 1px solid var(--border-subtle);
279
+ padding-bottom: 4px;
280
+ }
281
+
282
+ /* --- Sessions header (pinned above scroll) --- */
283
+ #sidebar-sessions-header {
284
+ flex-shrink: 0;
285
+ }
286
+
337
287
  .session-list-header {
338
288
  display: flex;
339
289
  align-items: center;
340
- gap: 4px;
341
- padding: 24px 12px 4px 20px;
290
+ justify-content: space-between;
291
+ padding: 8px 8px 4px 12px;
342
292
  font-size: 11px;
343
293
  font-weight: 600;
344
294
  color: var(--text-dimmer);
@@ -346,12 +296,18 @@
346
296
  letter-spacing: 0.5px;
347
297
  }
348
298
 
349
- #search-session-btn {
299
+ .session-list-header-actions {
300
+ display: flex;
301
+ align-items: center;
302
+ gap: 2px;
303
+ }
304
+
305
+ .session-list-header-actions button {
350
306
  display: flex;
351
307
  align-items: center;
352
308
  justify-content: center;
353
- width: 24px;
354
- height: 24px;
309
+ width: 22px;
310
+ height: 22px;
355
311
  border-radius: 6px;
356
312
  border: none;
357
313
  background: transparent;
@@ -361,12 +317,13 @@
361
317
  transition: color 0.15s, background 0.15s;
362
318
  }
363
319
 
364
- #search-session-btn .lucide { width: 14px; height: 14px; }
365
- #search-session-btn:hover { color: var(--text); background: var(--sidebar-hover); }
320
+ .session-list-header-actions button .lucide { width: 14px; height: 14px; }
321
+ .session-list-header-actions button:hover { color: var(--text); background: var(--sidebar-hover); }
366
322
 
367
323
  /* --- Session search --- */
368
324
  #session-search {
369
325
  padding: 0 12px 8px;
326
+ position: relative;
370
327
  }
371
328
 
372
329
  #session-search.hidden {
@@ -375,7 +332,7 @@
375
332
 
376
333
  #session-search-input {
377
334
  width: 100%;
378
- padding: 7px 10px;
335
+ padding: 7px 28px 7px 10px;
379
336
  border-radius: 8px;
380
337
  border: 1px solid var(--border);
381
338
  background: var(--input-bg);
@@ -384,6 +341,7 @@
384
341
  font-family: inherit;
385
342
  outline: none;
386
343
  transition: border-color 0.15s;
344
+ box-sizing: border-box;
387
345
  }
388
346
 
389
347
  #session-search-input:focus {
@@ -394,12 +352,34 @@
394
352
  color: var(--text-dimmer);
395
353
  }
396
354
 
355
+ #session-search-clear {
356
+ position: absolute;
357
+ right: 16px;
358
+ top: calc(50% - 4px);
359
+ transform: translateY(-50%);
360
+ display: flex;
361
+ align-items: center;
362
+ justify-content: center;
363
+ width: 20px;
364
+ height: 20px;
365
+ border: none;
366
+ background: transparent;
367
+ color: var(--text-dimmer);
368
+ cursor: pointer;
369
+ padding: 0;
370
+ border-radius: 4px;
371
+ transition: color 0.15s, background 0.15s;
372
+ }
373
+
374
+ #session-search-clear .lucide { width: 14px; height: 14px; }
375
+ #session-search-clear:hover { color: var(--text); background: var(--sidebar-hover); }
376
+
397
377
  #search-session-btn.active {
398
378
  color: var(--accent);
399
379
  }
400
380
 
401
381
  .session-item.search-match {
402
- background: rgba(218, 119, 86, 0.1);
382
+ background: var(--accent-12);
403
383
  color: var(--text);
404
384
  }
405
385
 
@@ -412,7 +392,7 @@
412
392
  }
413
393
 
414
394
  .session-highlight {
415
- background: rgba(218, 119, 86, 0.3);
395
+ background: var(--accent-30);
416
396
  color: var(--text);
417
397
  border-radius: 2px;
418
398
  padding: 0 1px;
@@ -508,7 +488,7 @@
508
488
 
509
489
  .session-more-btn .lucide { width: 14px; height: 14px; }
510
490
  .session-item:hover .session-more-btn { display: flex; }
511
- .session-more-btn:hover { color: var(--text); background: rgba(255, 255, 255, 0.06); }
491
+ .session-more-btn:hover { color: var(--text); background: rgba(var(--overlay-rgb), 0.06); }
512
492
 
513
493
  /* --- Session context menu --- */
514
494
  .session-ctx-menu {
@@ -521,7 +501,7 @@
521
501
  border-radius: 10px;
522
502
  padding: 4px 0;
523
503
  min-width: 140px;
524
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
504
+ box-shadow: 0 4px 16px rgba(var(--shadow-rgb), 0.4);
525
505
  z-index: 110;
526
506
  }
527
507
 
@@ -541,10 +521,10 @@
541
521
  }
542
522
 
543
523
  .session-ctx-item .lucide { width: 14px; height: 14px; flex-shrink: 0; }
544
- .session-ctx-item:hover { background: rgba(255, 255, 255, 0.05); }
524
+ .session-ctx-item:hover { background: rgba(var(--overlay-rgb), 0.05); }
545
525
 
546
526
  .session-ctx-item.session-ctx-delete { color: var(--error); }
547
- .session-ctx-item.session-ctx-delete:hover { background: rgba(229, 83, 75, 0.08); }
527
+ .session-ctx-item.session-ctx-delete:hover { background: var(--error-8); }
548
528
 
549
529
  /* --- Session inline rename --- */
550
530
  .session-rename-input {
@@ -621,7 +601,7 @@
621
601
  border: 1px solid var(--border);
622
602
  border-radius: 10px;
623
603
  padding: 4px 0;
624
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
604
+ box-shadow: 0 4px 16px rgba(var(--shadow-rgb), 0.4);
625
605
  z-index: 110;
626
606
  }
627
607
 
@@ -644,7 +624,7 @@
644
624
  }
645
625
 
646
626
  .sidebar-menu-item .lucide { width: 14px; height: 14px; flex-shrink: 0; }
647
- .sidebar-menu-item:hover { background: rgba(255, 255, 255, 0.05); }
627
+ .sidebar-menu-item:hover { background: rgba(var(--overlay-rgb), 0.05); }
648
628
 
649
629
  .sidebar-menu-item.has-badge { position: relative; }
650
630
  .sidebar-menu-item .menu-badge {
@@ -659,7 +639,7 @@
659
639
  display: none;
660
640
  position: fixed;
661
641
  inset: 0;
662
- background: rgba(0, 0, 0, 0.6);
642
+ background: rgba(var(--shadow-rgb), 0.6);
663
643
  z-index: 99;
664
644
  backdrop-filter: blur(2px);
665
645
  -webkit-backdrop-filter: blur(2px);
@@ -712,3 +692,96 @@
712
692
  height: 20px;
713
693
  }
714
694
 
695
+ /* --- Theme picker --- */
696
+ .theme-picker {
697
+ position: fixed;
698
+ background: var(--bg-alt);
699
+ border: 1px solid var(--border);
700
+ border-radius: 12px;
701
+ padding: 0;
702
+ min-width: 220px;
703
+ max-height: 70vh;
704
+ overflow-y: auto;
705
+ box-shadow: 0 8px 32px rgba(var(--shadow-rgb), 0.5);
706
+ z-index: 200;
707
+ opacity: 0;
708
+ transform: translateY(8px);
709
+ pointer-events: none;
710
+ transition: opacity 0.15s, transform 0.15s;
711
+ }
712
+
713
+ .theme-picker.visible {
714
+ opacity: 1;
715
+ transform: translateY(0);
716
+ pointer-events: auto;
717
+ }
718
+
719
+ .theme-picker-header {
720
+ padding: 8px 14px 4px;
721
+ font-size: 11px;
722
+ font-weight: 600;
723
+ color: var(--text-dimmer);
724
+ text-transform: uppercase;
725
+ letter-spacing: 0.5px;
726
+ position: sticky;
727
+ top: 0;
728
+ background: var(--bg-alt);
729
+ z-index: 1;
730
+ }
731
+
732
+ .theme-picker-section {
733
+ padding-bottom: 4px;
734
+ }
735
+
736
+ .theme-picker-item {
737
+ display: flex;
738
+ align-items: center;
739
+ gap: 10px;
740
+ width: 100%;
741
+ padding: 7px 14px;
742
+ border: none;
743
+ background: none;
744
+ color: var(--text-secondary);
745
+ font-family: inherit;
746
+ font-size: 13px;
747
+ cursor: pointer;
748
+ transition: background 0.15s;
749
+ }
750
+
751
+ .theme-picker-item:hover {
752
+ background: rgba(var(--overlay-rgb), 0.05);
753
+ }
754
+
755
+ .theme-picker-item.active {
756
+ color: var(--text);
757
+ }
758
+
759
+ .theme-swatches {
760
+ display: flex;
761
+ gap: 3px;
762
+ flex-shrink: 0;
763
+ }
764
+
765
+ .theme-swatch {
766
+ width: 12px;
767
+ height: 12px;
768
+ border-radius: 3px;
769
+ border: 1px solid rgba(var(--overlay-rgb), 0.1);
770
+ }
771
+
772
+ .theme-picker-label {
773
+ flex: 1;
774
+ text-align: left;
775
+ }
776
+
777
+ .theme-picker-check {
778
+ font-size: 14px;
779
+ color: var(--accent);
780
+ opacity: 0;
781
+ flex-shrink: 0;
782
+ }
783
+
784
+ .theme-picker-item.active .theme-picker-check {
785
+ opacity: 1;
786
+ }
787
+