pyre-cli 1.3.0 → 1.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.
- package/README.md +209 -16
- package/dist/index.js +735 -332
- package/package.json +5 -2
- package/parity.md +542 -0
- package/src/formatters/index.ts +17 -0
- package/src/formatters/output.ts +137 -0
- package/src/formatters/render.ts +468 -0
- package/src/formatters/themes.ts +115 -0
- package/src/formatters/types.ts +58 -0
- package/src/history.ts +115 -0
- package/src/index.ts +81 -0
- package/src/live/export.ts +73 -0
- package/src/live/index.ts +16 -0
- package/src/live/input.ts +311 -0
- package/src/live/render.ts +142 -0
- package/src/live/state.ts +83 -0
- package/src/live/types.ts +23 -0
- package/src/monitors/collectors.ts +484 -0
- package/src/monitors/index.ts +14 -0
- package/src/monitors/run.ts +18 -0
- package/src/monitors/smc.ts +107 -0
- package/src/monitors/types.ts +107 -0
- package/src/pyre_img +0 -0
- package/src/sparkline.ts +34 -0
- package/src/splash.ts +102 -0
- package/tsconfig.json +19 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pyre-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "CLI Mac monitoring tool: temps, system stats, live dashboard, and export",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -9,9 +9,12 @@
|
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|
|
12
|
+
"src",
|
|
13
|
+
"tsconfig.json",
|
|
12
14
|
"install.sh",
|
|
13
15
|
"Formula/pyre.rb",
|
|
14
|
-
"README.md"
|
|
16
|
+
"README.md",
|
|
17
|
+
"parity.md"
|
|
15
18
|
],
|
|
16
19
|
"scripts": {
|
|
17
20
|
"build": "tsup src/index.ts --format esm --clean",
|
package/parity.md
ADDED
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
btop is a **resource monitor and process manager** designed as a modern, interactive replacement for tools like `top` and `htop`. It combines a rich terminal UI with system telemetry, process control, graphs, and customization.
|
|
2
|
+
|
|
3
|
+
Below is a comprehensive feature list.
|
|
4
|
+
|
|
5
|
+
# btop Feature List
|
|
6
|
+
|
|
7
|
+
## 1. User Interface (TUI) Features
|
|
8
|
+
|
|
9
|
+
### Modern Terminal Dashboard
|
|
10
|
+
|
|
11
|
+
* Full-screen terminal interface
|
|
12
|
+
* Multi-panel dashboard layout
|
|
13
|
+
* Real-time animated graphs
|
|
14
|
+
* Color-coded status indicators
|
|
15
|
+
* Smooth transitions and updates
|
|
16
|
+
* Mouse interaction support
|
|
17
|
+
* Keyboard-driven navigation
|
|
18
|
+
* Responsive layout scaling
|
|
19
|
+
* Unicode/ASCII rendering support
|
|
20
|
+
* True-color terminal support
|
|
21
|
+
|
|
22
|
+
### Main Dashboard Panels
|
|
23
|
+
|
|
24
|
+
#### CPU Panel
|
|
25
|
+
|
|
26
|
+
Displays:
|
|
27
|
+
|
|
28
|
+
* Total CPU utilization
|
|
29
|
+
* Per-core utilization
|
|
30
|
+
* Core frequency
|
|
31
|
+
* CPU temperature (when available)
|
|
32
|
+
* CPU load averages
|
|
33
|
+
* Process activity
|
|
34
|
+
* CPU graph history
|
|
35
|
+
|
|
36
|
+
Visualizations:
|
|
37
|
+
|
|
38
|
+
* Per-core bar graphs
|
|
39
|
+
* Historical usage graphs
|
|
40
|
+
* Frequency indicators
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
#### Memory Panel
|
|
45
|
+
|
|
46
|
+
Shows:
|
|
47
|
+
|
|
48
|
+
* Total RAM
|
|
49
|
+
* Used RAM
|
|
50
|
+
* Available RAM
|
|
51
|
+
* Cached memory
|
|
52
|
+
* Buffers
|
|
53
|
+
* Memory percentage
|
|
54
|
+
* Swap usage
|
|
55
|
+
|
|
56
|
+
Visualizations:
|
|
57
|
+
|
|
58
|
+
* RAM usage bars
|
|
59
|
+
* Swap graphs
|
|
60
|
+
* Memory history
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
#### Disk Panel
|
|
65
|
+
|
|
66
|
+
Displays:
|
|
67
|
+
|
|
68
|
+
* Disk usage
|
|
69
|
+
* Mounted drives
|
|
70
|
+
* Used/free space
|
|
71
|
+
* Read/write activity
|
|
72
|
+
* I/O speed
|
|
73
|
+
* Storage utilization
|
|
74
|
+
|
|
75
|
+
Metrics:
|
|
76
|
+
|
|
77
|
+
* Read throughput
|
|
78
|
+
* Write throughput
|
|
79
|
+
* Disk activity graphs
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
#### Network Panel
|
|
84
|
+
|
|
85
|
+
Shows:
|
|
86
|
+
|
|
87
|
+
* Upload speed
|
|
88
|
+
* Download speed
|
|
89
|
+
* Total transferred data
|
|
90
|
+
* Network interface activity
|
|
91
|
+
|
|
92
|
+
Metrics:
|
|
93
|
+
|
|
94
|
+
* RX bandwidth
|
|
95
|
+
* TX bandwidth
|
|
96
|
+
* Packet activity
|
|
97
|
+
* Network history graphs
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
#### Process Panel
|
|
102
|
+
|
|
103
|
+
Displays:
|
|
104
|
+
|
|
105
|
+
* Running processes
|
|
106
|
+
* Process IDs
|
|
107
|
+
* CPU usage
|
|
108
|
+
* Memory usage
|
|
109
|
+
* User
|
|
110
|
+
* Command name
|
|
111
|
+
* Process state
|
|
112
|
+
* Threads
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
# 2. Process Management Features
|
|
117
|
+
|
|
118
|
+
## Process Viewer
|
|
119
|
+
|
|
120
|
+
Supports:
|
|
121
|
+
|
|
122
|
+
* Real-time process list
|
|
123
|
+
* Sorting processes
|
|
124
|
+
* Searching processes
|
|
125
|
+
* Filtering processes
|
|
126
|
+
* Process tree view
|
|
127
|
+
* Parent/child relationships
|
|
128
|
+
* Process details
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Process Sorting
|
|
133
|
+
|
|
134
|
+
Sort by:
|
|
135
|
+
|
|
136
|
+
* CPU usage
|
|
137
|
+
* Memory usage
|
|
138
|
+
* PID
|
|
139
|
+
* User
|
|
140
|
+
* Command
|
|
141
|
+
* Process state
|
|
142
|
+
* Threads
|
|
143
|
+
* Runtime
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Process Actions
|
|
148
|
+
|
|
149
|
+
Can:
|
|
150
|
+
|
|
151
|
+
* Kill processes
|
|
152
|
+
* Send signals
|
|
153
|
+
* Terminate applications
|
|
154
|
+
* Force kill stuck processes
|
|
155
|
+
|
|
156
|
+
Supported signals include:
|
|
157
|
+
|
|
158
|
+
* SIGTERM
|
|
159
|
+
* SIGKILL
|
|
160
|
+
* SIGINT
|
|
161
|
+
* SIGHUP
|
|
162
|
+
* SIGSTOP
|
|
163
|
+
* SIGCONT
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
# 3. Real-Time Monitoring
|
|
168
|
+
|
|
169
|
+
## Live Updates
|
|
170
|
+
|
|
171
|
+
Configurable:
|
|
172
|
+
|
|
173
|
+
* Update interval
|
|
174
|
+
* Graph refresh speed
|
|
175
|
+
* Process refresh rate
|
|
176
|
+
* Animation speed
|
|
177
|
+
|
|
178
|
+
Default behavior:
|
|
179
|
+
|
|
180
|
+
* Continuous monitoring
|
|
181
|
+
* Low latency updates
|
|
182
|
+
* Minimal CPU overhead
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Historical Graphs
|
|
187
|
+
|
|
188
|
+
Provides:
|
|
189
|
+
|
|
190
|
+
* CPU history
|
|
191
|
+
* RAM history
|
|
192
|
+
* Network history
|
|
193
|
+
* Disk I/O history
|
|
194
|
+
* Temperature history
|
|
195
|
+
|
|
196
|
+
Graph features:
|
|
197
|
+
|
|
198
|
+
* Scrolling history
|
|
199
|
+
* Adjustable time window
|
|
200
|
+
* Smooth rendering
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
# 4. Hardware Monitoring
|
|
205
|
+
|
|
206
|
+
## CPU Monitoring
|
|
207
|
+
|
|
208
|
+
Tracks:
|
|
209
|
+
|
|
210
|
+
* CPU load
|
|
211
|
+
* Per-thread activity
|
|
212
|
+
* Core utilization
|
|
213
|
+
* Frequency scaling
|
|
214
|
+
* Load averages
|
|
215
|
+
* CPU temperature (hardware dependent)
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Temperature Monitoring
|
|
220
|
+
|
|
221
|
+
Supports:
|
|
222
|
+
|
|
223
|
+
* CPU temperatures
|
|
224
|
+
* Sensor readings
|
|
225
|
+
* Thermal states
|
|
226
|
+
|
|
227
|
+
Availability depends on:
|
|
228
|
+
|
|
229
|
+
* OS
|
|
230
|
+
* Hardware sensors
|
|
231
|
+
* Permissions
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Battery Monitoring (Laptop)
|
|
236
|
+
|
|
237
|
+
Displays:
|
|
238
|
+
|
|
239
|
+
* Battery percentage
|
|
240
|
+
* Charging state
|
|
241
|
+
* Battery time remaining
|
|
242
|
+
* Power consumption
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
# 5. macOS-Specific Features
|
|
247
|
+
|
|
248
|
+
On macOS, btop can display:
|
|
249
|
+
|
|
250
|
+
* Apple Silicon CPU information
|
|
251
|
+
* Intel CPU information
|
|
252
|
+
* Memory pressure data
|
|
253
|
+
* Battery state
|
|
254
|
+
* Disk statistics
|
|
255
|
+
* Network statistics
|
|
256
|
+
* Process information
|
|
257
|
+
|
|
258
|
+
Supports:
|
|
259
|
+
|
|
260
|
+
* Intel Macs
|
|
261
|
+
* Apple Silicon Macs (M1/M2/M3/M4)
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
# 6. GPU Monitoring
|
|
266
|
+
|
|
267
|
+
GPU support:
|
|
268
|
+
|
|
269
|
+
Displays (when available):
|
|
270
|
+
|
|
271
|
+
* GPU utilization
|
|
272
|
+
* GPU memory usage
|
|
273
|
+
* GPU temperature
|
|
274
|
+
* GPU processes
|
|
275
|
+
|
|
276
|
+
Support depends on:
|
|
277
|
+
|
|
278
|
+
* Operating system APIs
|
|
279
|
+
* GPU vendor
|
|
280
|
+
* Drivers
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
# 7. Configuration Features
|
|
285
|
+
|
|
286
|
+
## Fully Configurable UI
|
|
287
|
+
|
|
288
|
+
Customize:
|
|
289
|
+
|
|
290
|
+
* Colors
|
|
291
|
+
* Themes
|
|
292
|
+
* Layout
|
|
293
|
+
* Display order
|
|
294
|
+
* Graph styles
|
|
295
|
+
* Update speed
|
|
296
|
+
* Background style
|
|
297
|
+
|
|
298
|
+
Configuration file:
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
~/.config/btop/btop.conf
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Theme System
|
|
307
|
+
|
|
308
|
+
Supports:
|
|
309
|
+
|
|
310
|
+
* Built-in themes
|
|
311
|
+
* Custom themes
|
|
312
|
+
* User-created color schemes
|
|
313
|
+
|
|
314
|
+
Theme file:
|
|
315
|
+
|
|
316
|
+
```
|
|
317
|
+
~/.config/btop/themes/
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Examples:
|
|
321
|
+
|
|
322
|
+
* Dracula style
|
|
323
|
+
* Nord style
|
|
324
|
+
* Monokai style
|
|
325
|
+
* Solarized style
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Layout Customization
|
|
330
|
+
|
|
331
|
+
Adjust:
|
|
332
|
+
|
|
333
|
+
* Panel sizes
|
|
334
|
+
* Visible modules
|
|
335
|
+
* Graph types
|
|
336
|
+
* Information density
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
# 8. Keyboard Controls
|
|
341
|
+
|
|
342
|
+
Common shortcuts:
|
|
343
|
+
|
|
344
|
+
| Key | Action |
|
|
345
|
+
| ----- | ---------------- |
|
|
346
|
+
| `Esc` | Close menu |
|
|
347
|
+
| `m` | Main menu |
|
|
348
|
+
| `p` | Process menu |
|
|
349
|
+
| `f` | Filter processes |
|
|
350
|
+
| `k` | Kill process |
|
|
351
|
+
| `r` | Reverse sorting |
|
|
352
|
+
| `c` | Sort by CPU |
|
|
353
|
+
| `m` | Sort by memory |
|
|
354
|
+
| `q` | Quit |
|
|
355
|
+
|
|
356
|
+
Navigation:
|
|
357
|
+
|
|
358
|
+
* Arrow keys
|
|
359
|
+
* Page Up/Down
|
|
360
|
+
* Mouse clicks
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
# 9. Technical Features
|
|
365
|
+
|
|
366
|
+
## Cross Platform
|
|
367
|
+
|
|
368
|
+
Supported:
|
|
369
|
+
|
|
370
|
+
* macOS
|
|
371
|
+
* Linux
|
|
372
|
+
* FreeBSD
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Implementation
|
|
377
|
+
|
|
378
|
+
Written in:
|
|
379
|
+
|
|
380
|
+
* C++
|
|
381
|
+
|
|
382
|
+
Uses:
|
|
383
|
+
|
|
384
|
+
* Native OS APIs
|
|
385
|
+
* Terminal rendering
|
|
386
|
+
* Low-level system calls
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Performance
|
|
391
|
+
|
|
392
|
+
Designed for:
|
|
393
|
+
|
|
394
|
+
* Low CPU usage
|
|
395
|
+
* Low memory usage
|
|
396
|
+
* Fast startup
|
|
397
|
+
* Efficient polling
|
|
398
|
+
|
|
399
|
+
Typical resource usage:
|
|
400
|
+
|
|
401
|
+
* Small RAM footprint
|
|
402
|
+
* Minimal background overhead
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
# 10. Terminal Compatibility
|
|
407
|
+
|
|
408
|
+
Works with:
|
|
409
|
+
|
|
410
|
+
* Terminal.app
|
|
411
|
+
* iTerm2
|
|
412
|
+
* Ghostty
|
|
413
|
+
* Alacritty
|
|
414
|
+
* Kitty
|
|
415
|
+
* WezTerm
|
|
416
|
+
* tmux
|
|
417
|
+
* SSH sessions
|
|
418
|
+
|
|
419
|
+
Supports:
|
|
420
|
+
|
|
421
|
+
* ANSI colors
|
|
422
|
+
* Unicode
|
|
423
|
+
* True color
|
|
424
|
+
* 256-color terminals
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
# 11. Accessibility Features
|
|
429
|
+
|
|
430
|
+
Includes:
|
|
431
|
+
|
|
432
|
+
* High contrast themes
|
|
433
|
+
* Adjustable colors
|
|
434
|
+
* Keyboard-only operation
|
|
435
|
+
* Configurable information density
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
# 12. Advanced Features
|
|
440
|
+
|
|
441
|
+
## Mouse Support
|
|
442
|
+
|
|
443
|
+
Allows:
|
|
444
|
+
|
|
445
|
+
* Clicking panels
|
|
446
|
+
* Selecting processes
|
|
447
|
+
* Opening menus
|
|
448
|
+
* Changing sorting
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
## Vim-Like Navigation
|
|
453
|
+
|
|
454
|
+
Supports:
|
|
455
|
+
|
|
456
|
+
* Keyboard navigation
|
|
457
|
+
* Fast movement
|
|
458
|
+
* Terminal workflow
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
## Process Tree
|
|
463
|
+
|
|
464
|
+
Shows:
|
|
465
|
+
|
|
466
|
+
```
|
|
467
|
+
launchd
|
|
468
|
+
├── Terminal
|
|
469
|
+
│ └── btop
|
|
470
|
+
└── Chrome
|
|
471
|
+
├── Renderer
|
|
472
|
+
└── GPU Process
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
## Secure Operation
|
|
478
|
+
|
|
479
|
+
Features:
|
|
480
|
+
|
|
481
|
+
* Does not require root for normal usage
|
|
482
|
+
* Uses read-only system metrics by default
|
|
483
|
+
* Only requires elevated privileges for certain actions
|
|
484
|
+
|
|
485
|
+
---
|
|
486
|
+
|
|
487
|
+
# 13. Developer / Sysadmin Features
|
|
488
|
+
|
|
489
|
+
Useful for:
|
|
490
|
+
|
|
491
|
+
### Debugging
|
|
492
|
+
|
|
493
|
+
* CPU spikes
|
|
494
|
+
* Memory leaks
|
|
495
|
+
* Zombie processes
|
|
496
|
+
* Runaway applications
|
|
497
|
+
|
|
498
|
+
### Servers
|
|
499
|
+
|
|
500
|
+
* SSH monitoring
|
|
501
|
+
* Lightweight dashboards
|
|
502
|
+
* Resource tracking
|
|
503
|
+
|
|
504
|
+
### Development
|
|
505
|
+
|
|
506
|
+
* Compiler monitoring
|
|
507
|
+
* Docker workload observation
|
|
508
|
+
* Build performance tracking
|
|
509
|
+
|
|
510
|
+
---
|
|
511
|
+
|
|
512
|
+
# 14. What btop Does NOT Do
|
|
513
|
+
|
|
514
|
+
Compared to macOS Activity Monitor, btop does **not** provide:
|
|
515
|
+
|
|
516
|
+
* App energy impact scoring
|
|
517
|
+
* Detailed GPU history graphs on all Macs
|
|
518
|
+
* Network connection inspector
|
|
519
|
+
* Application sandbox details
|
|
520
|
+
* Launch agent management
|
|
521
|
+
* System extension management
|
|
522
|
+
* Full disk/file activity tracing
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
# Feature Summary
|
|
527
|
+
|
|
528
|
+
| Category | Features |
|
|
529
|
+
| ------------- | ----------------------------------- |
|
|
530
|
+
| UI | Animated TUI, graphs, colors, mouse |
|
|
531
|
+
| CPU | Cores, load, frequency, temperature |
|
|
532
|
+
| Memory | RAM, cache, swap |
|
|
533
|
+
| Disk | Usage, I/O, throughput |
|
|
534
|
+
| Network | RX/TX monitoring |
|
|
535
|
+
| Processes | Search, sort, kill, tree |
|
|
536
|
+
| Hardware | Sensors, battery, temperature |
|
|
537
|
+
| Customization | Themes, layouts, configs |
|
|
538
|
+
| Platforms | macOS/Linux/FreeBSD |
|
|
539
|
+
| Performance | Lightweight, real-time |
|
|
540
|
+
| Terminal | Ghostty/iTerm/Kitty compatible |
|
|
541
|
+
|
|
542
|
+
**In short:** btop is essentially a **terminal-native Activity Monitor** with a dashboard-first design, closer to a "cyberpunk system HUD" than the classic `top` experience.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pyre formatters module.
|
|
3
|
+
*
|
|
4
|
+
* Provides dashboard rendering (`formatTable`), data export
|
|
5
|
+
* (`formatJson`, `formatCsv`, `formatTsv`), and graph
|
|
6
|
+
* rendering (`formatGraphs`) for the live dashboard.
|
|
7
|
+
*
|
|
8
|
+
* The module is organised into four sub-files:
|
|
9
|
+
* - `types.ts` — public-facing type definitions
|
|
10
|
+
* - `themes.ts` — colour theme definitions
|
|
11
|
+
* - `render.ts` — dashboard layout, cards, tables, and the main `formatTable`
|
|
12
|
+
* - `output.ts` — JSON/CSV/TSV export and sparkline graph rendering
|
|
13
|
+
*/
|
|
14
|
+
export { formatTable, clampWidth, gridColumns, thermalColor, capacityColor } from './render.js';
|
|
15
|
+
export { formatJson, formatCsv, formatTsv, formatGraphs } from './output.js';
|
|
16
|
+
export type { ThemeName, ThemeColors, VisibleItems, TableOptions } from './types.js';
|
|
17
|
+
export { THEMES } from './themes.js';
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data-export and graph-rendering helpers.
|
|
3
|
+
*
|
|
4
|
+
* Provides JSON, CSV, and TSV serialisation of a
|
|
5
|
+
* {@link StatsData} snapshot, as well as sparkline-graph
|
|
6
|
+
* rendering for the live dashboard.
|
|
7
|
+
*/
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import { sparkline } from '../sparkline.js';
|
|
10
|
+
import type { History } from '../history.js';
|
|
11
|
+
import type { StatsData } from './types.js';
|
|
12
|
+
import { THEMES, type ThemeName } from './themes.js';
|
|
13
|
+
import { formatBytes, celsiusToFahrenheit, formatTemp } from './render.js';
|
|
14
|
+
import { panel } from './render.js';
|
|
15
|
+
|
|
16
|
+
export function formatJson(data: StatsData): string {
|
|
17
|
+
return JSON.stringify(data, null, 2);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function formatCsv(data: StatsData): string {
|
|
21
|
+
const rows: string[][] = [
|
|
22
|
+
['property', 'key', 'value'],
|
|
23
|
+
['cpu', 'brand', data.cpu.brand],
|
|
24
|
+
['cpu', 'usage', String(data.cpu.usage)],
|
|
25
|
+
['cpu', 'loadAvg_1m', String(data.cpu.loadAvg[0])],
|
|
26
|
+
['cpu', 'loadAvg_5m', String(data.cpu.loadAvg[1])],
|
|
27
|
+
['cpu', 'loadAvg_15m', String(data.cpu.loadAvg[2])],
|
|
28
|
+
['memory', 'total', String(data.memory.total)],
|
|
29
|
+
['memory', 'used', String(data.memory.used)],
|
|
30
|
+
['memory', 'usagePercent', String(data.memory.usagePercent)],
|
|
31
|
+
['memory', 'swapUsed', String(data.memory.swapUsed)],
|
|
32
|
+
['memory', 'swapTotal', String(data.memory.swapTotal)],
|
|
33
|
+
['thermal', 'state', data.thermal.state],
|
|
34
|
+
['thermal', 'cpuTempC', data.thermal.temperatures?.cpu_die ? String(data.thermal.temperatures.cpu_die) : ''],
|
|
35
|
+
[
|
|
36
|
+
'thermal',
|
|
37
|
+
'cpuTempF',
|
|
38
|
+
data.thermal.temperatures?.cpu_die != null ? String(celsiusToFahrenheit(data.thermal.temperatures.cpu_die)) : '',
|
|
39
|
+
],
|
|
40
|
+
['network', 'rxBytes', String(data.network.rxBytes)],
|
|
41
|
+
['network', 'txBytes', String(data.network.txBytes)],
|
|
42
|
+
['battery', 'level', data.battery ? String(data.battery.level) : ''],
|
|
43
|
+
['battery', 'powerSource', data.battery ? data.battery.powerSource : ''],
|
|
44
|
+
['battery', 'condition', data.battery?.condition ?? ''],
|
|
45
|
+
['battery', 'maxCapacityPercent', data.battery?.maxCapacityPercent !== undefined ? String(data.battery.maxCapacityPercent) : ''],
|
|
46
|
+
['battery', 'cycles', data.battery?.cycles !== undefined ? String(data.battery.cycles) : ''],
|
|
47
|
+
['power', 'cpuWatts', data.power?.cpuWatts !== undefined ? String(data.power.cpuWatts) : ''],
|
|
48
|
+
['power', 'gpuWatts', data.power?.gpuWatts !== undefined ? String(data.power.gpuWatts) : ''],
|
|
49
|
+
['power', 'combinedWatts', data.power?.combinedWatts !== undefined ? String(data.power.combinedWatts) : ''],
|
|
50
|
+
['system', 'hostname', data.header.hostname],
|
|
51
|
+
['system', 'uptime', data.header.uptime],
|
|
52
|
+
['system', 'timestamp', data.timestamp],
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
if (data.gpu) {
|
|
56
|
+
rows.push(['gpu', 'model', data.gpu.model]);
|
|
57
|
+
rows.push(['gpu', 'memory', String(data.gpu.memory)]);
|
|
58
|
+
rows.push(['gpu', 'utilization', String(data.gpu.utilization)]);
|
|
59
|
+
if (data.gpu.temperature) rows.push(['gpu', 'tempC', String(data.gpu.temperature)]);
|
|
60
|
+
rows.push(['gpu', 'processes', String(data.gpu.processes)]);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
for (const p of data.processes) {
|
|
64
|
+
rows.push(['process', `pid=${p.pid}`, `${p.pid}`]);
|
|
65
|
+
rows.push(['process', `ppid=${p.pid}`, String(p.ppid)]);
|
|
66
|
+
rows.push(['process', `user=${p.pid}`, p.user]);
|
|
67
|
+
rows.push(['process', `cpu=${p.pid}`, String(p.cpu)]);
|
|
68
|
+
rows.push(['process', `mem=${p.pid}`, String(p.mem)]);
|
|
69
|
+
rows.push(['process', `state=${p.pid}`, p.state]);
|
|
70
|
+
rows.push(['process', `threads=${p.pid}`, String(p.threads)]);
|
|
71
|
+
rows.push(['process', `runtime=${p.pid}`, String(p.runtime)]);
|
|
72
|
+
rows.push(['process', `command=${p.pid}`, p.command]);
|
|
73
|
+
}
|
|
74
|
+
return rows.map(r => r.map(item => `"${String(item).replace(/"/g, '""')}"`).join(',')).join('\n');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function formatTsv(data: StatsData): string {
|
|
78
|
+
return formatCsv(data).split('\n').map(r => r.split(',').join('\t')).join('\n');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function formatGraphs(history: History, width = 80, themeName: ThemeName = 'default', graphMode: 'spark' | 'bar' = 'spark'): string {
|
|
82
|
+
const theme = THEMES[themeName] || THEMES.default;
|
|
83
|
+
const contentWidth = width - 4;
|
|
84
|
+
const sampleCount = history.cpuUsage.length;
|
|
85
|
+
const sparkWidth = Math.max(10, contentWidth - 28);
|
|
86
|
+
|
|
87
|
+
const lines: string[] = [];
|
|
88
|
+
lines.push(graphRow('CPU %', history.cpuUsage, { min: 0, max: 100 }, v => `${v.toFixed(0)}%`, sparkWidth, graphMode));
|
|
89
|
+
lines.push(graphRow('Mem %', history.memUsage, { min: 0, max: 100 }, v => `${v.toFixed(0)}%`, sparkWidth, graphMode));
|
|
90
|
+
lines.push(
|
|
91
|
+
graphRow('Temp', history.temp, {}, formatTemp, sparkWidth, 'no sensor access (needs sudo powermetrics)', graphMode)
|
|
92
|
+
);
|
|
93
|
+
lines.push(graphRow('Net RX/s', history.netRxRate, {}, v => `${formatBytes(v)}/s`, sparkWidth, graphMode));
|
|
94
|
+
lines.push(graphRow('Net TX/s', history.netTxRate, {}, v => `${formatBytes(v)}/s`, sparkWidth, graphMode));
|
|
95
|
+
|
|
96
|
+
const title = `Graphs · mode:${graphMode} · last ${sampleCount} sample${sampleCount === 1 ? '' : 's'}`;
|
|
97
|
+
return panel(title, lines, width, theme.graphs, theme.border).join('\n');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function graphRow(
|
|
101
|
+
label: string,
|
|
102
|
+
values: number[],
|
|
103
|
+
bounds: { min?: number; max?: number },
|
|
104
|
+
fmt: (v: number) => string,
|
|
105
|
+
sparkWidth = 40,
|
|
106
|
+
emptyMessage = 'collecting data...',
|
|
107
|
+
mode: 'spark' | 'bar' = 'spark'
|
|
108
|
+
): string {
|
|
109
|
+
if (!values.length) {
|
|
110
|
+
return `${chalk.dim(label.padEnd(10))} ${chalk.dim(emptyMessage)}`;
|
|
111
|
+
}
|
|
112
|
+
const visible = values.slice(-sparkWidth);
|
|
113
|
+
const spark = mode === 'spark' ? sparkline(visible, bounds) : barGraph(visible, bounds, sparkWidth);
|
|
114
|
+
const current = values[values.length - 1];
|
|
115
|
+
|
|
116
|
+
let color = chalk.cyan;
|
|
117
|
+
if (bounds.min !== undefined && bounds.max !== undefined) {
|
|
118
|
+
const pct = ((current - bounds.min) / (bounds.max - bounds.min || 1)) * 100;
|
|
119
|
+
color = pct > 90 ? chalk.red : pct > 70 ? chalk.yellow : chalk.green;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return `${chalk.dim(label.padEnd(10))}${color(spark)} ${chalk.bold(fmt(current))}`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function barGraph(values: number[], bounds: { min?: number; max?: number }, width: number): string {
|
|
126
|
+
const min = bounds.min ?? Math.min(...values);
|
|
127
|
+
const max = bounds.max ?? Math.max(...values);
|
|
128
|
+
const range = max - min || 1;
|
|
129
|
+
return values.map(v => {
|
|
130
|
+
const pct = (v - min) / range;
|
|
131
|
+
if (pct > 0.8) return '█';
|
|
132
|
+
if (pct > 0.6) return '▇';
|
|
133
|
+
if (pct > 0.4) return '▆';
|
|
134
|
+
if (pct > 0.2) return '▄';
|
|
135
|
+
return ' ';
|
|
136
|
+
}).join('');
|
|
137
|
+
}
|