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
@@ -9,13 +9,13 @@
9
9
  box-sizing: border-box;
10
10
  -webkit-tap-highlight-color: transparent;
11
11
  scrollbar-width: thin;
12
- scrollbar-color: rgba(255,255,255,0.15) transparent;
12
+ scrollbar-color: rgba(var(--overlay-rgb),0.15) transparent;
13
13
  }
14
14
 
15
15
  ::-webkit-scrollbar { width: 6px; height: 6px; }
16
16
  ::-webkit-scrollbar-track { background: transparent; }
17
- ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.15); border-radius: 3px; }
18
- ::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.25); }
17
+ ::-webkit-scrollbar-thumb { background: rgba(var(--overlay-rgb),0.15); border-radius: 3px; }
18
+ ::-webkit-scrollbar-thumb:hover { background: rgba(var(--overlay-rgb),0.25); }
19
19
 
20
20
  :root {
21
21
  --bg: #2F2E2B;
@@ -34,6 +34,40 @@
34
34
  --user-bubble: #46423A;
35
35
  --error: #E5534B;
36
36
  --success: #57AB5A;
37
+ --warning: #E5A84B;
38
+ --accent-8: rgba(218, 119, 86, 0.08);
39
+ --accent-12: rgba(218, 119, 86, 0.12);
40
+ --accent-15: rgba(218, 119, 86, 0.15);
41
+ --accent-20: rgba(218, 119, 86, 0.20);
42
+ --accent-25: rgba(218, 119, 86, 0.25);
43
+ --accent-30: rgba(218, 119, 86, 0.30);
44
+ --error-8: rgba(229, 83, 75, 0.08);
45
+ --error-12: rgba(229, 83, 75, 0.12);
46
+ --error-15: rgba(229, 83, 75, 0.15);
47
+ --error-25: rgba(229, 83, 75, 0.25);
48
+ --success-8: rgba(87, 171, 90, 0.08);
49
+ --success-12: rgba(87, 171, 90, 0.12);
50
+ --success-15: rgba(87, 171, 90, 0.15);
51
+ --success-25: rgba(87, 171, 90, 0.25);
52
+ --warning-bg: rgba(229, 168, 75, 0.12);
53
+ --overlay-rgb: 255,255,255;
54
+ --shadow-rgb: 0,0,0;
55
+ --hl-comment: #6D6860;
56
+ --hl-keyword: #C586C0;
57
+ --hl-string: #57AB5A;
58
+ --hl-number: #DA7756;
59
+ --hl-function: #569CD6;
60
+ --hl-variable: #E5534B;
61
+ --hl-type: #E5A84B;
62
+ --hl-constant: #DA7756;
63
+ --hl-tag: #E5534B;
64
+ --hl-attr: #569CD6;
65
+ --hl-regexp: #4EC9B0;
66
+ --hl-meta: #D7BA7D;
67
+ --hl-builtin: #DA7756;
68
+ --hl-symbol: #D7BA7D;
69
+ --hl-addition: #57AB5A;
70
+ --hl-deletion: #E5534B;
37
71
  --sidebar-bg: #262522;
38
72
  --sidebar-hover: #302E2A;
39
73
  --sidebar-active: #3A3834;
@@ -96,7 +130,7 @@ html, body {
96
130
  opacity: 0;
97
131
  transition: opacity 0.2s, transform 0.2s;
98
132
  pointer-events: none;
99
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
133
+ box-shadow: 0 4px 20px rgba(var(--shadow-rgb), 0.3);
100
134
  }
101
135
 
102
136
  .toast.visible {
@@ -104,8 +138,8 @@ html, body {
104
138
  transform: translateX(-50%) translateY(0);
105
139
  }
106
140
  .toast.toast-warn {
107
- background: #3a2a00;
108
- border-color: #7a5a00;
109
- color: #ffc107;
141
+ background: var(--warning-bg);
142
+ border-color: var(--warning);
143
+ color: var(--warning);
110
144
  }
111
145
 
@@ -51,19 +51,19 @@
51
51
 
52
52
  /* --- Unified diff row colors --- */
53
53
  .diff-row-remove {
54
- background: rgba(229, 83, 75, 0.12);
54
+ background: var(--error-12);
55
55
  }
56
56
 
57
57
  .diff-row-remove .diff-marker {
58
- color: var(--diff-remove, #E5534B);
58
+ color: var(--error);
59
59
  }
60
60
 
61
61
  .diff-row-add {
62
- background: rgba(87, 171, 90, 0.12);
62
+ background: var(--success-12);
63
63
  }
64
64
 
65
65
  .diff-row-add .diff-marker {
66
- color: var(--diff-add, #57AB5A);
66
+ color: var(--success);
67
67
  }
68
68
 
69
69
  /* --- Hunk header row (patch diffs) --- */
@@ -92,12 +92,12 @@
92
92
  /* Split: change rows */
93
93
  .diff-row-change .diff-code-old,
94
94
  .diff-row-remove .diff-code-old {
95
- background: rgba(229, 83, 75, 0.12);
95
+ background: var(--error-12);
96
96
  }
97
97
 
98
98
  .diff-row-change .diff-code-new,
99
99
  .diff-row-add .diff-code-new {
100
- background: rgba(87, 171, 90, 0.12);
100
+ background: var(--success-12);
101
101
  }
102
102
 
103
103
  /* Empty cells in split view */
@@ -32,50 +32,12 @@
32
32
  .sidebar-panel { flex: 1; overflow-y: auto; min-height: 0; }
33
33
  .sidebar-panel.hidden { display: none; }
34
34
 
35
- /* --- File panel header --- */
36
- #file-panel-header {
37
- display: flex;
38
- align-items: center;
39
- padding: 4px 8px;
40
- }
41
-
42
- #file-panel-back {
43
- display: flex;
44
- align-items: center;
45
- gap: 8px;
46
- padding: 8px 12px;
47
- border-radius: 10px;
48
- border: none;
49
- background: transparent;
50
- color: var(--text-secondary);
51
- font-family: inherit;
52
- font-size: 14px;
53
- font-weight: 400;
54
- cursor: pointer;
55
- flex: 1;
56
- transition: background 0.15s, color 0.15s;
57
- }
58
-
59
- #file-panel-back .lucide { width: 16px; height: 16px; flex-shrink: 0; }
60
- #file-panel-back:hover { background: var(--sidebar-hover); color: var(--text); }
61
-
62
- #file-panel-refresh {
63
- display: flex;
64
- align-items: center;
65
- justify-content: center;
66
- width: 32px;
67
- height: 32px;
68
- border-radius: 8px;
69
- border: none;
70
- background: transparent;
71
- color: var(--text-muted);
72
- cursor: pointer;
73
- flex-shrink: 0;
74
- transition: background 0.15s, color 0.15s, transform 0.3s;
35
+ /* --- File browser header --- */
36
+ #sessions-header-content.hidden,
37
+ #files-header-content.hidden {
38
+ display: none;
75
39
  }
76
40
 
77
- #file-panel-refresh .lucide { width: 14px; height: 14px; }
78
- #file-panel-refresh:hover { background: var(--sidebar-hover); color: var(--text); }
79
41
  #file-panel-refresh.spinning { animation: spin-once 0.5s ease; }
80
42
  @keyframes spin-once { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
81
43
 
@@ -414,7 +376,6 @@
414
376
 
415
377
  .terminal-tabs {
416
378
  display: flex;
417
- flex: 1;
418
379
  overflow-x: auto;
419
380
  -webkit-overflow-scrolling: touch;
420
381
  gap: 0;
@@ -424,6 +385,25 @@
424
385
 
425
386
  .terminal-tabs::-webkit-scrollbar { display: none; }
426
387
 
388
+ .terminal-new-tab-btn {
389
+ display: flex;
390
+ align-items: center;
391
+ justify-content: center;
392
+ width: 28px;
393
+ height: 28px;
394
+ flex-shrink: 0;
395
+ border: none;
396
+ background: transparent;
397
+ color: var(--text-muted);
398
+ cursor: pointer;
399
+ border-radius: 6px;
400
+ padding: 0;
401
+ margin: 4px 2px;
402
+ transition: background 0.15s, color 0.15s;
403
+ }
404
+ .terminal-new-tab-btn:hover { background: rgba(var(--overlay-rgb),0.08); color: var(--text); }
405
+ .terminal-new-tab-btn .lucide { width: 14px; height: 14px; }
406
+
427
407
  .terminal-tab {
428
408
  display: flex;
429
409
  align-items: center;
@@ -461,7 +441,7 @@
461
441
 
462
442
  .terminal-tab:hover .terminal-tab-close,
463
443
  .terminal-tab.active .terminal-tab-close { display: flex; }
464
- .terminal-tab-close:hover { background: rgba(255,255,255,0.1); color: var(--text); }
444
+ .terminal-tab-close:hover { background: rgba(var(--overlay-rgb),0.1); color: var(--text); }
465
445
 
466
446
  .terminal-tab-label { cursor: default; }
467
447
 
@@ -483,6 +463,7 @@
483
463
  gap: 2px;
484
464
  padding: 0 8px;
485
465
  flex-shrink: 0;
466
+ margin-left: auto;
486
467
  }
487
468
 
488
469
  /* Wide screens: split panel beside #app */
@@ -517,7 +498,6 @@
517
498
 
518
499
  #terminal-body {
519
500
  flex: 1;
520
- background: #1a1a1a;
521
501
  min-height: 0;
522
502
  overflow: hidden;
523
503
  position: relative;
@@ -526,7 +506,7 @@
526
506
  .terminal-tab-body {
527
507
  position: absolute;
528
508
  inset: 0;
529
- padding: 4px;
509
+ padding: 4px 0 0 4px;
530
510
  }
531
511
 
532
512
  .terminal-tab-body .xterm {
@@ -598,6 +578,36 @@
598
578
  font-style: italic;
599
579
  }
600
580
 
581
+ /* --- Terminal context menu --- */
582
+ .term-ctx-menu {
583
+ position: fixed;
584
+ background: var(--bg-alt);
585
+ border: 1px solid var(--border);
586
+ border-radius: 10px;
587
+ padding: 4px 0;
588
+ min-width: 160px;
589
+ box-shadow: 0 4px 16px rgba(var(--shadow-rgb), 0.4);
590
+ z-index: 500;
591
+ }
592
+
593
+ .term-ctx-item {
594
+ display: flex;
595
+ align-items: center;
596
+ gap: 8px;
597
+ width: 100%;
598
+ padding: 8px 12px;
599
+ font-size: 13px;
600
+ color: var(--text-secondary);
601
+ background: none;
602
+ border: none;
603
+ font-family: inherit;
604
+ cursor: pointer;
605
+ transition: background 0.15s;
606
+ }
607
+
608
+ .term-ctx-item .lucide { width: 14px; height: 14px; flex-shrink: 0; }
609
+ .term-ctx-item:hover { background: rgba(var(--overlay-rgb), 0.05); }
610
+
601
611
  /* --- File Edit History --- */
602
612
 
603
613
  .file-history-panel {
@@ -697,7 +707,7 @@
697
707
  }
698
708
 
699
709
  .file-history-badge.badge-commit {
700
- background: rgba(255,255,255,0.06);
710
+ background: rgba(var(--overlay-rgb),0.06);
701
711
  color: var(--text-muted);
702
712
  }
703
713
 
@@ -707,7 +717,7 @@
707
717
  color: var(--text-muted);
708
718
  margin-top: 4px;
709
719
  padding: 2px 6px;
710
- background: rgba(255, 255, 255, 0.04);
720
+ background: rgba(var(--overlay-rgb), 0.04);
711
721
  border-radius: 3px;
712
722
  overflow: hidden;
713
723
  text-overflow: ellipsis;
@@ -781,7 +791,7 @@
781
791
  padding: 10px 12px;
782
792
  margin-bottom: 8px;
783
793
  border-radius: 8px;
784
- background: rgba(255, 255, 255, 0.04);
794
+ background: rgba(var(--overlay-rgb), 0.04);
785
795
  border: 1px solid var(--border);
786
796
  }
787
797
 
@@ -816,11 +826,11 @@
816
826
  flex: 1;
817
827
  min-width: 0;
818
828
  padding: 7px 10px;
819
- border: 1.5px dashed rgba(255, 255, 255, 0.15);
829
+ border: 1.5px dashed rgba(var(--overlay-rgb), 0.15);
820
830
  border-radius: 6px;
821
831
  font-size: 11px;
822
832
  color: var(--text-muted);
823
- background: rgba(255, 255, 255, 0.02);
833
+ background: rgba(var(--overlay-rgb), 0.02);
824
834
  transition: border-color 0.15s, background 0.15s;
825
835
  }
826
836
 
@@ -841,7 +851,7 @@
841
851
  font-size: 10px;
842
852
  font-weight: 700;
843
853
  flex-shrink: 0;
844
- background: rgba(255, 255, 255, 0.1);
854
+ background: rgba(var(--overlay-rgb), 0.1);
845
855
  color: var(--text-muted);
846
856
  }
