@lynxhub/hwmonitor
v0.11.0
Published
Lynx Hardware Monitor is a Node.js module that tracks your system's CPU, GPU, memory, motherboard, storage, and network.
Readme
Lynx Hardware Monitor
Lynx Hardware Monitor is a Node.js module for monitoring system hardware components such as CPU, GPU, Memory, Motherboard, Storage, Network, Battery, Controller and PSU.
Features
- Selective Component Monitoring: Choose which hardware components (CPU, GPU, Memory, etc.) to monitor.
- Detailed Hardware Information: Provides structured data including sensor readings (name, value, type, unit, identifier) for various hardware items.
- Typed API: Includes TypeScript definitions for
HardwareReport,SensorInfo,HardwareItemInfo,MonitorError, andComponentType. - One-Time Data Fetch: Retrieve a snapshot of hardware data.
- Timed Monitoring: Continuously monitor hardware components at specified intervals.
- Event-Driven: Emits
dataevents withHardwareReportanderrorevents withMonitorError. - Cross-Platform Support: Detects OS (Windows, macOS, Linux) and architecture (x64, arm64) to download the appropriate CLI tool.
- Automatic CLI Management: Downloads and manages the required
LynxHardwareCLIfrom GitHub releases. - .NET Runtime Check: Verifies if the required .NET 9 runtime is installed.
Requirements
- Node.js: As this is a Node.js module.
- .NET 9 Runtime: The companion CLI tool (
LynxHardwareCLI) requires the .NET 9 runtime to be installed. The module will check for this requirement. You can download it from https://dotnet.microsoft.com/download/dotnet/9.0. - Administrative Privileges: Some hardware data may not be accessible unless the application using this module is
run with administrative privileges (e.g., "Run as administrator" on Windows, or using
sudoon Linux/macOS).
Installation
npm i @lynxhub/hwmonitorOr if you use yarn:
yarn add @lynxhub/hwmonitorUsage
import HardwareMonitor, {HardwareReport, MonitorError, ComponentType} from '@lynxhub/hwmonitor';
import {join} from 'node:path';
import {homedir} from 'node:os';
const homeDir = homedir();
// Define a directory where the CLI tool will be downloaded and stored.
// Choose the appropriate path for your OS or make it configurable.
// Example for Windows:
// const cliStorageDir = join(homeDir, 'AppData', 'Local', 'YourApp', 'HardwareMonitorCLI');
// Example for macOS:
// const cliStorageDir = join(homeDir, 'Library', 'Application Support', 'YourApp', 'HardwareMonitorCLI');
// Example for Linux:
// const cliStorageDir = join(homeDir, '.local', 'share', 'YourApp', 'HardwareMonitorCLI');
// Defaulting to a generic path, ensure this directory is writable.
const cliStorageDir = join(homeDir, '.your-app-name', 'HardwareMonitorCLI');
const monitor = new HardwareMonitor();
async function main() {
try {
// 1. Check requirements and download the CLI tool
// This needs a directory path where the CLI can be stored.
console.log(`Initializing Hardware Monitor... CLI will be stored in: ${cliStorageDir}`);
await monitor.checkRequirements(cliStorageDir);
console.log('Requirements checked and CLI is ready.');
// 2. Get data once
console.log('\nGetting data once for GPU, CPU, and Uptime...');
// Monitor only GPU and CPU, with a 5-second timeout. 'uptime' is also requested.
const reportOnce = await monitor.getDataOnce(['gpu', 'cpu', 'uptime'], 5000);
console.log('Data (once):');
console.log(JSON.stringify(reportOnce, null, 2));
// Example: Accessing specific data
if (reportOnce.CPU && reportOnce.CPU.length > 0) {
const cpuName = reportOnce.CPU[0].Name;
console.log(`\nCPU Name: ${cpuName}`); //
const cpuLoadSensor = reportOnce.CPU[0].Sensors.find(s => s.Name === 'CPU Total' && s.Type === 'Load'); //
if (cpuLoadSensor && cpuLoadSensor.Value !== null) {
console.log(`Current CPU Load: ${cpuLoadSensor.Value.toFixed(2)}%`); //
}
}
if (reportOnce.Uptime) {
console.log(`System Uptime: ${reportOnce.Uptime.formatted}`); //
}
if (reportOnce.ElapsedTime) {
console.log(`Monitor Elapsed Time: ${reportOnce.ElapsedTime.formatted}`); //
}
// 3. Start timed monitoring
console.log('\nStarting timed monitoring for CPU and Memory (updates every 3 seconds)...');
monitor.on('data', (data: HardwareReport) => { //
console.log('\n--- Timed Data Received ---');
console.log(`Timestamp: ${new Date(data.Timestamp).toISOString()}`); //
if (data.CPU && data.CPU.length > 0 && data.CPU[0].Sensors) { //
const cpuLoad = data.CPU[0].Sensors.find(s => s.Name === 'CPU Total' && s.Type === 'Load'); //
if (cpuLoad && cpuLoad.Value !== null) {
console.log(`Current CPU Load: ${cpuLoad.Value.toFixed(2)}%`); //
}
}
if (data.Memory && data.Memory.length > 0 && data.Memory[0].Sensors) { //
const memoryUsedSensor = data.Memory[0].Sensors.find(s => s.Name === 'Memory Used' && s.Type === 'Data'); //
const memoryAvailableSensor = data.Memory[0].Sensors.find(s => s.Name === 'Memory Available' && s.Type === 'Data'); //
if (memoryUsedSensor && memoryUsedSensor.Value !== null) {
console.log(`Memory Used: ${memoryUsedSensor.Value.toFixed(2)} ${memoryUsedSensor.Unit}`); //
}
if (memoryAvailableSensor && memoryAvailableSensor.Value !== null) {
console.log(`Memory Available: ${memoryAvailableSensor.Value.toFixed(2)} ${memoryAvailableSensor.Unit}`); //
}
}
if (data.Uptime) { //
console.log(`System Uptime: ${data.Uptime.formatted}`); //
}
if (data.ElapsedTime) { //
console.log(`Monitor Elapsed Time: ${data.ElapsedTime.formatted}`); //
}
// console.log(JSON.stringify(data, null, 2)); // Optionally log full data
console.log('--- End Timed Data ---');
});
monitor.on('error', (error: MonitorError) => { //
console.error('\n--- Timed Monitoring Error ---');
console.error(`Error Type: ${error.type}`); //
console.error(`Message: ${error.message}`); //
if (error.stderrData) console.error('Stderr:', error.stderrData); //
if (error.rawError) console.error('Raw Error:', error.rawError); //
console.error('--- End Error ---');
});
// Start monitoring CPU, Memory, and Uptime. Updates every 3 seconds.
monitor.startTimed(3000, ['cpu', 'memory', 'uptime']); //
// Stop timed monitoring after a while (e.g., 15 seconds for this example)
setTimeout(() => {
console.log('\nStopping timed monitoring...');
monitor.stopTimed(); //
console.log('Monitoring stopped. Example finished.');
// Example of getting data again after stopping
// Note: checkRequirements is only needed once unless cliStorageDir changes or CLI needs update.
console.log('\nGetting data once for Storage and Uptime after stopping timed monitor...');
monitor.getDataOnce(['storage', 'uptime'], 5000) //
.then(report => {
console.log('Data (storage - after stop):');
console.log(JSON.stringify(report, null, 2));
})
.catch(err => {
const monitorError = err as MonitorError;
console.error('Error getting storage data after stop:', monitorError.message);
});
}, 15000);
} catch (error) {
console.error('\n--- An Error Occurred in Main ---');
// Using 'as MonitorError' for type assertion to access specific properties
const monitorError = error as MonitorError;
console.error(`Error Type: ${monitorError.type || 'N/A'}`);
console.error(`Message: ${monitorError.message}`);
if (monitorError.stderrData) {
console.error('Stderr Data:', monitorError.stderrData);
}
if (monitorError.rawError) {
console.error('Raw Error:', monitorError.rawError);
}
// Check for the specific .NET runtime error message
if (monitorError.message && monitorError.message.includes('.NET 9 runtime')) { //
console.error(
"Please ensure .NET 9 runtime is installed. " +
"Download from: [https://dotnet.microsoft.com/download/dotnet/9.0](https://dotnet.microsoft.com/download/dotnet/9.0)" //
);
}
console.error('--- End Error in Main ---');
}
}
main();API
HardwareMonitor
An EventEmitter class.
new HardwareMonitor()
Creates a new instance of the hardware monitor.
async checkRequirements(targetDir: string): Promise<void>
Checks if the .NET 9 runtime is installed and downloads the necessary CLI tool to the specified targetDir. This
directory is used to store different versions of the LynxHardwareCLI.
Throws an error if .NET 9 is not found or if the CLI download fails.
async getDataOnce(components?: ComponentType[], timeoutMs?: number): Promise<HardwareReport>
Retrieves hardware data once.
components(optional): Array ofComponentType(e.g.,['cpu', 'gpu']) to monitor. Defaults to all components.timeoutMs(optional): Timeout in milliseconds for the operation. Defaults to 10000ms. Returns a Promise resolving to aHardwareReport. Throws aMonitorErroron failure or timeout.
startTimed(intervalMs: number, components?: ComponentType[]): void
Starts timed monitoring of hardware data.
intervalMs: Interval in milliseconds for data updates.components(optional): Array ofComponentTypeto monitor. Defaults to all. Emitsdataevents withHardwareReportobjects anderrorevents withMonitorErrorobjects.
stopTimed(): void
Stops the currently active timed monitoring process.
Events
data: Emitted during timed monitoring with aHardwareReportobject.monitor.on('data', (report: HardwareReport) => { /* ... */ });error: Emitted when an error occurs during timed monitoring or ifstartTimedis called while already active. Payload is aMonitorErrorobject.monitor.on('error', (error: MonitorError) => { /* ... */ });
Types
ComponentType:'cpu' | 'gpu' | 'memory' | 'motherboard' | 'storage' | 'network' | 'battery' | 'controller' | 'psu' | 'uptime'SensorInfo:{ Name: string; Value: number | null; Type: string; Unit: string; Identifier: string; }HardwareItemInfo:{ Name: string; HardwareType: string; Sensors: SensorInfo[]; SubHardware: HardwareItemInfo[]; }HardwareReport: Contains aTimestampand arrays forCPU,GPU,Memory,Motherboard,Storage,Network,Battery,ControllerandPSU, each beingHardwareItemInfo[].MonitorError:Error & { type: 'spawn_error' | 'process_error' | 'json_parse_error' | 'timeout_error'; rawError?: any; stderrData?: string; }
CLI Tool (LynxHardwareCLI)
This module relies on an external CLI tool, LynxHardwareCLI. The HardwareMonitor module automatically handles the
download and management of this CLI.
- Repository: KindaBrazy/LynxHardwareCLI
- Functionality: The
downloadAndExtractLatestClifunction withincli_downloader.tsfetches the latest release from the GitHub API, identifies the correct asset based on OS and architecture, downloads it, extracts it to a versioned folder within thetargetDirprovided tocheckRequirements, and cleans up older versions.
Scripts (from package.json)
npm run build: Compiles TypeScript to JavaScript. (tsc)npm start: Builds the project and then runsdist/index.js(Note:index.jsseems to be the main class definition, not a runnable script in itself without the example usage). Theexample.tsfile provides a runnable example.
Development
- Linting: Uses ESLint with TypeScript support. Configured in
eslint.config.js. - Formatting: Uses Prettier. Configured in
.prettierrc.json. - TypeScript Configuration:
tsconfig.jsonspecifies ESNext as target and NodeNext for module system, with output todistdirectory.
© 2025 KindaBrazy.
