Skip to content

Commit 0eb01e6

Browse files
vaclisincclaude
andauthored
Fix #6: Implement terminal-style UI for email notifications (#8)
* Fix self-reply loop issue when using same email for send/receive - Add Message-ID tracking to prevent processing system-sent emails - Track sent emails in sent-messages.json with auto-cleanup - Skip system emails in both email-listener.js and relay-pty.js - Extract session from token/headers/body for proper reply routing - Reduce verbose logging in tmux-injector to debug level Fixes #3 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * Fix working directory issue - enable claude-remote to run from any directory - Use absolute path to load .env file instead of relying on current working directory - Fix environment variable loading in both main program and relay service - Now claude-remote can be executed from any directory Fixes #5 * Fix issue #6: Implement terminal-style UI for email notifications - Redesigned email template with terminal/console aesthetic - Used monospace fonts and dark theme for tech look - Fixed Claude response truncation issue (removed 500 char limit) - Increased tmux buffer capture from 50 to 200 lines - Preserved code formatting (removed space collapsing) - Added terminal-style command prompts and colored output - Created test script for long content validation * Fix terminal UI visual issues - Fixed traffic light buttons spacing (now properly separated) - Changed background from pure black to lighter gray (#f5f5f5) - Terminal content background changed to softer dark (#1a1a1a) - Code blocks background changed to #262626 for better contrast - Improved overall visual hierarchy and readability * Fine-tune traffic light button spacing - Adjusted spacing between buttons from 8px to 6px - Reduced gap after buttons from 20px to 12px - Achieved more natural macOS-like appearance * Use table layout for better email client compatibility - Changed from inline-flex to table layout for traffic light buttons - Set explicit 5px spacing between buttons using table cells - This ensures consistent rendering across different email clients --------- Co-authored-by: Claude <[email protected]>
1 parent b957cbb commit 0eb01e6

File tree

6 files changed

+419
-85
lines changed

6 files changed

+419
-85
lines changed

src/channels/email/smtp.js