847
857
 
@@ -0,0 +1,144 @@
1
+ /* ==========================================================================
2
+ Syntax Highlighting (highlight.js) — base16 CSS-variable driven
3
+ Replaces CDN github-dark-dimmed.min.css
4
+ ========================================================================== */
5
+
6
+ .hljs {
7
+ color: var(--text);
8
+ background: var(--code-bg);
9
+ }
10
+
11
+ /* --- Comments --- */
12
+ .hljs-comment,
13
+ .hljs-quote {
14
+ color: var(--hl-comment);
15
+ font-style: italic;
16
+ }
17
+
18
+ /* --- Keywords / control flow --- */
19
+ .hljs-keyword,
20
+ .hljs-selector-tag,
21
+ .hljs-selector-id {
22
+ color: var(--hl-keyword);
23
+ }
24
+
25
+ /* --- Strings / template literals --- */
26
+ .hljs-string,
27
+ .hljs-doctag,
28
+ .hljs-selector-class {
29
+ color: var(--hl-string);
30
+ }
31
+
32
+ /* --- Numbers / booleans / null --- */
33
+ .hljs-number,
34
+ .hljs-literal {
35
+ color: var(--hl-number);
36
+ }
37
+
38
+ /* --- Functions / method calls --- */
39
+ .hljs-title,
40
+ .hljs-title.function_,
41
+ .hljs-section {
42
+ color: var(--hl-function);
43
+ }
44
+
45
+ /* --- Variables / params --- */
46
+ .hljs-variable,
47
+ .hljs-template-variable,
48
+ .hljs-params {
49
+ color: var(--hl-variable);
50
+ }
51
+
52
+ /* --- Types / classes --- */
53
+ .hljs-type,
54
+ .hljs-title.class_,
55
+ .hljs-title.class_.inherited__ {
56
+ color: var(--hl-type);
57
+ }
58
+
59
+ /* --- Constants / built-ins --- */
60
+ .hljs-built_in {
61
+ color: var(--hl-builtin);
62
+ }
63
+
64
+ /* --- Tags (HTML/XML) --- */
65
+ .hljs-tag,
66
+ .hljs-name {
67
+ color: var(--hl-tag);
68
+ }
69
+
70
+ /* --- Attributes --- */
71
+ .hljs-attr,
72
+ .hljs-attribute {
73
+ color: var(--hl-attr);
74
+ }
75
+
76
+ /* --- Regexp / links --- */
77
+ .hljs-regexp,
78
+ .hljs-link {
79
+ color: var(--hl-regexp);
80
+ }
81
+
82
+ /* --- Meta / preprocessor --- */
83
+ .hljs-meta,
84
+ .hljs-meta .hljs-keyword,
85
+ .hljs-meta .hljs-string {
86
+ color: var(--hl-meta);
87
+ }
88
+
89
+ /* --- Symbols / special --- */
90
+ .hljs-symbol,
91
+ .hljs-bullet {
92
+ color: var(--hl-symbol);
93
+ }
94
+
95
+ /* --- Diff additions / deletions --- */
96
+ .hljs-addition {
97
+ color: var(--hl-addition);
98
+ background: var(--success-8);
99
+ }
100
+
101
+ .hljs-deletion {
102
+ color: var(--hl-deletion);
103
+ background: var(--error-8);
104
+ }
105
+
106
+ /* --- Emphasis / strong --- */
107
+ .hljs-emphasis {
108
+ font-style: italic;
109
+ }
110
+
111
+ .hljs-strong {
112
+ font-weight: 700;
113
+ }
114
+
115
+ /* --- Subst / interpolation --- */
116
+ .hljs-subst {
117
+ color: var(--text);
118
+ }
119
+
120
+ /* --- Selector --- */
121
+ .hljs-selector-attr,
122
+ .hljs-selector-pseudo {
123
+ color: var(--hl-keyword);
124
+ }
125
+
126
+ /* --- Property (CSS, JSON keys) --- */
127
+ .hljs-property {
128
+ color: var(--hl-attr);
129
+ }
130
+
131
+ /* --- Punctuation (brackets etc.) --- */
132
+ .hljs-punctuation {
133
+ color: var(--text-secondary);
134
+ }
135
+
136
+ /* --- Operator --- */
137
+ .hljs-operator {
138
+ color: var(--hl-keyword);
139
+ }
140
+
141
+ /* --- Char / escape sequences --- */
142
+ .hljs-char.escape_ {
143
+ color: var(--hl-regexp);
144
+ }
@@ -12,7 +12,7 @@
12
12
  display: inline-flex;
