vibe-monitor 1.0.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.
package/README.md ADDED
@@ -0,0 +1,281 @@
1
+ # Vibe Monitor Desktop App
2
+
3
+ Electron-based desktop app for real-time monitoring of AI coding assistants (Claude Code, Kiro IDE/CLI) with pixel art character.
4
+
5
+ ## Features
6
+
7
+ - **Frameless Window**: Clean floating design
8
+ - **Always on Top**: Always displayed above other windows
9
+ - **System Tray**: Quick control from the menu bar
10
+ - **HTTP API**: Easy integration with IDE hooks (Claude Code, Kiro)
11
+ - **Draggable**: Move the window to any position
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ cd desktop
17
+ npm install
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Run the App
23
+
24
+ ```bash
25
+ npm start
26
+ ```
27
+
28
+ ### Update Status via HTTP API
29
+
30
+ ```bash
31
+ # Change to working state
32
+ curl -X POST http://127.0.0.1:19280/status \
33
+ -H "Content-Type: application/json" \
34
+ -d '{"state":"working","tool":"Bash","project":"my-project","model":"opus","memory":"45%"}'
35
+
36
+ # Check current status
37
+ curl http://127.0.0.1:19280/status
38
+ ```
39
+
40
+ ### IDE Hooks Integration
41
+
42
+ #### Claude Code
43
+
44
+ Uses `hooks/vibe-monitor.sh` - see [main README](../README.md#claude-code-setup) for setup.
45
+
46
+ #### Kiro IDE
47
+
48
+ Copy hook files to `~/.kiro/hooks/` (or your project's `.kiro/hooks/` folder):
49
+
50
+ ```bash
51
+ # Global installation (recommended)
52
+ mkdir -p ~/.kiro/hooks
53
+ cp config/kiro/hooks/*.kiro.hook ~/.kiro/hooks/
54
+
55
+ # Or project-level installation
56
+ # cp config/kiro/hooks/*.kiro.hook your-project/.kiro/hooks/
57
+ ```
58
+
59
+ **Hook files:**
60
+ - `vibe-monitor-agent-spawn.kiro.hook` - Sends `start` on `agentSpawn`
61
+ - `vibe-monitor-prompt-submit.kiro.hook` - Sends `working` on `promptSubmit`
62
+ - `vibe-monitor-pre-tool-use.kiro.hook` - Sends `working` on `preToolUse`
63
+ - `vibe-monitor-agent-stop.kiro.hook` - Sends `idle` on `agentStop`
64
+
65
+ ## Supported IDEs
66
+
67
+ | IDE | Hook System | Status |
68
+ |-----|-------------|--------|
69
+ | **Claude Code** | Shell hooks via `settings.json` | ✅ Supported |
70
+ | **Kiro IDE** | `.kiro.hook` files in `.kiro/hooks/` | ✅ Supported |
71
+
72
+ ## States & Characters
73
+
74
+ See [main README](../README.md#state-display) for details on states, animations, and characters.
75
+
76
+ ## API
77
+
78
+ ### POST /status
79
+
80
+ Update status
81
+
82
+ ```json
83
+ {
84
+ "state": "working",
85
+ "event": "PreToolUse",
86
+ "tool": "Bash",
87
+ "project": "vibe-monitor",
88
+ "model": "opus",
89
+ "memory": "45%",
90
+ "character": "clawd"
91
+ }
92
+ ```
93
+
94
+ ### GET /status
95
+
96
+ Get current status
97
+
98
+ ```json
99
+ {
100
+ "state": "working",
101
+ "project": "vibe-monitor",
102
+ "tool": "Bash",
103
+ "model": "opus",
104
+ "memory": "45%"
105
+ }
106
+ ```
107
+
108
+ ### GET /health
109
+
110
+ Health check endpoint
111
+
112
+ ```json
113
+ {
114
+ "status": "ok"
115
+ }
116
+ ```
117
+
118
+ ### POST /show
119
+
120
+ Show window and position to top-right corner
121
+
122
+ ```json
123
+ {
124
+ "success": true
125
+ }
126
+ ```
127
+
128
+ ### GET /debug
129
+
130
+ Get display and window debug information (useful for troubleshooting positioning issues)
131
+
132
+ ```json
133
+ {
134
+ "primaryDisplay": {
135
+ "bounds": { "x": 0, "y": 0, "width": 1920, "height": 1080 },
136
+ "workArea": { "x": 0, "y": 0, "width": 1920, "height": 1040 },
137
+ "scaleFactor": 1
138
+ },
139
+ "window": { "x": 1748, "y": 0, "width": 172, "height": 348 },
140
+ "platform": "darwin"
141
+ }
142
+ ```
143
+
144
+ ## WSL (Windows Subsystem for Linux)
145
+
146
+ Running the Electron app on WSL requires WSLg (Windows 11) and additional dependencies.
147
+
148
+ ### Prerequisites
149
+
150
+ 1. **Windows 11** with WSLg support
151
+ 2. **Update WSL**:
152
+ ```bash
153
+ wsl --update
154
+ ```
155
+
156
+ ### Install Dependencies
157
+
158
+ Electron requires several system libraries that are not installed by default on WSL:
159
+
160
+ ```bash
161
+ # Ubuntu 24.04 (Noble) or later
162
+ sudo apt-get update && sudo apt-get install -y \
163
+ libasound2t64 \
164
+ libatk1.0-0 \
165
+ libatk-bridge2.0-0 \
166
+ libcups2 \
167
+ libdrm2 \
168
+ libgbm1 \
169
+ libgtk-3-0 \
170
+ libnss3 \
171
+ libxcomposite1 \
172
+ libxdamage1 \
173
+ libxfixes3 \
174
+ libxkbcommon0 \
175
+ libxrandr2 \
176
+ libxshmfence1 \
177
+ libglu1-mesa
178
+
179
+ # Ubuntu 22.04 (Jammy) or earlier
180
+ sudo apt-get update && sudo apt-get install -y \
181
+ libasound2 \
182
+ libatk1.0-0 \
183
+ libatk-bridge2.0-0 \
184
+ libcups2 \
185
+ libdrm2 \
186
+ libgbm1 \
187
+ libgtk-3-0 \
188
+ libnss3 \
189
+ libxcomposite1 \
190
+ libxdamage1 \
191
+ libxfixes3 \
192
+ libxkbcommon0 \
193
+ libxrandr2
194
+ ```
195
+
196
+ ### Run
197
+
198
+ ```bash
199
+ cd desktop
200
+ npm install
201
+ npm start
202
+ ```
203
+
204
+ ### Troubleshooting
205
+
206
+ **Error: `libasound.so.2: cannot open shared object file`**
207
+
208
+ Install the audio library:
209
+ ```bash
210
+ # Ubuntu 24.04+
211
+ sudo apt-get install -y libasound2t64
212
+
213
+ # Ubuntu 22.04 or earlier
214
+ sudo apt-get install -y libasound2
215
+ ```
216
+
217
+ **GPU process errors (can be ignored)**
218
+
219
+ WSL may show GPU-related warnings like:
220
+ ```
221
+ Exiting GPU process due to errors during initialization
222
+ ```
223
+ These warnings don't affect app functionality.
224
+
225
+ **Window not appearing**
226
+
227
+ Ensure WSLg is working:
228
+ ```bash
229
+ # Test with a simple GUI app
230
+ sudo apt-get install -y x11-apps
231
+ xclock
232
+ ```
233
+
234
+ If xclock doesn't appear, WSLg may need to be enabled or updated.
235
+
236
+ ## Build
237
+
238
+ Build for macOS:
239
+
240
+ ```bash
241
+ npm run build:mac
242
+ ```
243
+
244
+ Build DMG only:
245
+
246
+ ```bash
247
+ npm run build:dmg
248
+ ```
249
+
250
+ Build for Windows:
251
+
252
+ ```bash
253
+ npm run build:win
254
+ ```
255
+
256
+ Build for Linux:
257
+
258
+ ```bash
259
+ npm run build:linux
260
+ ```
261
+
262
+ Build for all platforms:
263
+
264
+ ```bash
265
+ npm run build:all
266
+ ```
267
+
268
+ ## Tray Menu
269
+
270
+ Click the system tray icon to:
271
+ - Check current status
272
+ - Manually change status
273
+ - Toggle Always on Top
274
+ - Show/Hide window
275
+ - Quit
276
+
277
+ ## Port
278
+
279
+ Default HTTP server port: `19280`
280
+
281
+ (Can be changed via `HTTP_PORT` constant in main.js)
@@ -0,0 +1,86 @@
1
+ const { createCanvas } = require('canvas');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ const COLOR_CLAUDE = '#D97757';
6
+ const COLOR_EYE = '#000000';
7
+ const COLOR_BG = '#FFCC00';
8
+
9
+ function drawIcon(size) {
10
+ const canvas = createCanvas(size, size);
11
+ const ctx = canvas.getContext('2d');
12
+ const scale = size / 64;
13
+
14
+ function rect(x, y, w, h, color) {
15
+ ctx.fillStyle = color;
16
+ ctx.fillRect(x * scale, y * scale, w * scale, h * scale);
17
+ }
18
+
19
+ // Round rectangle background
20
+ const radius = size * 0.15;
21
+ ctx.fillStyle = COLOR_BG;
22
+ ctx.beginPath();
23
+ ctx.roundRect(0, 0, size, size, radius);
24
+ ctx.fill();
25
+
26
+ // Character positioning
27
+ const offsetX = 0;
28
+ const offsetY = 4;
29
+
30
+ // Main body (52x36)
31
+ rect(6 + offsetX, 8 + offsetY, 52, 36, COLOR_CLAUDE);
32
+
33
+ // Arms (6x10)
34
+ rect(0 + offsetX, 22 + offsetY, 6, 10, COLOR_CLAUDE);
35
+ rect(58 + offsetX, 22 + offsetY, 6, 10, COLOR_CLAUDE);
36
+
37
+ // Legs (4 legs)
38
+ rect(10 + offsetX, 44 + offsetY, 6, 12, COLOR_CLAUDE);
39
+ rect(18 + offsetX, 44 + offsetY, 6, 12, COLOR_CLAUDE);
40
+ rect(40 + offsetX, 44 + offsetY, 6, 12, COLOR_CLAUDE);
41
+ rect(48 + offsetX, 44 + offsetY, 6, 12, COLOR_CLAUDE);
42
+
43
+ // Alert eyes (round)
44
+ const leftX = 14 + offsetX;
45
+ const rightX = 44 + offsetX;
46
+ const eyeY = 22 + offsetY;
47
+
48
+ // Left eye
49
+ rect(leftX + 1, eyeY, 4, 6, COLOR_EYE);
50
+ rect(leftX, eyeY + 1, 6, 4, COLOR_EYE);
51
+
52
+ // Right eye
53
+ rect(rightX + 1, eyeY, 4, 6, COLOR_EYE);
54
+ rect(rightX, eyeY + 1, 6, 4, COLOR_EYE);
55
+
56
+ // Question mark
57
+ const qx = 50 + offsetX;
58
+ const qy = 2 + offsetY;
59
+ rect(qx + 1, qy, 4, 2, COLOR_EYE);
60
+ rect(qx + 4, qy + 2, 2, 2, COLOR_EYE);
61
+ rect(qx + 2, qy + 4, 2, 2, COLOR_EYE);
62
+ rect(qx + 2, qy + 6, 2, 2, COLOR_EYE);
63
+ rect(qx + 2, qy + 10, 2, 2, COLOR_EYE);
64
+
65
+ return canvas;
66
+ }
67
+
68
+ // Generate icons
69
+ const sizes = [512, 256, 128, 64, 32, 16];
70
+ const assetsDir = __dirname;
71
+
72
+ console.log('Generating icons...');
73
+
74
+ sizes.forEach(size => {
75
+ const canvas = drawIcon(size);
76
+ const filename = size === 512 ? 'icon.png' : `icon-${size}.png`;
77
+ const filepath = path.join(assetsDir, filename);
78
+ const buffer = canvas.toBuffer('image/png');
79
+ fs.writeFileSync(filepath, buffer);
80
+ console.log(`Created: ${filename} (${size}x${size})`);
81
+ });
82
+
83
+ console.log('\nDone! PNG files created.');
84
+ console.log('\nNext steps:');
85
+ console.log('1. For Windows (.ico): convert icon-256.png icon-128.png icon-64.png icon-32.png icon-16.png icon.ico');
86
+ console.log('2. For macOS (.icns): See instructions in icon-generator.html');
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,221 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Vibe Monitor Icon Generator</title>
6
+ <style>
7
+ body {
8
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
9
+ background: #1a1a2e;
10
+ color: white;
11
+ padding: 40px;
12
+ text-align: center;
13
+ }
14
+ .container {
15
+ display: flex;
16
+ flex-wrap: wrap;
17
+ justify-content: center;
18
+ gap: 40px;
19
+ margin-top: 30px;
20
+ }
21
+ .icon-box {
22
+ background: #2d2d2d;
23
+ padding: 20px;
24
+ border-radius: 12px;
25
+ }
26
+ .icon-box h3 {
27
+ margin: 0 0 15px 0;
28
+ font-size: 14px;
29
+ color: #888;
30
+ }
31
+ canvas {
32
+ display: block;
33
+ margin: 0 auto 15px;
34
+ border-radius: 8px;
35
+ }
36
+ button {
37
+ background: #D97757;
38
+ color: white;
39
+ border: none;
40
+ padding: 10px 20px;
41
+ border-radius: 6px;
42
+ cursor: pointer;
43
+ font-size: 14px;
44
+ margin: 5px;
45
+ }
46
+ button:hover {
47
+ background: #c86a2f;
48
+ }
49
+ .info {
50
+ max-width: 600px;
51
+ margin: 30px auto;
52
+ text-align: left;
53
+ background: #2d2d2d;
54
+ padding: 20px;
55
+ border-radius: 12px;
56
+ }
57
+ .info h2 {
58
+ margin-top: 0;
59
+ color: #D97757;
60
+ }
61
+ .info code {
62
+ background: #1a1a1a;
63
+ padding: 2px 6px;
64
+ border-radius: 4px;
65
+ }
66
+ .info pre {
67
+ background: #1a1a1a;
68
+ padding: 10px;
69
+ border-radius: 6px;
70
+ overflow-x: auto;
71
+ }
72
+ </style>
73
+ </head>
74
+ <body>
75
+ <h1>Vibe Monitor Icon Generator</h1>
76
+ <p>Notification character icons for desktop app</p>
77
+
78
+ <div class="container">
79
+ <div class="icon-box">
80
+ <h3>512x512 (Linux)</h3>
81
+ <canvas id="icon512" width="512" height="512"></canvas>
82
+ <button onclick="download('icon512', 'icon.png')">Download PNG</button>
83
+ </div>
84
+ <div class="icon-box">
85
+ <h3>256x256 (Windows)</h3>
86
+ <canvas id="icon256" width="256" height="256"></canvas>
87
+ <button onclick="download('icon256', 'icon-256.png')">Download PNG</button>
88
+ </div>
89
+ <div class="icon-box">
90
+ <h3>128x128</h3>
91
+ <canvas id="icon128" width="128" height="128"></canvas>
92
+ <button onclick="download('icon128', 'icon-128.png')">Download PNG</button>
93
+ </div>
94
+ <div class="icon-box">
95
+ <h3>64x64</h3>
96
+ <canvas id="icon64" width="64" height="64"></canvas>
97
+ <button onclick="download('icon64', 'icon-64.png')">Download PNG</button>
98
+ </div>
99
+ <div class="icon-box">
100
+ <h3>32x32</h3>
101
+ <canvas id="icon32" width="32" height="32"></canvas>
102
+ <button onclick="download('icon32', 'icon-32.png')">Download PNG</button>
103
+ </div>
104
+ <div class="icon-box">
105
+ <h3>16x16</h3>
106
+ <canvas id="icon16" width="16" height="16"></canvas>
107
+ <button onclick="download('icon16', 'icon-16.png')">Download PNG</button>
108
+ </div>
109
+ </div>
110
+
111
+ <div class="info">
112
+ <h2>How to Create Icon Files</h2>
113
+ <p><strong>1. Download the PNG files</strong></p>
114
+ <p><strong>2. For Windows (.ico):</strong></p>
115
+ <pre>brew install imagemagick
116
+ convert icon-256.png icon-128.png icon-64.png icon-32.png icon-16.png icon.ico</pre>
117
+
118
+ <p><strong>3. For macOS (.icns):</strong></p>
119
+ <pre>mkdir icon.iconset
120
+ cp icon.png icon.iconset/icon_512x512.png
121
+ sips -z 256 256 icon.png --out icon.iconset/icon_256x256.png
122
+ sips -z 128 128 icon.png --out icon.iconset/icon_128x128.png
123
+ sips -z 64 64 icon.png --out icon.iconset/icon_64x64.png
124
+ sips -z 32 32 icon.png --out icon.iconset/icon_32x32.png
125
+ sips -z 16 16 icon.png --out icon.iconset/icon_16x16.png
126
+ iconutil -c icns icon.iconset</pre>
127
+
128
+ <p><strong>4. Place files in <code>desktop/assets/</code>:</strong></p>
129
+ <ul>
130
+ <li><code>icon.png</code> - 512x512 for Linux</li>
131
+ <li><code>icon.ico</code> - for Windows</li>
132
+ <li><code>icon.icns</code> - for macOS</li>
133
+ </ul>
134
+ </div>
135
+
136
+ <script>
137
+ const COLOR_CLAUDE = '#D97757';
138
+ const COLOR_EYE = '#000000';
139
+
140
+ // Base design is 64x64, scale up for larger sizes
141
+ function drawIcon(canvasId, size) {
142
+ const canvas = document.getElementById(canvasId);
143
+ const ctx = canvas.getContext('2d');
144
+ const scale = size / 64;
145
+
146
+ function rect(x, y, w, h, color) {
147
+ ctx.fillStyle = color;
148
+ ctx.fillRect(x * scale, y * scale, w * scale, h * scale);
149
+ }
150
+
151
+ // Clear with transparent background
152
+ ctx.clearRect(0, 0, size, size);
153
+
154
+ // Round rectangle background (optional - for rounded icon look)
155
+ const radius = size * 0.15;
156
+ ctx.fillStyle = '#FFCC00';
157
+ ctx.beginPath();
158
+ ctx.roundRect(0, 0, size, size, radius);
159
+ ctx.fill();
160
+
161
+ // Character body - centered in 64x64 space
162
+ // Original positions adjusted for centering
163
+ const offsetX = 0;
164
+ const offsetY = 4;
165
+
166
+ // Main body (52x36 at position 6,8)
167
+ rect(6 + offsetX, 8 + offsetY, 52, 36, COLOR_CLAUDE);
168
+
169
+ // Arms (6x10)
170
+ rect(0 + offsetX, 22 + offsetY, 6, 10, COLOR_CLAUDE); // Left
171
+ rect(58 + offsetX, 22 + offsetY, 6, 10, COLOR_CLAUDE); // Right
172
+
173
+ // Legs (4 legs)
174
+ rect(10 + offsetX, 44 + offsetY, 6, 12, COLOR_CLAUDE); // Left outer
175
+ rect(18 + offsetX, 44 + offsetY, 6, 12, COLOR_CLAUDE); // Left inner
176
+ rect(40 + offsetX, 44 + offsetY, 6, 12, COLOR_CLAUDE); // Right inner
177
+ rect(48 + offsetX, 44 + offsetY, 6, 12, COLOR_CLAUDE); // Right outer
178
+
179
+ // Alert eyes (round)
180
+ const leftX = 14 + offsetX;
181
+ const rightX = 44 + offsetX;
182
+ const eyeY = 22 + offsetY;
183
+
184
+ // Left eye (circle approximation)
185
+ rect(leftX + 1, eyeY, 4, 6, COLOR_EYE);
186
+ rect(leftX, eyeY + 1, 6, 4, COLOR_EYE);
187
+
188
+ // Right eye (circle approximation)
189
+ rect(rightX + 1, eyeY, 4, 6, COLOR_EYE);
190
+ rect(rightX, eyeY + 1, 6, 4, COLOR_EYE);
191
+
192
+ // Question mark above head
193
+ const qx = 50 + offsetX;
194
+ const qy = 2 + offsetY;
195
+ rect(qx + 1, qy, 4, 2, COLOR_EYE); // Top curve
196
+ rect(qx + 4, qy + 2, 2, 2, COLOR_EYE); // Right side
197
+ rect(qx + 2, qy + 4, 2, 2, COLOR_EYE); // Middle
198
+ rect(qx + 2, qy + 6, 2, 2, COLOR_EYE); // Lower middle
199
+ rect(qx + 2, qy + 10, 2, 2, COLOR_EYE); // Dot
200
+ }
201
+
202
+ function download(canvasId, filename) {
203
+ const canvas = document.getElementById(canvasId);
204
+ const link = document.createElement('a');
205
+ link.download = filename;
206
+ link.href = canvas.toDataURL('image/png');
207
+ link.click();
208
+ }
209
+
210
+ // Draw all icons
211
+ window.onload = function() {
212
+ drawIcon('icon512', 512);
213
+ drawIcon('icon256', 256);
214
+ drawIcon('icon128', 128);
215
+ drawIcon('icon64', 64);
216
+ drawIcon('icon32', 32);
217
+ drawIcon('icon16', 16);
218
+ };
219
+ </script>
220
+ </body>
221
+ </html>
Binary file
Binary file
Binary file
package/bin/cli.js ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawn } = require('child_process');
4
+ const path = require('path');
5
+
6
+ const electron = require('electron');
7
+ const appPath = path.join(__dirname, '..');
8
+
9
+ spawn(electron, [appPath], {
10
+ stdio: 'inherit'
11
+ });
package/index.html ADDED
@@ -0,0 +1,56 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Vibe Monitor</title>
7
+ <link rel="stylesheet" href="../shared/styles.css">
8
+ <link rel="stylesheet" href="styles.css">
9
+ </head>
10
+ <body>
11
+ <!-- Draggable Title Bar -->
12
+ <div class="title-bar">
13
+ <div class="title-bar-buttons">
14
+ <button class="title-bar-btn btn-close" onclick="window.electronAPI.closeWindow()"></button>
15
+ <button class="title-bar-btn btn-minimize" onclick="window.electronAPI.minimizeWindow()"></button>
16
+ </div>
17
+ <span class="title-text">VibeMon</span>
18
+ <div style="width: 20px;"></div>
19
+ </div>
20
+
21
+ <!-- Display -->
22
+ <div class="device-frame">
23
+ <div class="display" id="display">
24
+ <canvas id="character-canvas" width="128" height="128"></canvas>
25
+ <div class="status-text" id="status-text">Ready</div>
26
+ <div class="loading-dots" id="loading-dots">
27
+ <div class="dot dim"></div>
28
+ <div class="dot dim"></div>
29
+ <div class="dot dim"></div>
30
+ <div class="dot dim"></div>
31
+ </div>
32
+ <div class="info-text project-text">
33
+ <span class="info-label"><span class="emoji-icon">📂 </span><canvas class="pixel-icon" id="icon-project" width="8" height="8"></canvas></span>
34
+ <span class="info-value" id="project-value">-</span>
35
+ </div>
36
+ <div class="info-text tool-text" id="tool-line">
37
+ <span class="info-label"><span class="emoji-icon">🛠️ </span><canvas class="pixel-icon" id="icon-tool" width="8" height="8"></canvas></span>
38
+ <span class="info-value" id="tool-value">-</span>
39
+ </div>
40
+ <div class="info-text model-text" id="model-line">
41
+ <span class="info-label"><span class="emoji-icon">🤖 </span><canvas class="pixel-icon" id="icon-model" width="8" height="8"></canvas></span>
42
+ <span class="info-value" id="model-value">-</span>
43
+ </div>
44
+ <div class="info-text memory-text" id="memory-line">
45
+ <span class="info-label"><span class="emoji-icon">🧠 </span><canvas class="pixel-icon" id="icon-memory" width="8" height="8"></canvas></span>
46
+ <span class="info-value" id="memory-value">-</span>
47
+ </div>
48
+ <div class="memory-bar-container" id="memory-bar-container">
49
+ <div class="memory-bar" id="memory-bar"></div>
50
+ </div>
51
+ </div>
52
+ </div>
53
+
54
+ <script type="module" src="renderer.js"></script>
55
+ </body>
56
+ </html>