@delt/claude-alarm 0.3.2 → 0.3.5
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/README.md +15 -76
- package/dist/dashboard/index.html +53 -10
- package/package.json +1 -1
- package/src/dashboard/index.html +53 -10
package/README.md
CHANGED
|
@@ -6,50 +6,18 @@ Monitor and interact with multiple Claude Code sessions from a web dashboard. Ge
|
|
|
6
6
|
|
|
7
7
|
## Architecture
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
CC1["Claude Code<br/>(Session 1)"] --> CS1["Channel Server"]
|
|
13
|
-
CC2["Claude Code<br/>(Session 2)"] --> CS2["Channel Server"]
|
|
14
|
-
CC3["Claude Code<br/>(Session 3)"] --> CS3["Channel Server"]
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
CS1 -->|WebSocket| HUB["Hub Server<br/>:7900"]
|
|
18
|
-
CS2 -->|WebSocket| HUB
|
|
19
|
-
CS3 -->|WebSocket| HUB
|
|
20
|
-
|
|
21
|
-
HUB -->|HTTP| DASH["Web Dashboard"]
|
|
22
|
-
HUB -->|Toast| NOTIF["Desktop<br/>Notifications"]
|
|
23
|
-
|
|
24
|
-
subgraph "Remote Machine (optional)"
|
|
25
|
-
CC4["Claude Code<br/>(Session 4)"] --> CS4["Channel Server"]
|
|
26
|
-
end
|
|
27
|
-
CS4 -->|WebSocket| HUB
|
|
28
|
-
|
|
29
|
-
style HUB fill:#7c6aef,stroke:#5a4db8,color:#fff
|
|
30
|
-
style DASH fill:#3dd68c,stroke:#22a06b,color:#000
|
|
31
|
-
style NOTIF fill:#f5c542,stroke:#d4a72c,color:#000
|
|
32
|
-
```
|
|
9
|
+
<p align="center">
|
|
10
|
+
<img src="docs/architecture.svg" alt="Architecture" width="800">
|
|
11
|
+
</p>
|
|
33
12
|
|
|
34
13
|
## Features
|
|
35
14
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
A --> |"theme"| F["Dark / Light Mode"]
|
|
43
|
-
A --> |"remote"| G["Multi-Machine<br/>Support"]
|
|
44
|
-
|
|
45
|
-
style A fill:#7c6aef,stroke:#5a4db8,color:#fff
|
|
46
|
-
style B fill:#60a5fa,stroke:#3b82f6,color:#000
|
|
47
|
-
style C fill:#3dd68c,stroke:#22a06b,color:#000
|
|
48
|
-
style D fill:#f5c542,stroke:#d4a72c,color:#000
|
|
49
|
-
style E fill:#ef4444,stroke:#dc2626,color:#fff
|
|
50
|
-
style F fill:#8b8fa3,stroke:#6b7280,color:#fff
|
|
51
|
-
style G fill:#a78bfa,stroke:#7c3aed,color:#000
|
|
52
|
-
```
|
|
15
|
+
- **Multi-Session Monitoring** — Real-time session status (idle / working / waiting)
|
|
16
|
+
- **Two-way Messaging** — Text + markdown + image exchange with Claude
|
|
17
|
+
- **Desktop Notifications** — Windows / macOS / Linux toast alerts
|
|
18
|
+
- **Token Auth** — Auto-generated secure access
|
|
19
|
+
- **Dark / Light Mode** — Theme toggle with persistence
|
|
20
|
+
- **Multi-Machine** — Remote hub access support
|
|
53
21
|
|
|
54
22
|
## Quick Start
|
|
55
23
|
|
|
@@ -84,22 +52,9 @@ Open `http://127.0.0.1:7900` in your browser.
|
|
|
84
52
|
|
|
85
53
|
## Message Flow
|
|
86
54
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
participant H as Hub Server
|
|
91
|
-
participant C as Channel Server
|
|
92
|
-
participant CC as Claude Code
|
|
93
|
-
|
|
94
|
-
D->>H: Send message
|
|
95
|
-
H->>C: Forward via WebSocket
|
|
96
|
-
C->>CC: MCP Channel notification
|
|
97
|
-
CC->>CC: Process & execute
|
|
98
|
-
CC->>C: Call reply tool
|
|
99
|
-
C->>H: Forward reply
|
|
100
|
-
H->>D: Display in chat
|
|
101
|
-
H->>H: Desktop notification
|
|
102
|
-
```
|
|
55
|
+
<p align="center">
|
|
56
|
+
<img src="docs/message-flow.svg" alt="Message Flow" width="700">
|
|
57
|
+
</p>
|
|
103
58
|
|
|
104
59
|
## Dashboard Layout
|
|
105
60
|
|
|
@@ -195,25 +150,9 @@ Config stored at `~/.claude-alarm/config.json`:
|
|
|
195
150
|
|
|
196
151
|
## Remote Access
|
|
197
152
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
HUB["Hub Server<br/>0.0.0.0:7900"]
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
subgraph "Remote PC"
|
|
205
|
-
RC["Claude Code"] --> RCS["Channel Server"]
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
subgraph "Browser (any device)"
|
|
209
|
-
DASH["Dashboard"]
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
RCS -->|"WS + token"| HUB
|
|
213
|
-
DASH -->|"HTTP + token"| HUB
|
|
214
|
-
|
|
215
|
-
style HUB fill:#7c6aef,stroke:#5a4db8,color:#fff
|
|
216
|
-
```
|
|
153
|
+
<p align="center">
|
|
154
|
+
<img src="docs/remote-access.svg" alt="Remote Access" width="600">
|
|
155
|
+
</p>
|
|
217
156
|
|
|
218
157
|
1. Set host to `0.0.0.0` in `~/.claude-alarm/config.json`
|
|
219
158
|
2. Open port 7900 in your firewall
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
--border: #2a2d3a;
|
|
12
12
|
--text: #e1e4ed;
|
|
13
13
|
--text-dim: #8b8fa3;
|
|
14
|
-
--accent: #
|
|
15
|
-
--accent-dim: #
|
|
14
|
+
--accent: #e0a86d;
|
|
15
|
+
--accent-dim: #c48d52;
|
|
16
16
|
--green: #3dd68c;
|
|
17
|
-
--yellow: #
|
|
17
|
+
--yellow: #f59e0b;
|
|
18
18
|
--red: #ef4444;
|
|
19
19
|
--blue: #60a5fa;
|
|
20
20
|
}
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
--border: #d1d5db;
|
|
25
25
|
--text: #1f2937;
|
|
26
26
|
--text-dim: #6b7280;
|
|
27
|
-
--accent: #
|
|
28
|
-
--accent-dim: #
|
|
27
|
+
--accent: #c48d52;
|
|
28
|
+
--accent-dim: #a87642;
|
|
29
29
|
--green: #22c55e;
|
|
30
|
-
--yellow: #
|
|
30
|
+
--yellow: #d97706;
|
|
31
31
|
--red: #ef4444;
|
|
32
32
|
--blue: #3b82f6;
|
|
33
33
|
}
|
|
@@ -142,6 +142,26 @@
|
|
|
142
142
|
text-align: center;
|
|
143
143
|
padding: 40px 20px;
|
|
144
144
|
}
|
|
145
|
+
.cmd-copy {
|
|
146
|
+
display: flex;
|
|
147
|
+
align-items: center;
|
|
148
|
+
background: var(--bg);
|
|
149
|
+
border: 1px solid var(--border);
|
|
150
|
+
border-radius: 6px;
|
|
151
|
+
padding: 6px 10px;
|
|
152
|
+
margin-top: 12px;
|
|
153
|
+
font-size: 11px;
|
|
154
|
+
font-family: monospace;
|
|
155
|
+
cursor: pointer;
|
|
156
|
+
transition: border-color 0.15s;
|
|
157
|
+
text-align: left;
|
|
158
|
+
gap: 6px;
|
|
159
|
+
}
|
|
160
|
+
.cmd-copy:hover { border-color: var(--accent); }
|
|
161
|
+
.cmd-copy .cmd-text { flex: 1; color: var(--text); word-break: break-all; }
|
|
162
|
+
.cmd-copy .cmd-icon { color: var(--text-dim); font-size: 14px; flex-shrink: 0; }
|
|
163
|
+
.cmd-copy.copied { border-color: var(--green); }
|
|
164
|
+
.cmd-copy.copied .cmd-icon { color: var(--green); }
|
|
145
165
|
|
|
146
166
|
/* Messages panel */
|
|
147
167
|
.messages-panel {
|
|
@@ -172,8 +192,8 @@
|
|
|
172
192
|
border: 1px solid var(--border);
|
|
173
193
|
}
|
|
174
194
|
.message.from-dashboard {
|
|
175
|
-
background: rgba(
|
|
176
|
-
border: 1px solid rgba(
|
|
195
|
+
background: rgba(224,168,109,0.12);
|
|
196
|
+
border: 1px solid rgba(224,168,109,0.25);
|
|
177
197
|
margin-left: auto;
|
|
178
198
|
}
|
|
179
199
|
.message-meta {
|
|
@@ -223,7 +243,7 @@
|
|
|
223
243
|
.drag-overlay {
|
|
224
244
|
position: absolute;
|
|
225
245
|
inset: 0;
|
|
226
|
-
background: rgba(
|
|
246
|
+
background: rgba(224,168,109,0.15);
|
|
227
247
|
border: 2px dashed var(--accent);
|
|
228
248
|
border-radius: 8px;
|
|
229
249
|
display: none;
|
|
@@ -580,7 +600,30 @@
|
|
|
580
600
|
const el = $('#sessionsList');
|
|
581
601
|
const ids = Object.keys(state.sessions);
|
|
582
602
|
if (!ids.length) {
|
|
583
|
-
el.innerHTML =
|
|
603
|
+
el.innerHTML = `<div class="no-sessions">No active sessions.<br>Start Claude Code with the channel:
|
|
604
|
+
<div class="cmd-copy" id="cmdCopy1" title="Click to copy">
|
|
605
|
+
<span class="cmd-text">claude --dangerously-load-development-channels server:claude-alarm</span>
|
|
606
|
+
<span class="cmd-icon">📋</span>
|
|
607
|
+
</div>
|
|
608
|
+
<div style="margin-top:8px;font-size:11px;color:var(--text-dim)">or with auto-approve:</div>
|
|
609
|
+
<div class="cmd-copy" id="cmdCopy2" title="Click to copy">
|
|
610
|
+
<span class="cmd-text">claude --dangerously-load-development-channels server:claude-alarm --dangerously-skip-permissions</span>
|
|
611
|
+
<span class="cmd-icon">📋</span>
|
|
612
|
+
</div>
|
|
613
|
+
</div>`;
|
|
614
|
+
el.querySelectorAll('.cmd-copy').forEach(btn => {
|
|
615
|
+
btn.addEventListener('click', () => {
|
|
616
|
+
const text = btn.querySelector('.cmd-text').textContent;
|
|
617
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
618
|
+
btn.classList.add('copied');
|
|
619
|
+
btn.querySelector('.cmd-icon').innerHTML = '✓';
|
|
620
|
+
setTimeout(() => {
|
|
621
|
+
btn.classList.remove('copied');
|
|
622
|
+
btn.querySelector('.cmd-icon').innerHTML = '📋';
|
|
623
|
+
}, 2000);
|
|
624
|
+
});
|
|
625
|
+
});
|
|
626
|
+
});
|
|
584
627
|
return;
|
|
585
628
|
}
|
|
586
629
|
el.innerHTML = ids.map(id => {
|
package/package.json
CHANGED
package/src/dashboard/index.html
CHANGED
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
--border: #2a2d3a;
|
|
12
12
|
--text: #e1e4ed;
|
|
13
13
|
--text-dim: #8b8fa3;
|
|
14
|
-
--accent: #
|
|
15
|
-
--accent-dim: #
|
|
14
|
+
--accent: #e0a86d;
|
|
15
|
+
--accent-dim: #c48d52;
|
|
16
16
|
--green: #3dd68c;
|
|
17
|
-
--yellow: #
|
|
17
|
+
--yellow: #f59e0b;
|
|
18
18
|
--red: #ef4444;
|
|
19
19
|
--blue: #60a5fa;
|
|
20
20
|
}
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
--border: #d1d5db;
|
|
25
25
|
--text: #1f2937;
|
|
26
26
|
--text-dim: #6b7280;
|
|
27
|
-
--accent: #
|
|
28
|
-
--accent-dim: #
|
|
27
|
+
--accent: #c48d52;
|
|
28
|
+
--accent-dim: #a87642;
|
|
29
29
|
--green: #22c55e;
|
|
30
|
-
--yellow: #
|
|
30
|
+
--yellow: #d97706;
|
|
31
31
|
--red: #ef4444;
|
|
32
32
|
--blue: #3b82f6;
|
|
33
33
|
}
|
|
@@ -142,6 +142,26 @@
|
|
|
142
142
|
text-align: center;
|
|
143
143
|
padding: 40px 20px;
|
|
144
144
|
}
|
|
145
|
+
.cmd-copy {
|
|
146
|
+
display: flex;
|
|
147
|
+
align-items: center;
|
|
148
|
+
background: var(--bg);
|
|
149
|
+
border: 1px solid var(--border);
|
|
150
|
+
border-radius: 6px;
|
|
151
|
+
padding: 6px 10px;
|
|
152
|
+
margin-top: 12px;
|
|
153
|
+
font-size: 11px;
|
|
154
|
+
font-family: monospace;
|
|
155
|
+
cursor: pointer;
|
|
156
|
+
transition: border-color 0.15s;
|
|
157
|
+
text-align: left;
|
|
158
|
+
gap: 6px;
|
|
159
|
+
}
|
|
160
|
+
.cmd-copy:hover { border-color: var(--accent); }
|
|
161
|
+
.cmd-copy .cmd-text { flex: 1; color: var(--text); word-break: break-all; }
|
|
162
|
+
.cmd-copy .cmd-icon { color: var(--text-dim); font-size: 14px; flex-shrink: 0; }
|
|
163
|
+
.cmd-copy.copied { border-color: var(--green); }
|
|
164
|
+
.cmd-copy.copied .cmd-icon { color: var(--green); }
|
|
145
165
|
|
|
146
166
|
/* Messages panel */
|
|
147
167
|
.messages-panel {
|
|
@@ -172,8 +192,8 @@
|
|
|
172
192
|
border: 1px solid var(--border);
|
|
173
193
|
}
|
|
174
194
|
.message.from-dashboard {
|
|
175
|
-
background: rgba(
|
|
176
|
-
border: 1px solid rgba(
|
|
195
|
+
background: rgba(224,168,109,0.12);
|
|
196
|
+
border: 1px solid rgba(224,168,109,0.25);
|
|
177
197
|
margin-left: auto;
|
|
178
198
|
}
|
|
179
199
|
.message-meta {
|
|
@@ -223,7 +243,7 @@
|
|
|
223
243
|
.drag-overlay {
|
|
224
244
|
position: absolute;
|
|
225
245
|
inset: 0;
|
|
226
|
-
background: rgba(
|
|
246
|
+
background: rgba(224,168,109,0.15);
|
|
227
247
|
border: 2px dashed var(--accent);
|
|
228
248
|
border-radius: 8px;
|
|
229
249
|
display: none;
|
|
@@ -580,7 +600,30 @@
|
|
|
580
600
|
const el = $('#sessionsList');
|
|
581
601
|
const ids = Object.keys(state.sessions);
|
|
582
602
|
if (!ids.length) {
|
|
583
|
-
el.innerHTML =
|
|
603
|
+
el.innerHTML = `<div class="no-sessions">No active sessions.<br>Start Claude Code with the channel:
|
|
604
|
+
<div class="cmd-copy" id="cmdCopy1" title="Click to copy">
|
|
605
|
+
<span class="cmd-text">claude --dangerously-load-development-channels server:claude-alarm</span>
|
|
606
|
+
<span class="cmd-icon">📋</span>
|
|
607
|
+
</div>
|
|
608
|
+
<div style="margin-top:8px;font-size:11px;color:var(--text-dim)">or with auto-approve:</div>
|
|
609
|
+
<div class="cmd-copy" id="cmdCopy2" title="Click to copy">
|
|
610
|
+
<span class="cmd-text">claude --dangerously-load-development-channels server:claude-alarm --dangerously-skip-permissions</span>
|
|
611
|
+
<span class="cmd-icon">📋</span>
|
|
612
|
+
</div>
|
|
613
|
+
</div>`;
|
|
614
|
+
el.querySelectorAll('.cmd-copy').forEach(btn => {
|
|
615
|
+
btn.addEventListener('click', () => {
|
|
616
|
+
const text = btn.querySelector('.cmd-text').textContent;
|
|
617
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
618
|
+
btn.classList.add('copied');
|
|
619
|
+
btn.querySelector('.cmd-icon').innerHTML = '✓';
|
|
620
|
+
setTimeout(() => {
|
|
621
|
+
btn.classList.remove('copied');
|
|
622
|
+
btn.querySelector('.cmd-icon').innerHTML = '📋';
|
|
623
|
+
}, 2000);
|
|
624
|
+
});
|
|
625
|
+
});
|
|
626
|
+
});
|
|
584
627
|
return;
|
|
585
628
|
}
|
|
586
629
|
el.innerHTML = ids.map(id => {
|