13
13
  align-items: center;
14
14
  gap: 8px;
15
- background: rgba(255, 255, 255, 0.06);
15
+ background: rgba(var(--overlay-rgb), 0.06);
16
16
  border: 1px solid var(--border);
17
17
  border-radius: 10px;
18
18
  padding: 8px 12px;
@@ -23,7 +23,7 @@
23
23
 
24
24
  .bubble-paste:hover {
25
25
  border-color: var(--text-dimmer);
26
- background: rgba(255, 255, 255, 0.1);
26
+ background: rgba(var(--overlay-rgb), 0.1);
27
27
  }
28
28
 
29
29
  .bubble-paste-preview {
@@ -90,7 +90,7 @@
90
90
  }
91
91
 
92
92
  .pasted-chip-remove .lucide { width: 12px; height: 12px; }
93
- .pasted-chip-remove:hover { color: var(--text); background: rgba(255, 255, 255, 0.1); }
93
+ .pasted-chip-remove:hover { color: var(--text); background: rgba(var(--overlay-rgb), 0.1); }
94
94
 
95
95
  /* --- Paste viewer modal --- */
96
96
  #paste-modal { position: fixed; inset: 0; z-index: 300; display: flex; align-items: center; justify-content: center; }
@@ -133,7 +133,7 @@
133
133
  transition: color 0.15s, background 0.15s;