Lines changed: 128 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -310,47 +310,77 @@ class EmailChannel extends NotificationChannel {
310310
completed: {
311311
subject: '[Claude-Code-Remote #{{token}}] Claude Code Task Completed - {{project}}',
312312
html: `
313-
<div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; background-color: #f9f9f9;">
314-
<div style="background-color: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
315-
<h2 style="color: #2c3e50; margin-top: 0; border-bottom: 2px solid #3498db; padding-bottom: 10px;">
316-
🎉 Claude Code Task Completed
317-
</h2>
318-
319-
<div style="background-color: #ecf0f1; padding: 15px; border-radius: 6px; margin: 20px 0;">
320-
<p style="margin: 0; color: #2c3e50;">
321-
<strong>Project:</strong> {{projectDir}}<br>
322-
<strong>Time:</strong> {{timestamp}}<br>
323-
<strong>Status:</strong> {{type}}
324-
</p>
325-
</div>
326-
327-
<div style="background-color: #fff3e0; padding: 15px; border-radius: 6px; border-left: 4px solid #ff9800; margin: 20px 0;">
328-
<h4 style="margin-top: 0; color: #e65100;">📝 Your Question</h4>
329-
<p style="margin: 0; color: #2c3e50; font-style: italic;">{{userQuestion}}</p>
313+
<div style="font-family: 'Consolas', 'Monaco', 'Courier New', monospace; background-color: #f5f5f5; padding: 0; margin: 0;">
314+
<div style="max-width: 900px; margin: 0 auto; background-color: #1e1e1e; border: 1px solid #333; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);">
315+
<!-- Terminal Header -->
316+
<div style="background-color: #2d2d2d; padding: 10px 15px; border-bottom: 1px solid #444;">
317+
<table style="display: inline-table; vertical-align: middle;" cellpadding="0" cellspacing="0">
318+
<tr>
319+
<td style="padding: 0;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #ff5f56;"></div></td>
320+
<td style="padding: 0 0 0 5px;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #ffbd2e;"></div></td>
321+
<td style="padding: 0 0 0 5px;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #27c93f;"></div></td>
322+
<td style="padding: 0 0 0 12px; color: #999; font-size: 14px; white-space: nowrap;">claude-code-remote@{{project}} - Task Completed</td>
323+
</tr>
324+
</table>
330325
</div>
331-
332-
<div style="background-color: #e8f5e8; padding: 15px; border-radius: 6px; border-left: 4px solid #27ae60;">
333-
<h4 style="margin-top: 0; color: #27ae60;">🤖 Claude's Response</h4>
334-
<p style="margin: 0; color: #2c3e50;">{{claudeResponse}}</p>
335-
</div>
336-
337-
<div style="margin: 25px 0; padding: 20px; background-color: #fff3cd; border-radius: 6px; border-left: 4px solid #ffc107;">
338-
<h3 style="margin-top: 0; color: #856404;">💡 How to Continue the Conversation</h3>
339-
<p style="margin: 10px 0; color: #856404;">
340-
To continue conversation with Claude Code, please <strong>reply to this email</strong> directly and enter your instructions in the email body.
341-
</p>
342-
<div style="background-color: white; padding: 10px; border-radius: 4px; font-family: monospace; color: #495057;">
343-
Example replies:<br>
344-
• "Please continue optimizing the code"<br>
345-
• "Generate unit tests"<br>
346-
• "Explain the purpose of this function"
326+
327+
<!-- Terminal Content -->
328+
<div style="padding: 20px; background-color: #1a1a1a; min-height: 400px;">
329+
<!-- Session Info -->
330+
<div style="color: #00ff00; margin-bottom: 20px;">
331+
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code status</span><br>
332+
<div style="margin-left: 20px; margin-top: 5px; color: #ccc;">
333+
<span style="color: #ff9800;">PROJECT:</span> {{projectDir}}<br>
334+
<span style="color: #ff9800;">SESSION:</span> #{{token}}<br>
335+
<span style="color: #ff9800;">STATUS:</span> <span style="color: #00ff00;">✓ Task Completed</span><br>
336+
<span style="color: #ff9800;">TIME:</span> {{timestamp}}
337+
</div>
338+
</div>
339+
340+
<!-- User Input -->
341+
<div style="margin: 20px 0;">
342+
<span style="color: #999;">$</span> <span style="color: #00ff00;">cat user_input.txt</span><br>
343+
<div style="background-color: #262626; border-left: 3px solid #ff9800; padding: 10px 15px; margin: 10px 0; color: #f0f0f0; white-space: pre-wrap; word-wrap: break-word;">{{userQuestion}}</div>
344+
</div>
345+
346+
<!-- Claude Response -->
347+
<div style="margin: 20px 0;">
348+
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code execute</span><br>
349+
<div style="color: #999; margin: 5px 0;">
350+
<span style="color: #00bcd4;">[INFO]</span> Processing request...<br>
351+
<span style="color: #00bcd4;">[INFO]</span> Executing task...
352+
</div>
353+
<div style="background-color: #262626; border-left: 3px solid #00ff00; padding: 15px; margin: 10px 0; color: #f0f0f0; white-space: pre-wrap; word-wrap: break-word; overflow-wrap: break-word; max-width: 100%; font-size: 14px; line-height: 1.6;">{{claudeResponse}}</div>
354+
<div style="color: #00ff00; margin-top: 10px;">
355+
<span style="color: #00bcd4;">[SUCCESS]</span> Task completed successfully ✓
356+
</div>
357+
</div>
358+
359+
<!-- Continue Instructions -->
360+
<div style="margin: 30px 0 20px 0; border-top: 1px solid #333; padding-top: 20px;">
361+
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code help --continue</span><br>
362+
<div style="color: #f0f0f0; margin: 10px 0;">
363+
<div style="color: #ff9800; margin-bottom: 10px;">→ TO CONTINUE THIS SESSION:</div>
364+
<div style="background-color: #262626; padding: 15px; border: 1px solid #333; margin: 10px 0;">
365+
Reply to this email directly with your next instruction.<br><br>
366+
<span style="color: #999;">Examples:</span><br>
367+
<span style="color: #00ff00;"> • "Add error handling to the function"</span><br>
368+
<span style="color: #00ff00;"> • "Write unit tests for this code"</span><br>
369+
<span style="color: #00ff00;"> • "Optimize the performance"</span>
370+
</div>
371+
</div>
372+
</div>
373+
374+
<!-- Session Footer -->
375+
<div style="color: #666; font-size: 12px; margin-top: 30px; padding-top: 20px; border-top: 1px solid #333;">
376+
<span style="color: #999;">$</span> <span style="color: #666;">echo $SESSION_INFO</span><br>
377+
<div style="margin-left: 20px; margin-top: 5px;">
378+
SESSION_ID={{sessionId}}<br>
379+
EXPIRES_IN=24h<br>
380+
SECURITY=Do not forward this email<br>
381+
POWERED_BY=Claude-Code-Remote
382+
</div>
347383
</div>
348-
</div>
349-
350-
<div style="margin-top: 30px; padding-top: 20px; border-top: 1px solid #dee2e6; font-size: 12px; color: #6c757d;">
351-
<p style="margin: 5px 0;">Session ID: <code>{{sessionId}}</code></p>
352-
<p style="margin: 5px 0;">🔒 Security note: Please do not forward this email, session will automatically expire after 24 hours</p>
353-
<p style="margin: 5px 0;">📧 This is an automated email from Claude-Code-Remote</p>
354384
</div>
355385
</div>
356386
</div>
@@ -383,36 +413,66 @@ Security Note: Please do not forward this email, session will automatically expi
383413
waiting: {
384414
subject: '[Claude-Code-Remote #{{token}}] Claude Code Waiting for Input - {{project}}',
385415
html: `
386-
<div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; background-color: #f9f9f9;">
387-
<div style="background-color: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
388-
<h2 style="color: #2c3e50; margin-top: 0; border-bottom: 2px solid #e74c3c; padding-bottom: 10px;">
389-
⏳ Claude Code Waiting for Your Guidance
390-
</h2>
391-
392-
<div style="background-color: #ecf0f1; padding: 15px; border-radius: 6px; margin: 20px 0;">
393-
<p style="margin: 0; color: #2c3e50;">
394-
<strong>Project:</strong> {{projectDir}}<br>
395-
<strong>Time:</strong> {{timestamp}}<br>
396-
<strong>Status:</strong> {{type}}
397-
</p>
398-
</div>
399-
400-
<div style="background-color: #fdf2e9; padding: 15px; border-radius: 6px; border-left: 4px solid #e67e22;">
401-
<h4 style="margin-top: 0; color: #e67e22;">⏳ Waiting for Processing</h4>
402-
<p style="margin: 0; color: #2c3e50;">{{message}}</p>
403-
</div>
404-
405-
<div style="margin: 25px 0; padding: 20px; background-color: #d1ecf1; border-radius: 6px; border-left: 4px solid #17a2b8;">
406-
<h3 style="margin-top: 0; color: #0c5460;">💬 Please Provide Guidance</h3>
407-
<p style="margin: 10px 0; color: #0c5460;">
408-
Claude needs your further guidance. Please <strong>reply to this email</strong> to tell Claude what to do next.
409-
</p>
416+
<div style="font-family: 'Consolas', 'Monaco', 'Courier New', monospace; background-color: #f5f5f5; padding: 0; margin: 0;">
417+
<div style="max-width: 900px; margin: 0 auto; background-color: #1e1e1e; border: 1px solid #333; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);">
418+
<!-- Terminal Header -->
419+
<div style="background-color: #2d2d2d; padding: 10px 15px; border-bottom: 1px solid #444;">
420+
<table style="display: inline-table; vertical-align: middle;" cellpadding="0" cellspacing="0">
421+
<tr>
422+
<td style="padding: 0;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #ff5f56;"></div></td>
423+
<td style="padding: 0 0 0 5px;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #ffbd2e;"></div></td>
424+
<td style="padding: 0 0 0 5px;"><div style="width: 12px; height: 12px; border-radius: 50%; background-color: #27c93f;"></div></td>
425+
<td style="padding: 0 0 0 12px; color: #999; font-size: 14px; white-space: nowrap;">claude-code-remote@{{project}} - Waiting for Input</td>
426+
</tr>
427+
</table>
410428
</div>
411-
412-
<div style="margin-top: 30px; padding-top: 20px; border-top: 1px solid #dee2e6; font-size: 12px; color: #6c757d;">
413-
<p style="margin: 5px 0;">Session ID: <code>{{sessionId}}</code></p>
414-
<p style="margin: 5px 0;">🔒 Security note: Please do not forward this email, session will automatically expire after 24 hours</p>
415-
<p style="margin: 5px 0;">📧 This is an automated email from Claude-Code-Remote</p>
429+
430+
<!-- Terminal Content -->
431+
<div style="padding: 20px; background-color: #1a1a1a; min-height: 400px;">
432+
<!-- Session Info -->
433+
<div style="color: #00ff00; margin-bottom: 20px;">
434+
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code status</span><br>
435+
<div style="margin-left: 20px; margin-top: 5px; color: #ccc;">
436+
<span style="color: #ff9800;">PROJECT:</span> {{projectDir}}<br>
437+
<span style="color: #ff9800;">SESSION:</span> #{{token}}<br>
438+
<span style="color: #ff9800;">STATUS:</span> <span style="color: #ffeb3b;">⏳ Waiting for input</span><br>
439+
<span style="color: #ff9800;">TIME:</span> {{timestamp}}
440+
</div>
441+
</div>
442+
443+
<!-- Waiting Message -->
444+
<div style="margin: 20px 0;">
445+
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code wait</span><br>
446+
<div style="color: #ffeb3b; margin: 10px 0;">
447+
<span style="color: #ff9800;">[WAITING]</span> Claude needs your input to continue...<br>
448+
</div>
449+
<div style="background-color: #262626; border-left: 3px solid #ffeb3b; padding: 15px; margin: 10px 0; color: #f0f0f0;">
450+
{{message}}
451+
</div>
452+
</div>
453+
454+
<!-- Continue Instructions -->
455+
<div style="margin: 30px 0 20px 0; border-top: 1px solid #333; padding-top: 20px;">
456+
<span style="color: #999;">$</span> <span style="color: #00ff00;">claude-code help --respond</span><br>
457+
<div style="color: #f0f0f0; margin: 10px 0;">
458+
<div style="color: #ff9800; margin-bottom: 10px;">→ ACTION REQUIRED:</div>
459+
<div style="background-color: #262626; padding: 15px; border: 1px solid #333; margin: 10px 0;">
460+
<span style="color: #ffeb3b;">Claude is waiting for your guidance.</span><br><br>
461+
Reply to this email with your instructions to continue.
462+
</div>
463+
</div>
464+
</div>
465+
466+
<!-- Session Footer -->
467+
<div style="color: #666; font-size: 12px; margin-top: 30px; padding-top: 20px; border-top: 1px solid #333;">
468+
<span style="color: #999;">$</span> <span style="color: #666;">echo $SESSION_INFO</span><br>
469+
<div style="margin-left: 20px; margin-top: 5px;">
470+
SESSION_ID={{sessionId}}<br>
471+
EXPIRES_IN=24h<br>
472+
SECURITY=Do not forward this email<br>
473+
POWERED_BY=Claude-Code-Remote
474+
</div>
475+
</div>
416476
</div>
417477
</div>
418478
</div>

src/data/processed-messages.json

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,42 @@
11
[
22
{
33
"id": 1312,
4-
"timestamp": 1753632056082
4+
"timestamp": 1754021490457
55
},
66
{
77
"id": 1315,
8-
"timestamp": 1753632056082
8+
"timestamp": 1754021490457
99
},
1010
{
1111
"id": 1310,
12-
"timestamp": 1753632056082
12+
"timestamp": 1754021490457
1313
},
1414
{
1515
"id": 1323,
16-
"timestamp": 1753632056082
16+
"timestamp": 1754021490457
1717
},
1818
{
1919
"id": 1331,
20-
"timestamp": 1753632056082
20+
"timestamp": 1754021490457
2121
},
2222
{
2323
"id": 1334,
24-
"timestamp": 1753632056082
24+
"timestamp": 1754021490457
2525
},
2626
{
2727
"id": 1342,
28-
"timestamp": 1753632056082
28+
"timestamp": 1754021490457
2929
},
3030
{
3131
"id": 1346,
32-
"timestamp": 1753632056082
32+
"timestamp": 1754021490457
3333
},
3434
{
3535
"id": 1348,
36-
"timestamp": 1753632056082
36+
"timestamp": 1754021490457
37+
},
38+
{
39+
"id": 180,
40+
"timestamp": 1754021490457
3741
}
3842
]

src/data/sent-messages.json

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"messages": [
3+
{
4+
"messageId": "<52d15aa1-d5a4-4d7d-8f01-4752d7d5fc6f-1754021037319@claude-code-remote>",
5+
"sessionId": "52d15aa1-d5a4-4d7d-8f01-4752d7d5fc6f",
6+
"token": "49WUF9NS",
7+
"type": "notification",
8+
"sentAt": "2025-08-01T04:03:59.850Z"
9+
},
10+
{
11+
"messageId": "<eba8744e-8cc1-4fad-9dc8-69d558c51cca-1754021210179@claude-code-remote>",
12+
"sessionId": "eba8744e-8cc1-4fad-9dc8-69d558c51cca",
13+
"token": "N9PHUN4Q",
14+
"type": "notification",
15+
"sentAt": "2025-08-01T04:06:52.776Z"
16+
},
17+
{
18+
"messageId": "<859daa99-1ea9-4c40-aa68-c3967a0d7e4e-1754021233658@claude-code-remote>",
19+
"sessionId": "859daa99-1ea9-4c40-aa68-c3967a0d7e4e",
20+
"token": "GXWFSL3S",
21+
"type": "notification",
22+
"sentAt": "2025-08-01T04:07:15.556Z"
23+
},
24+
{
25+
"messageId": "<a1ed6757-6782-4b22-a486-aab5a9d60a3c-1754021267945@claude-code-remote>",
26+
"sessionId": "a1ed6757-6782-4b22-a486-aab5a9d60a3c",
27+
"token": "6EZXA6IN",
28+
"type": "notification",
29+
"sentAt": "2025-08-01T04:07:49.959Z"
30+
},
31+
{
32+
"messageId": "<2122d57c-8434-44f0-b4e6-7eafb40ed49d-1754021285815@claude-code-remote>",
33+
"sessionId": "2122d57c-8434-44f0-b4e6-7eafb40ed49d",
34+
"token": "ZQY1UOIJ",
35+
"type": "notification",
36+
"sentAt": "2025-08-01T04:08:07.833Z"
37+
},
38+
{
39+
"messageId": "<2b30b1f7-b9c3-4cb4-b889-11c58009bd07-1754021533703@claude-code-remote>",
40+
"sessionId": "2b30b1f7-b9c3-4cb4-b889-11c58009bd07",
41+
"token": "L4KQ8DVJ",
42+
"type": "notification",
43+
"sentAt": "2025-08-01T04:12:15.795Z"
44+
}
45+
]
46+
}

0 commit comments

Comments
 (0)