pyre-cli 8.2.0 → 9.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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  run
3
- } from "./chunk-GLH7EKAX.js";
3
+ } from "./chunk-FH5WDJBF.js";
4
4
 
5
5
  // src/brewHealth.ts
6
6
  import chalk from "chalk";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  run
3
- } from "./chunk-GLH7EKAX.js";
3
+ } from "./chunk-FH5WDJBF.js";
4
4
 
5
5
  // src/monitors/collectors.ts
6
6
  import chalk from "chalk";
@@ -15,7 +15,8 @@ async function getSmcMetrics() {
15
15
  try {
16
16
  const pm = (await run(
17
17
  "sudo -n powermetrics --samplers smc,cpu_power -n 1 --format text 2>/dev/null",
18
- ""
18
+ "",
19
+ 2e3
19
20
  )).trim();
20
21
  if (pm) {
21
22
  const cpuTemp = pm.match(/CPU die temperature:\s*([\d.]+)/i);
@@ -71,13 +72,9 @@ async function getSmcMetrics() {
71
72
  }
72
73
  }
73
74
  if (result.temps["cpu_die"] === void 0) {
74
- let loadUsage = 0;
75
- try {
76
- const top = await run("top -l 1 -n 0 2>/dev/null", "");
77
- const m = top.match(/CPU usage:\s*[\d.]+\%\s*user,\s*[\d.]+\%\s*sys,\s*([\d.]+)\%\s*idle/);
78
- if (m) loadUsage = Math.max(0, 100 - parseFloat(m[1]));
79
- } catch {
80
- }
75
+ const loadAvg = (await import("os")).loadavg();
76
+ const ncpus = (await import("os")).cpus().length || 1;
77
+ const loadUsage = Math.min(100, loadAvg[0] / ncpus * 100);
81
78
  const estCpu = Math.round((38 + loadUsage * 0.42) * 10) / 10;
82
79
  result.temps["cpu_die"] = estCpu;
83
80
  if (result.temps["gpu_die"] === void 0) {
@@ -98,6 +95,7 @@ function parseSuffix(s) {
98
95
  var SP_TTL_MS = 1e4;
99
96
  var NETSTAT_TTL_MS = 1e3;
100
97
  var prevCpuTimes = null;
98
+ var prevCpuTotal = { total: 0, idle: 0, ts: 0 };
101
99
  var ROUTE_TTL_MS = 5e3;
102
100
  var SYSCTL_TTL_MS = 6e4;
103
101
  var spGpuCache = null;
@@ -239,7 +237,7 @@ async function collectGpu(detailed) {
239
237
  if (spGpuCache && now - spGpuCache.ts < SP_TTL_MS) {
240
238
  spRaw = spGpuCache.raw;
241
239
  } else {
242
- spRaw = (await run("system_profiler SPDisplaysDataType 2>/dev/null")).trim();
240
+ spRaw = (await run("system_profiler SPDisplaysDataType 2>/dev/null", "", 3e3)).trim();
243
241
  spGpuCache = { raw: spRaw, ts: now };
244
242
  }
245
243
  let model = "Unknown";
@@ -376,12 +374,21 @@ async function collectCpu() {
376
374
  }
377
375
  let usage = 0;
378
376
  try {
379
- const top = (await run("top -l 1 -n 0")).trim();
380
- const cpuLine = top.match(/CPU usage:\s*[\d.]+%\s*user,\s*[\d.]+%\s*sys,\s*([\d.]+)%\s*idle/);
381
- if (cpuLine) {
382
- const idle = parseFloat(cpuLine[1]);
383
- usage = Math.round(100 - idle);
377
+ const cpus = os.cpus();
378
+ let totalNow = 0;
379
+ let idleNow = 0;
380
+ for (const cpu of cpus) {
381
+ totalNow += cpu.times.user + cpu.times.nice + cpu.times.sys + cpu.times.idle + cpu.times.irq;
382
+ idleNow += cpu.times.idle;
383
+ }
384
+ if (prevCpuTotal.ts > 0) {
385
+ const totalDelta = totalNow - prevCpuTotal.total;
386
+ const idleDelta = idleNow - prevCpuTotal.idle;
387
+ if (totalDelta > 0) {
388
+ usage = Math.round((totalDelta - idleDelta) / totalDelta * 100);
389
+ }
384
390
  }
391
+ prevCpuTotal = { total: totalNow, idle: idleNow, ts: Date.now() };
385
392
  } catch {
386
393
  }
387
394
  const loadAvgStr = (await run("sysctl -n vm.loadavg", "0.00 0.00 0.00")).trim();
@@ -485,7 +492,7 @@ async function getDiskIoRates() {
485
492
  return { readBytesSec: cachedDiskIo.readBytesSec, writeBytesSec: cachedDiskIo.writeBytesSec };
486
493
  }
487
494
  try {
488
- const raw = (await run("iostat -d -c 2 1 2", "")).trim();
495
+ const raw = (await run("iostat -d -c 2 1 2", "", 3e3)).trim();
489
496
  const blocks = raw.split(/\n\s*\n/).filter(Boolean);
490
497
  const targetBlock = blocks.length > 1 ? blocks[1] : blocks[0];
491
498
  if (targetBlock) {
@@ -547,7 +554,7 @@ async function collectBattery() {
547
554
  if (spBatteryCache && now - spBatteryCache.ts < SP_TTL_MS) {
548
555
  battInfo = spBatteryCache.raw;
549
556
  } else {
550
- battInfo = (await run("system_profiler SPPowerDataType 2>/dev/null")).trim();
557
+ battInfo = (await run("system_profiler SPPowerDataType 2>/dev/null", "", 3e3)).trim();
551
558
  spBatteryCache = { raw: battInfo, ts: now };
552
559
  }
553
560
  const cycleMatch = battInfo.match(/Cycle Count:\s+(\d+)/);
@@ -723,7 +730,7 @@ async function collectPackets() {
723
730
  }
724
731
  let connections = 0;
725
732
  try {
726
- const tcpConns = (await run("netstat -an | grep ESTABLISHED | wc -l", "0")).trim();
733
+ const tcpConns = (await run("netstat -an | grep ESTABLISHED | wc -l", "0", 2e3)).trim();
727
734
  connections = parseInt(tcpConns) || 0;
728
735
  } catch {
729
736
  connections = 0;
@@ -731,7 +738,7 @@ async function collectPackets() {
731
738
  let topProcesses = [];
732
739
  let allProcesses = [];
733
740
  try {
734
- const lsof = (await run("lsof -i -n -P 2>/dev/null | tail -n +2 | awk '{print $1, $2}' | sort | uniq -c | sort -rn", "")).trim();
741
+ const lsof = (await run("lsof -i -n -P 2>/dev/null | tail -n +2 | awk '{print $1, $2}' | sort | uniq -c | sort -rn", "", 2e3)).trim();
735
742
  const lsofLines = lsof.split("\n");
736
743
  topProcesses = lsofLines.map((line) => {
737
744
  const parts = line.trim().split(/\s+/);
@@ -2,7 +2,7 @@
2
2
  import { exec } from "child_process";
3
3
  import { promisify } from "util";
4
4
  var execAsync = promisify(exec);
5
- async function run(cmd, fallback = "", timeout = 5e3) {
5
+ async function run(cmd, fallback = "", timeout = 3e3) {
6
6
  try {
7
7
  return (await execAsync(cmd, { encoding: "utf8", timeout })).stdout.trim();
8
8
  } catch {
@@ -13,8 +13,8 @@ import {
13
13
  collectThermal,
14
14
  getDisplayInfo,
15
15
  getTimeMachineStatus
16
- } from "./chunk-KBKXU2ZV.js";
17
- import "./chunk-GLH7EKAX.js";
16
+ } from "./chunk-EQZCK2VC.js";
17
+ import "./chunk-FH5WDJBF.js";
18
18
  export {
19
19
  collectAll,
20
20
  collectBattery,
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-RVGKEJXT.js";
5
5
  import {
6
6
  run
7
- } from "./chunk-GLH7EKAX.js";
7
+ } from "./chunk-FH5WDJBF.js";
8
8
 
9
9
  // src/doctor.ts
10
10
  import chalk from "chalk";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  run
3
- } from "./chunk-GLH7EKAX.js";
3
+ } from "./chunk-FH5WDJBF.js";
4
4
 
5
5
  // src/extensions.ts
6
6
  import chalk from "chalk";
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  collectAll
4
- } from "./chunk-KBKXU2ZV.js";
4
+ } from "./chunk-EQZCK2VC.js";
5
5
  import {
6
6
  CONFIG_FILE,
7
7
  readConfig,
8
8
  writeConfig
9
9
  } from "./chunk-RVGKEJXT.js";
10
- import "./chunk-GLH7EKAX.js";
10
+ import "./chunk-FH5WDJBF.js";
11
11
 
12
12
  // src/index.ts
13
13
  import fs8 from "fs";
@@ -2697,8 +2697,7 @@ function graphsCacheParams() {
2697
2697
  }
2698
2698
  function processRowBudget() {
2699
2699
  let overlayRows = 0;
2700
- if (state.inputMode === "customizer") overlayRows = state.CUSTOMIZER_OPTIONS.length + 3;
2701
- else if (state.inputMode === "signal") overlayRows = 6;
2700
+ if (state.inputMode === "signal") overlayRows = 6;
2702
2701
  else if (state.inputMode === "filter" || state.inputMode === "kill" || state.inputMode === "p2p") overlayRows = 3;
2703
2702
  if (state.activePanel === "process") {
2704
2703
  return Math.max(10, state.termHeight - 12 - overlayRows);
@@ -2854,14 +2853,20 @@ function render() {
2854
2853
  const footerHeight = 3;
2855
2854
  const targetBodyHeight = Math.max(1, state.termHeight - footerHeight);
2856
2855
  if (state.inputMode === "customizer") {
2857
- const preOverlayCount = bodyLines.length;
2858
- const availableForOverlay = targetBodyHeight - preOverlayCount;
2859
2856
  const totalItems = state.CUSTOMIZER_OPTIONS.length;
2860
2857
  const headerLines = 1;
2861
- const blankLines = availableForOverlay >= 2 ? 1 : 0;
2862
- const maxVisibleItems = Math.max(0, availableForOverlay - headerLines - blankLines);
2858
+ const blankLines = 1;
2859
+ const idealOverlayHeight = totalItems + headerLines + blankLines;
2860
+ const minOverlayHeight = Math.min(10 + headerLines + blankLines, Math.floor(targetBodyHeight / 2));
2861
+ const overlayHeight = Math.min(idealOverlayHeight, Math.max(minOverlayHeight, Math.floor(targetBodyHeight * 0.6)));
2862
+ const maxBodyForTable = Math.max(3, targetBodyHeight - overlayHeight);
2863
+ if (bodyLines.length > maxBodyForTable) {
2864
+ bodyLines.length = maxBodyForTable;
2865
+ }
2866
+ const availableForOverlay = targetBodyHeight - bodyLines.length;
2867
+ const maxVisibleItems = Math.max(1, availableForOverlay - headerLines - blankLines);
2863
2868
  const scrollOffset = totalItems > maxVisibleItems ? Math.max(0, Math.min(state.customizerIndex, totalItems - maxVisibleItems)) : 0;
2864
- if (blankLines > 0) bodyLines.push("");
2869
+ bodyLines.push("");
2865
2870
  bodyLines.push(...renderCustomizerOverlay(scrollOffset, maxVisibleItems).split("\n"));
2866
2871
  } else if (state.inputMode === "filter") {
2867
2872
  bodyLines.push(chalk4.cyan(` Filter processes: ${state.inputBuffer}_`));
@@ -4591,7 +4596,7 @@ async function showSplash(config3) {
4591
4596
  process.stdin.setRawMode(true);
4592
4597
  process.stdin.resume();
4593
4598
  process.stdin.on("data", onEnter);
4594
- setTimeout(onEnter, 5e3);
4599
+ setTimeout(onEnter, 1500);
4595
4600
  });
4596
4601
  }
4597
4602
 
@@ -4861,12 +4866,12 @@ async function main() {
4861
4866
  return;
4862
4867
  }
4863
4868
  if (cmd === "extensions") {
4864
- const { printExtensionsReport } = await import("./extensions-QCFSVCL5.js");
4869
+ const { printExtensionsReport } = await import("./extensions-DVA5YLGH.js");
4865
4870
  await printExtensionsReport();
4866
4871
  return;
4867
4872
  }
4868
4873
  if (cmd === "brew") {
4869
- const { printBrewHealthReport } = await import("./brewHealth-6NE37NAU.js");
4874
+ const { printBrewHealthReport } = await import("./brewHealth-F2BXF5M6.js");
4870
4875
  await printBrewHealthReport();
4871
4876
  return;
4872
4877
  }
@@ -4969,7 +4974,7 @@ async function main() {
4969
4974
  return;
4970
4975
  }
4971
4976
  if (cmd === "doctor") {
4972
- const { runDoctor, printDoctorReport } = await import("./doctor-LJQAABZ4.js");
4977
+ const { runDoctor, printDoctorReport } = await import("./doctor-L6FZYA7F.js");
4973
4978
  const checks = await runDoctor();
4974
4979
  printDoctorReport(checks);
4975
4980
  return;
@@ -5234,7 +5239,7 @@ async function runP2PConnect() {
5234
5239
  }
5235
5240
  async function runInfoCommand() {
5236
5241
  const data = await collectAll({ detailed: true });
5237
- const { getDisplayInfo, getTimeMachineStatus } = await import("./collectors-4VYRJVRO.js");
5242
+ const { getDisplayInfo, getTimeMachineStatus } = await import("./collectors-KNEN4YJD.js");
5238
5243
  const displays = await getDisplayInfo();
5239
5244
  const tmStatus = await getTimeMachineStatus();
5240
5245
  const lines = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pyre-cli",
3
- "version": "8.2.0",
3
+ "version": "9.0.0",
4
4
  "description": "CLI Mac monitoring tool: temps, system stats, live dashboard, packet monitor, battery predictor, export",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -68,8 +68,7 @@ function graphsCacheParams(): string {
68
68
 
69
69
  function processRowBudget(): number {
70
70
  let overlayRows = 0;
71
- if (state.inputMode === 'customizer') overlayRows = state.CUSTOMIZER_OPTIONS.length + 3;
72
- else if (state.inputMode === 'signal') overlayRows = 6;
71
+ if (state.inputMode === 'signal') overlayRows = 6;
73
72
  else if (state.inputMode === 'filter' || state.inputMode === 'kill' || state.inputMode === 'p2p') overlayRows = 3;
74
73
 
75
74
  if (state.activePanel === 'process') {
@@ -265,17 +264,26 @@ function render() {
265
264
  const targetBodyHeight = Math.max(1, state.termHeight - footerHeight);
266
265
 
267
266
  if (state.inputMode === 'customizer') {
268
- const preOverlayCount = bodyLines.length;
269
- const availableForOverlay = targetBodyHeight - preOverlayCount;
270
267
  const totalItems = state.CUSTOMIZER_OPTIONS.length;
271
- const headerLines = 1;
272
- const blankLines = availableForOverlay >= 2 ? 1 : 0;
273
- const maxVisibleItems = Math.max(0, availableForOverlay - headerLines - blankLines);
268
+ const headerLines = 1; // the "UI CUSTOMIZER" header
269
+ const blankLines = 1; // blank separator line
270
+ // Reserve a fixed height for the customizer: show all items if they fit,
271
+ // otherwise guarantee at least 10 visible items (or half the screen).
272
+ const idealOverlayHeight = totalItems + headerLines + blankLines;
273
+ const minOverlayHeight = Math.min(10 + headerLines + blankLines, Math.floor(targetBodyHeight / 2));
274
+ const overlayHeight = Math.min(idealOverlayHeight, Math.max(minOverlayHeight, Math.floor(targetBodyHeight * 0.6)));
275
+ // Truncate table body to make room for the customizer overlay
276
+ const maxBodyForTable = Math.max(3, targetBodyHeight - overlayHeight);
277
+ if (bodyLines.length > maxBodyForTable) {
278
+ bodyLines.length = maxBodyForTable;
279
+ }
280
+ const availableForOverlay = targetBodyHeight - bodyLines.length;
281
+ const maxVisibleItems = Math.max(1, availableForOverlay - headerLines - blankLines);
274
282
  const scrollOffset = totalItems > maxVisibleItems
275
283
  ? Math.max(0, Math.min(state.customizerIndex, totalItems - maxVisibleItems))
276
284
  : 0;
277
285
 
278
- if (blankLines > 0) bodyLines.push('');
286
+ bodyLines.push('');
279
287
  bodyLines.push(...renderCustomizerOverlay(scrollOffset, maxVisibleItems).split('\n'));
280
288
  } else if (state.inputMode === 'filter') {
281
289
  bodyLines.push(chalk.cyan(` Filter processes: ${state.inputBuffer}_`));
@@ -20,6 +20,7 @@ import type { StatsData, CpuData, MemoryData, ThermalData, BatteryData, PowerDat
20
20
  const SP_TTL_MS = 10_000;
21
21
  const NETSTAT_TTL_MS = 1000;
22
22
  let prevCpuTimes: { total: number; idle: number }[] | null = null;
23
+ let prevCpuTotal = { total: 0, idle: 0, ts: 0 };
23
24
  const ROUTE_TTL_MS = 5_000;
24
25
  const SYSCTL_TTL_MS = 60_000;
25
26
 
@@ -236,7 +237,7 @@ export async function collectPower(): Promise<PowerData | null> {
236
237
  if (spGpuCache && now - spGpuCache.ts < SP_TTL_MS) {
237
238
  spRaw = spGpuCache.raw;
238
239
  } else {
239
- spRaw = (await run('system_profiler SPDisplaysDataType 2>/dev/null')).trim();
240
+ spRaw = (await run('system_profiler SPDisplaysDataType 2>/dev/null', '', 3000)).trim();
240
241
  spGpuCache = { raw: spRaw, ts: now };
241
242
  }
242
243
 
@@ -400,18 +401,25 @@ export async function collectCpu(): Promise<CpuData> {
400
401
  }
401
402
  }
402
403
 
404
+ // Use os.cpus() delta instead of the very slow `top -l 1 -n 0` which
405
+ // blocks for ~1-2s waiting for a sampling window. os.cpus() is instant.
403
406
  let usage = 0;
404
407
  try {
405
- const top = (await run('top -l 1 -n 0')).trim();
406
- // Real `top -l 1 -n 0` output is comma-separated and newline-terminated,
407
- // e.g. "CPU usage: 5.26% user, 10.52% sys, 84.21% idle" — there is no
408
- // semicolon anywhere on that line. The old regex required one to
409
- // terminate the match, so it never matched and usage stayed at 0.
410
- const cpuLine = top.match(/CPU usage:\s*[\d.]+%\s*user,\s*[\d.]+%\s*sys,\s*([\d.]+)%\s*idle/);
411
- if (cpuLine) {
412
- const idle = parseFloat(cpuLine[1]);
413
- usage = Math.round(100 - idle);
408
+ const cpus = os.cpus();
409
+ let totalNow = 0;
410
+ let idleNow = 0;
411
+ for (const cpu of cpus) {
412
+ totalNow += cpu.times.user + cpu.times.nice + cpu.times.sys + cpu.times.idle + cpu.times.irq;
413
+ idleNow += cpu.times.idle;
414
+ }
415
+ if (prevCpuTotal.ts > 0) {
416
+ const totalDelta = totalNow - prevCpuTotal.total;
417
+ const idleDelta = idleNow - prevCpuTotal.idle;
418
+ if (totalDelta > 0) {
419
+ usage = Math.round(((totalDelta - idleDelta) / totalDelta) * 100);
420
+ }
414
421
  }
422
+ prevCpuTotal = { total: totalNow, idle: idleNow, ts: Date.now() };
415
423
  } catch {
416
424
  // ignore
417
425
  }
@@ -534,7 +542,7 @@ async function getDiskIoRates(): Promise<{ readBytesSec: number; writeBytesSec:
534
542
  return { readBytesSec: cachedDiskIo.readBytesSec, writeBytesSec: cachedDiskIo.writeBytesSec };
535
543
  }
536
544
  try {
537
- const raw = (await run('iostat -d -c 2 1 2', '')).trim();
545
+ const raw = (await run('iostat -d -c 2 1 2', '', 3000)).trim();
538
546
  const blocks = raw.split(/\n\s*\n/).filter(Boolean);
539
547
  const targetBlock = blocks.length > 1 ? blocks[1] : blocks[0];
540
548
  if (targetBlock) {
@@ -606,7 +614,7 @@ export async function collectBattery(): Promise<BatteryData | null> {
606
614
  if (spBatteryCache && now - spBatteryCache.ts < SP_TTL_MS) {
607
615
  battInfo = spBatteryCache.raw;
608
616
  } else {
609
- battInfo = (await run('system_profiler SPPowerDataType 2>/dev/null')).trim();
617
+ battInfo = (await run('system_profiler SPPowerDataType 2>/dev/null', '', 3000)).trim();
610
618
  spBatteryCache = { raw: battInfo, ts: now };
611
619
  }
612
620
 
@@ -821,7 +829,7 @@ export async function collectPackets(): Promise<PacketData | null> {
821
829
 
822
830
  let connections = 0;
823
831
  try {
824
- const tcpConns = (await run('netstat -an | grep ESTABLISHED | wc -l', '0')).trim();
832
+ const tcpConns = (await run('netstat -an | grep ESTABLISHED | wc -l', '0', 2000)).trim();
825
833
  connections = parseInt(tcpConns) || 0;
826
834
  } catch {
827
835
  connections = 0;
@@ -830,7 +838,7 @@ export async function collectPackets(): Promise<PacketData | null> {
830
838
  let topProcesses: { pid: number; command: string; rxBytes: number; txBytes: number }[] = [];
831
839
  let allProcesses: { pid: number; command: string; rxBytes: number; txBytes: number; rxPackets?: number; txPackets?: number }[] = [];
832
840
  try {
833
- const lsof = (await run('lsof -i -n -P 2>/dev/null | tail -n +2 | awk \'{print $1, $2}\' | sort | uniq -c | sort -rn', '')).trim();
841
+ const lsof = (await run('lsof -i -n -P 2>/dev/null | tail -n +2 | awk \'{print $1, $2}\' | sort | uniq -c | sort -rn', '', 2000)).trim();
834
842
  const lsofLines = lsof.split('\n');
835
843
  topProcesses = lsofLines.map(line => {
836
844
  const parts = line.trim().split(/\s+/);
@@ -11,7 +11,7 @@ import { promisify } from 'node:util';
11
11
 
12
12
  const execAsync = promisify(exec);
13
13
 
14
- async function run(cmd: string, fallback: string = '', timeout = 5000): Promise<string> {
14
+ async function run(cmd: string, fallback: string = '', timeout = 3000): Promise<string> {
15
15
  try {
16
16
  return (await execAsync(cmd, { encoding: 'utf8', timeout })).stdout.trim();
17
17
  } catch {
@@ -41,7 +41,8 @@ export async function getSmcMetrics(): Promise<SmcMetrics> {
41
41
  const pm = (
42
42
  await run(
43
43
  'sudo -n powermetrics --samplers smc,cpu_power -n 1 --format text 2>/dev/null',
44
- ''
44
+ '',
45
+ 2000
45
46
  )
46
47
  ).trim();
47
48
 
@@ -116,14 +117,10 @@ export async function getSmcMetrics(): Promise<SmcMetrics> {
116
117
 
117
118
  // 4. Smart load-based thermal estimation if hardware sensors return nothing
118
119
  if (result.temps['cpu_die'] === undefined) {
119
- let loadUsage = 0;
120
- try {
121
- const top = await run('top -l 1 -n 0 2>/dev/null', '');
122
- const m = top.match(/CPU usage:\s*[\d.]+\%\s*user,\s*[\d.]+\%\s*sys,\s*([\d.]+)\%\s*idle/);
123
- if (m) loadUsage = Math.max(0, 100 - parseFloat(m[1]));
124
- } catch {
125
- // ignore
126
- }
120
+ // Use os.loadavg() (instant) instead of the slow `top -l 1` (~1-2s)
121
+ const loadAvg = (await import('node:os')).loadavg();
122
+ const ncpus = (await import('node:os')).cpus().length || 1;
123
+ const loadUsage = Math.min(100, (loadAvg[0] / ncpus) * 100);
127
124
 
128
125
  const estCpu = Math.round((38 + (loadUsage * 0.42)) * 10) / 10;
129
126
  result.temps['cpu_die'] = estCpu;
package/src/splash.ts CHANGED
@@ -198,6 +198,6 @@ export async function showSplash(config?: SplashConfig): Promise<void> {
198
198
  process.stdin.resume();
199
199
  process.stdin.on('data', onEnter);
200
200
 
201
- setTimeout(onEnter, 5000);
201
+ setTimeout(onEnter, 1500);
202
202
  });
203
203
  }