134
134
  }
135
135
 
136
- .paste-modal-close:hover { color: var(--text); background: rgba(255, 255, 255, 0.06); }
136
+ .paste-modal-close:hover { color: var(--text); background: rgba(var(--overlay-rgb), 0.06); }
137
137
 
138
138
  .paste-modal-body {
139
139
  margin: 0;
@@ -245,6 +245,8 @@
245
245
  max-height: 120px;
246
246
  overflow-y: auto;
247
247
  box-sizing: border-box;
248
+ unicode-bidi: plaintext;
249
+ text-align: start;
248
250
  }
249
251
 
250
252
  #input::placeholder {
@@ -286,7 +288,7 @@
286
288
  }
287
289
 
288
290
  #attach-btn .lucide { width: 20px; height: 20px; }
289
- #attach-btn:hover { background: rgba(255, 255, 255, 0.06); color: var(--text); }
291
+ #attach-btn:hover { background: rgba(var(--overlay-rgb), 0.06); color: var(--text); }
290
292
 
291
293
  #attach-menu {
292
294
  position: absolute;
@@ -296,7 +298,7 @@
296
298
  background: var(--bg-alt);
297
299
  border: 1px solid var(--border);
298
300
  border-radius: 14px;
299
- box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.4);
301
+ box-shadow: 0 -4px 24px rgba(var(--shadow-rgb), 0.4);
300
302
  z-index: 10;
301
303
  overflow: hidden;
302
304
  }
@@ -323,7 +325,7 @@
323
325
  }
324
326
 
325
327
  .attach-menu-item:hover {
326
- background: rgba(255, 255, 255, 0.05);
328
+ background: rgba(var(--overlay-rgb), 0.05);
327
329
  color: var(--text);
328
330
  }
329
331
 
@@ -379,7 +381,7 @@
379
381
  border: 1px solid var(--border);
380
382
  border-radius: 14px;
381
383
  margin-bottom: 8px;
382
- box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.4);
384
+ box-shadow: 0 -4px 24px rgba(var(--shadow-rgb), 0.4);
383
385
  z-index: 10;
384
386
  }
385
387
 
@@ -398,7 +400,7 @@
398
400
 
399
401
  .slash-item:hover,
400
402
  .slash-item.active {
401
- background: rgba(255, 255, 255, 0.05);
403
+ background: rgba(var(--overlay-rgb), 0.05);
402
404
  }
403
405
 
404
406
  .slash-item .slash-cmd {