claw-design 1.0.1

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 (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +72 -0
  3. package/dist/cli/commands/start.d.ts +7 -0
  4. package/dist/cli/commands/start.d.ts.map +1 -0
  5. package/dist/cli/commands/start.js +176 -0
  6. package/dist/cli/commands/start.js.map +1 -0
  7. package/dist/cli/index.d.ts +3 -0
  8. package/dist/cli/index.d.ts.map +1 -0
  9. package/dist/cli/index.js +20 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/cli/utils/claude.d.ts +21 -0
  12. package/dist/cli/utils/claude.d.ts.map +1 -0
  13. package/dist/cli/utils/claude.js +42 -0
  14. package/dist/cli/utils/claude.js.map +1 -0
  15. package/dist/cli/utils/dev-server.d.ts +14 -0
  16. package/dist/cli/utils/dev-server.d.ts.map +1 -0
  17. package/dist/cli/utils/dev-server.js +57 -0
  18. package/dist/cli/utils/dev-server.js.map +1 -0
  19. package/dist/cli/utils/electron.d.ts +7 -0
  20. package/dist/cli/utils/electron.d.ts.map +1 -0
  21. package/dist/cli/utils/electron.js +36 -0
  22. package/dist/cli/utils/electron.js.map +1 -0
  23. package/dist/cli/utils/output.d.ts +6 -0
  24. package/dist/cli/utils/output.d.ts.map +1 -0
  25. package/dist/cli/utils/output.js +21 -0
  26. package/dist/cli/utils/output.js.map +1 -0
  27. package/dist/cli/utils/port-detect.d.ts +30 -0
  28. package/dist/cli/utils/port-detect.d.ts.map +1 -0
  29. package/dist/cli/utils/port-detect.js +95 -0
  30. package/dist/cli/utils/port-detect.js.map +1 -0
  31. package/dist/cli/utils/preflight.d.ts +20 -0
  32. package/dist/cli/utils/preflight.d.ts.map +1 -0
  33. package/dist/cli/utils/preflight.js +33 -0
  34. package/dist/cli/utils/preflight.js.map +1 -0
  35. package/dist/cli/utils/process.d.ts +23 -0
  36. package/dist/cli/utils/process.d.ts.map +1 -0
  37. package/dist/cli/utils/process.js +57 -0
  38. package/dist/cli/utils/process.js.map +1 -0
  39. package/out/main/index.js +1123 -0
  40. package/out/preload/overlay.cjs +56 -0
  41. package/out/preload/sidebar.cjs +29 -0
  42. package/out/renderer/assets/overlay-Bsx1u_qg.css +449 -0
  43. package/out/renderer/assets/overlay-DZl3I3jq.js +689 -0
  44. package/out/renderer/assets/sidebar-Bt34gvPU.js +563 -0
  45. package/out/renderer/assets/sidebar-BxEPS84k.css +515 -0
  46. package/out/renderer/assets/toast-CLlgwMU_.js +110 -0
  47. package/out/renderer/overlay.html +131 -0
  48. package/out/renderer/sidebar.html +64 -0
  49. package/package.json +67 -0
  50. package/resources/icon.icns +0 -0
  51. package/resources/icon.png +0 -0
  52. package/scripts/postinstall.cjs +56 -0
@@ -0,0 +1,515 @@
1
+ /* Sidebar renderer: dark chrome aesthetic matching overlay */
2
+ html,
3
+ body {
4
+ margin: 0;
5
+ padding: 0;
6
+ width: 100%;
7
+ height: 100%;
8
+ overflow: hidden;
9
+ background: transparent;
10
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
11
+ -webkit-font-smoothing: antialiased;
12
+ -moz-osx-font-smoothing: grayscale;
13
+ }
14
+
15
+ /* ============================================================
16
+ Minimized state: icon + badge (vertically stacked)
17
+ ============================================================ */
18
+
19
+ .sidebar-minimized {
20
+ display: flex;
21
+ flex-direction: column;
22
+ align-items: center;
23
+ gap: 4px;
24
+ width: 100%;
25
+ height: 100%;
26
+ justify-content: center;
27
+ }
28
+
29
+ .sidebar-expand-btn {
30
+ width: 36px;
31
+ height: 36px;
32
+ background: rgba(10, 10, 10, 0.88);
33
+ border: none;
34
+ border-radius: 12px;
35
+ color: rgba(255, 255, 255, 0.55);
36
+ cursor: pointer;
37
+ display: flex;
38
+ align-items: center;
39
+ justify-content: center;
40
+ padding: 0;
41
+ transition: color 120ms ease, background 120ms ease;
42
+ }
43
+
44
+ .sidebar-expand-btn:hover {
45
+ color: #ffffff;
46
+ background: rgba(10, 10, 10, 0.95);
47
+ }
48
+
49
+ /* Drag handle (shared between minimized and expanded headers) */
50
+ .sidebar-drag-handle {
51
+ display: flex;
52
+ align-items: center;
53
+ justify-content: center;
54
+ width: 36px;
55
+ height: 20px;
56
+ color: rgba(255, 255, 255, 0.25);
57
+ cursor: grab;
58
+ }
59
+
60
+ .sidebar-drag-handle:active {
61
+ cursor: grabbing;
62
+ }
63
+
64
+ /* Badge counter below the expand icon */
65
+ .sidebar-badge {
66
+ background: rgba(10, 10, 10, 0.88);
67
+ border-radius: 8px;
68
+ padding: 4px 8px;
69
+ margin-top: 4px;
70
+ border: 2px solid transparent;
71
+ }
72
+
73
+ #sidebar-badge-text {
74
+ font-size: 12px;
75
+ font-weight: 600;
76
+ line-height: 1.0;
77
+ color: rgba(138, 180, 248, 1);
78
+ }
79
+
80
+ /* Badge pulse animations (single-shot on task complete/error while minimized) */
81
+ @keyframes badge-pulse-done {
82
+ 0% {
83
+ border-color: transparent;
84
+ }
85
+ 50% {
86
+ border-color: rgba(138, 180, 248, 0.6);
87
+ }
88
+ 100% {
89
+ border-color: transparent;
90
+ }
91
+ }
92
+
93
+ @keyframes badge-pulse-error {
94
+ 0% {
95
+ border-color: transparent;
96
+ }
97
+ 50% {
98
+ border-color: rgba(248, 150, 138, 0.7);
99
+ }
100
+ 100% {
101
+ border-color: transparent;
102
+ }
103
+ }
104
+
105
+ .sidebar-badge.pulse-done {
106
+ animation: badge-pulse-done 600ms ease-out 1;
107
+ border: 2px solid transparent;
108
+ }
109
+
110
+ .sidebar-badge.pulse-error {
111
+ animation: badge-pulse-error 600ms ease-out 1;
112
+ border: 2px solid transparent;
113
+ }
114
+
115
+ /* ============================================================
116
+ Expanded state: full sidebar panel
117
+ ============================================================ */
118
+
119
+ .sidebar-expanded {
120
+ width: 100%;
121
+ height: 100%;
122
+ background: rgba(10, 10, 10, 0.88);
123
+ box-shadow: 0 0 24px rgba(0, 0, 0, 0.4);
124
+ border: 1px solid rgba(255, 255, 255, 0.08);
125
+ border-radius: 16px;
126
+ overflow: hidden;
127
+ display: flex;
128
+ flex-direction: column;
129
+ }
130
+
131
+ /* Header: "Tasks" label + minimize button */
132
+ .sidebar-header {
133
+ display: flex;
134
+ justify-content: space-between;
135
+ align-items: center;
136
+ padding: 16px 16px 8px 16px;
137
+ }
138
+
139
+ .sidebar-header-label {
140
+ font-size: 11px;
141
+ font-weight: 400;
142
+ line-height: 1.36;
143
+ color: rgba(255, 255, 255, 0.5);
144
+ }
145
+
146
+ .sidebar-clear-btn {
147
+ background: none;
148
+ border: none;
149
+ font-size: 11px;
150
+ font-weight: 400;
151
+ color: rgba(255, 255, 255, 0.35);
152
+ cursor: pointer;
153
+ padding: 4px 8px;
154
+ border-radius: 6px;
155
+ margin-left: auto;
156
+ transition: color 120ms ease;
157
+ }
158
+
159
+ .sidebar-clear-btn:hover {
160
+ color: rgba(255, 255, 255, 0.7);
161
+ }
162
+
163
+ .sidebar-minimize-btn {
164
+ width: 28px;
165
+ height: 28px;
166
+ background: none;
167
+ border: none;
168
+ color: rgba(255, 255, 255, 0.4);
169
+ cursor: pointer;
170
+ display: flex;
171
+ align-items: center;
172
+ justify-content: center;
173
+ border-radius: 6px;
174
+ padding: 0;
175
+ transition: color 120ms ease;
176
+ }
177
+
178
+ .sidebar-minimize-btn:hover {
179
+ color: rgba(255, 255, 255, 0.7);
180
+ }
181
+
182
+ /* ============================================================
183
+ Task list (scrollable container)
184
+ ============================================================ */
185
+
186
+ .sidebar-task-list {
187
+ flex: 1;
188
+ overflow-y: auto;
189
+ scrollbar-width: none;
190
+ }
191
+
192
+ .sidebar-task-list::-webkit-scrollbar {
193
+ display: none;
194
+ }
195
+
196
+ /* ============================================================
197
+ Task row
198
+ ============================================================ */
199
+
200
+ .task-row {
201
+ padding: 8px 16px;
202
+ margin-bottom: 4px;
203
+ border-bottom: 1px solid rgba(255, 255, 255, 0.06);
204
+ animation: task-row-enter 150ms ease-out;
205
+ }
206
+
207
+ @keyframes task-row-enter {
208
+ from {
209
+ opacity: 0;
210
+ transform: translateY(8px);
211
+ }
212
+ to {
213
+ opacity: 1;
214
+ transform: translateY(0);
215
+ }
216
+ }
217
+
218
+ /* Instruction text: 2-line clamp */
219
+ .task-instruction {
220
+ font-size: 13px;
221
+ font-weight: 400;
222
+ line-height: 1.38;
223
+ color: rgba(255, 255, 255, 0.8);
224
+ display: -webkit-box;
225
+ -webkit-line-clamp: 2;
226
+ -webkit-box-orient: vertical;
227
+ overflow: hidden;
228
+ text-overflow: ellipsis;
229
+ margin-bottom: 4px;
230
+ }
231
+
232
+ .task-instruction.error-row {
233
+ color: rgba(255, 255, 255, 0.6);
234
+ }
235
+
236
+ /* ============================================================
237
+ Status badge
238
+ ============================================================ */
239
+
240
+ .task-status-row {
241
+ display: flex;
242
+ align-items: center;
243
+ justify-content: space-between;
244
+ }
245
+
246
+ .status-badge {
247
+ display: inline-block;
248
+ font-size: 11px;
249
+ font-weight: 600;
250
+ line-height: 1.0;
251
+ border-radius: 6px;
252
+ padding: 4px 8px;
253
+ }
254
+
255
+ .status-badge.queued {
256
+ background: rgba(255, 255, 255, 0.08);
257
+ color: rgba(255, 255, 255, 0.5);
258
+ }
259
+
260
+ .status-badge.sending {
261
+ background: rgba(255, 255, 255, 0.12);
262
+ color: rgba(255, 255, 255, 0.7);
263
+ animation: status-pulse 1500ms ease-in-out infinite;
264
+ }
265
+
266
+ .status-badge.editing {
267
+ background: rgba(138, 180, 248, 0.15);
268
+ color: rgba(138, 180, 248, 1);
269
+ animation: status-pulse 1500ms ease-in-out infinite;
270
+ }
271
+
272
+ .status-badge.done {
273
+ background: rgba(138, 180, 248, 0.15);
274
+ color: rgba(138, 180, 248, 1);
275
+ }
276
+
277
+ .status-badge.error {
278
+ background: rgba(248, 150, 138, 0.15);
279
+ color: rgba(248, 150, 138, 1);
280
+ }
281
+
282
+ @keyframes status-pulse {
283
+ 0%,
284
+ 100% {
285
+ opacity: 0.6;
286
+ }
287
+ 50% {
288
+ opacity: 1;
289
+ }
290
+ }
291
+
292
+ /* ============================================================
293
+ Error message + button row
294
+ ============================================================ */
295
+
296
+ .task-error-message {
297
+ font-size: 12px;
298
+ font-weight: 400;
299
+ line-height: 1.5;
300
+ color: rgba(248, 150, 138, 0.9);
301
+ margin-top: 4px;
302
+ display: -webkit-box;
303
+ -webkit-line-clamp: 3;
304
+ -webkit-box-orient: vertical;
305
+ overflow: hidden;
306
+ }
307
+
308
+ .task-button-row {
309
+ display: flex;
310
+ gap: 16px;
311
+ margin-top: 8px;
312
+ }
313
+
314
+ .btn-retry {
315
+ background: none;
316
+ border: none;
317
+ font-size: 11px;
318
+ font-weight: 400;
319
+ color: rgba(138, 180, 248, 0.8);
320
+ cursor: pointer;
321
+ padding: 0;
322
+ transition: color 120ms ease;
323
+ }
324
+
325
+ .btn-retry:hover {
326
+ color: rgba(138, 180, 248, 1);
327
+ }
328
+
329
+ .btn-dismiss {
330
+ background: none;
331
+ border: none;
332
+ font-size: 11px;
333
+ font-weight: 400;
334
+ color: rgba(255, 255, 255, 0.4);
335
+ cursor: pointer;
336
+ padding: 0;
337
+ transition: color 120ms ease;
338
+ }
339
+
340
+ .btn-dismiss:hover {
341
+ color: rgba(255, 255, 255, 0.7);
342
+ }
343
+
344
+ /* Model label */
345
+ .task-model {
346
+ font-size: 11px;
347
+ font-weight: 400;
348
+ color: rgba(255, 255, 255, 0.25);
349
+ }
350
+
351
+ /* Elapsed timer */
352
+ .task-timer {
353
+ font-size: 11px;
354
+ font-weight: 400;
355
+ color: rgba(255, 255, 255, 0.3);
356
+ font-variant-numeric: tabular-nums;
357
+ min-width: 28px;
358
+ }
359
+
360
+ /* Stop button on active tasks */
361
+ .task-row-stop-btn {
362
+ background: none;
363
+ border: none;
364
+ font-size: 11px;
365
+ font-weight: 400;
366
+ color: rgba(248, 150, 138, 0.7);
367
+ cursor: pointer;
368
+ padding: 2px 6px;
369
+ border-radius: 4px;
370
+ transition: color 80ms ease;
371
+ }
372
+
373
+ .task-row-stop-btn:hover {
374
+ color: rgba(248, 150, 138, 1);
375
+ }
376
+
377
+ /* Undo button on done rows (visible on hover) */
378
+ .task-row-undo-btn {
379
+ opacity: 0;
380
+ transition: opacity 80ms ease-out;
381
+ background: none;
382
+ border: none;
383
+ font-size: 11px;
384
+ font-weight: 400;
385
+ color: rgba(138, 180, 248, 0.7);
386
+ cursor: pointer;
387
+ padding: 2px 6px;
388
+ border-radius: 4px;
389
+ }
390
+
391
+ .task-row:hover .task-row-undo-btn {
392
+ opacity: 1;
393
+ }
394
+
395
+ .task-row-undo-btn:hover {
396
+ color: rgba(138, 180, 248, 1);
397
+ }
398
+
399
+ .task-row-undo-btn:disabled {
400
+ color: rgba(255, 255, 255, 0.3);
401
+ cursor: default;
402
+ }
403
+
404
+ /* Dismiss button on hover of done rows (small x icon) */
405
+ .task-row-dismiss-btn {
406
+ opacity: 0;
407
+ transition: opacity 80ms ease-out;
408
+ background: none;
409
+ border: none;
410
+ color: rgba(255, 255, 255, 0.4);
411
+ cursor: pointer;
412
+ width: 20px;
413
+ height: 20px;
414
+ display: flex;
415
+ align-items: center;
416
+ justify-content: center;
417
+ padding: 0;
418
+ border-radius: 4px;
419
+ }
420
+
421
+ .task-row:hover .task-row-dismiss-btn {
422
+ opacity: 1;
423
+ }
424
+
425
+ .task-row-dismiss-btn:hover {
426
+ color: rgba(255, 255, 255, 0.7);
427
+ }
428
+
429
+ /* ============================================================
430
+ Activity text (live-streaming what Claude is doing)
431
+ ============================================================ */
432
+
433
+ .task-activity {
434
+ font-size: 11px;
435
+ font-weight: 400;
436
+ line-height: 1.45;
437
+ color: rgba(255, 255, 255, 0.4);
438
+ margin-top: 2px;
439
+ display: -webkit-box;
440
+ -webkit-line-clamp: 2;
441
+ -webkit-box-orient: vertical;
442
+ overflow: hidden;
443
+ text-overflow: ellipsis;
444
+ font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
445
+ }
446
+
447
+ /* ============================================================
448
+ Task row clickable (for log expand)
449
+ ============================================================ */
450
+
451
+ .task-instruction {
452
+ cursor: pointer;
453
+ }
454
+
455
+ .task-instruction:hover {
456
+ color: rgba(255, 255, 255, 1);
457
+ }
458
+
459
+ /* ============================================================
460
+ Log viewer (expanded per-task)
461
+ ============================================================ */
462
+
463
+ .task-logs {
464
+ max-height: 200px;
465
+ overflow-y: auto;
466
+ scrollbar-width: thin;
467
+ scrollbar-color: rgba(255, 255, 255, 0.12) transparent;
468
+ margin-top: 6px;
469
+ padding: 8px;
470
+ background: rgba(0, 0, 0, 0.3);
471
+ border-radius: 8px;
472
+ border: 1px solid rgba(255, 255, 255, 0.06);
473
+ }
474
+
475
+ .task-logs::-webkit-scrollbar {
476
+ width: 4px;
477
+ }
478
+
479
+ .task-logs::-webkit-scrollbar-thumb {
480
+ background: rgba(255, 255, 255, 0.12);
481
+ border-radius: 2px;
482
+ }
483
+
484
+ .task-log-entry {
485
+ font-size: 11px;
486
+ font-weight: 400;
487
+ line-height: 1.5;
488
+ color: rgba(255, 255, 255, 0.5);
489
+ font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
490
+ padding: 1px 0;
491
+ white-space: pre-wrap;
492
+ word-break: break-all;
493
+ }
494
+
495
+ .task-log-entry.log-tool {
496
+ color: rgba(138, 180, 248, 0.7);
497
+ }
498
+
499
+ .task-log-entry.log-status {
500
+ color: rgba(255, 255, 255, 0.6);
501
+ font-weight: 500;
502
+ }
503
+
504
+ /* ============================================================
505
+ Accessibility: reduced motion
506
+ ============================================================ */
507
+
508
+ @media (prefers-reduced-motion: reduce) {
509
+ *,
510
+ *::before,
511
+ *::after {
512
+ animation-duration: 0s !important;
513
+ transition-duration: 0s !important;
514
+ }
515
+ }
@@ -0,0 +1,110 @@
1
+ const toastTimers = /* @__PURE__ */ new Map();
2
+ function createToastIcon(doc, severity) {
3
+ const svg = doc.createElementNS("http://www.w3.org/2000/svg", "svg");
4
+ svg.setAttribute("width", "20");
5
+ svg.setAttribute("height", "20");
6
+ svg.setAttribute("viewBox", "0 0 20 20");
7
+ svg.setAttribute("fill", "none");
8
+ svg.classList.add("claw-toast__icon");
9
+ if (severity === "error") {
10
+ const path = doc.createElementNS("http://www.w3.org/2000/svg", "path");
11
+ path.setAttribute("d", "M10 2L18 16H2L10 2Z");
12
+ path.setAttribute("stroke", "currentColor");
13
+ path.setAttribute("stroke-width", "1.5");
14
+ path.setAttribute("stroke-linejoin", "round");
15
+ path.setAttribute("fill", "none");
16
+ svg.appendChild(path);
17
+ const line = doc.createElementNS("http://www.w3.org/2000/svg", "path");
18
+ line.setAttribute("d", "M10 8V11M10 13.5V14");
19
+ line.setAttribute("stroke", "currentColor");
20
+ line.setAttribute("stroke-width", "1.5");
21
+ line.setAttribute("stroke-linecap", "round");
22
+ svg.appendChild(line);
23
+ } else {
24
+ const circle = doc.createElementNS("http://www.w3.org/2000/svg", "circle");
25
+ circle.setAttribute("cx", "10");
26
+ circle.setAttribute("cy", "10");
27
+ circle.setAttribute("r", "8");
28
+ circle.setAttribute("stroke", "currentColor");
29
+ circle.setAttribute("stroke-width", "1.5");
30
+ circle.setAttribute("fill", "none");
31
+ svg.appendChild(circle);
32
+ const line = doc.createElementNS("http://www.w3.org/2000/svg", "path");
33
+ line.setAttribute("d", "M10 7V7.01M10 10V14");
34
+ line.setAttribute("stroke", "currentColor");
35
+ line.setAttribute("stroke-width", "1.5");
36
+ line.setAttribute("stroke-linecap", "round");
37
+ svg.appendChild(line);
38
+ }
39
+ return svg;
40
+ }
41
+ function createToastElement(doc, data) {
42
+ const toast = doc.createElement("div");
43
+ toast.className = `claw-toast claw-toast--${data.severity}`;
44
+ toast.dataset.toastId = data.id;
45
+ toast.setAttribute("role", "alert");
46
+ toast.setAttribute("aria-live", data.persistent ? "assertive" : "polite");
47
+ const icon = createToastIcon(doc, data.severity);
48
+ toast.appendChild(icon);
49
+ const content = doc.createElement("div");
50
+ content.className = "claw-toast__content";
51
+ if (data.title) {
52
+ const titleEl = doc.createElement("div");
53
+ titleEl.className = "claw-toast__title";
54
+ titleEl.textContent = data.title;
55
+ content.appendChild(titleEl);
56
+ }
57
+ const msgEl = doc.createElement("div");
58
+ msgEl.className = "claw-toast__message";
59
+ msgEl.textContent = data.message;
60
+ content.appendChild(msgEl);
61
+ if (data.persistent) {
62
+ const dismissBtn = doc.createElement("button");
63
+ dismissBtn.className = "claw-toast__dismiss";
64
+ dismissBtn.textContent = "Dismiss";
65
+ dismissBtn.setAttribute("aria-label", "Dismiss notification");
66
+ dismissBtn.addEventListener("click", (e) => {
67
+ e.stopPropagation();
68
+ dismissToast(doc, data.id);
69
+ });
70
+ content.appendChild(dismissBtn);
71
+ }
72
+ toast.appendChild(content);
73
+ return toast;
74
+ }
75
+ function showToast(doc, data) {
76
+ const container = doc.getElementById("claw-toast-container");
77
+ if (!container) return;
78
+ const toast = createToastElement(doc, data);
79
+ container.prepend(toast);
80
+ requestAnimationFrame(() => {
81
+ toast.classList.add("claw-toast--visible");
82
+ });
83
+ if (!data.persistent) {
84
+ const timer = setTimeout(() => dismissToast(doc, data.id), 5e3);
85
+ toastTimers.set(data.id, timer);
86
+ toast.addEventListener("click", () => dismissToast(doc, data.id));
87
+ toast.style.cursor = "pointer";
88
+ }
89
+ }
90
+ function dismissToast(doc, id) {
91
+ const container = doc.getElementById("claw-toast-container");
92
+ if (!container) return;
93
+ const toast = container.querySelector(`[data-toast-id="${CSS.escape(id)}"]`);
94
+ if (!toast) return;
95
+ const timer = toastTimers.get(id);
96
+ if (timer) {
97
+ clearTimeout(timer);
98
+ toastTimers.delete(id);
99
+ }
100
+ toast.classList.remove("claw-toast--visible");
101
+ toast.classList.add("claw-toast--exiting");
102
+ setTimeout(() => {
103
+ toast.remove();
104
+ }, 150);
105
+ }
106
+ export {
107
+ createToastElement,
108
+ dismissToast,
109
+ showToast
110
+ };