node-system-bridge
v0.4.0
Published
A cross-platform system automation library for Node.js and Electron, written in Rust
Maintainers
Readme
Node System Bridge
A cross‑platform system bridge written in Rust, exposing mouse, keyboard, process, window, clipboard and system‑info capabilities to Node.js / Electron apps.
✨ Features
- 🚀 Process control: launch apps, check status, kill processes, list processes
- 🖱️ Mouse control: click, move, smooth move, scroll, drag
- ⌨️ Keyboard input: type text, special keys, human‑like typing
- 🪟 Window control: bring window to front by process id
- 📋 Clipboard: read / write / clear system clipboard
- 💻 System info: fast hardware / OS / network information
- 🌐 Cross‑platform API: macOS & Windows today, Linux planned
- 📦 Prebuilt binaries: no Rust toolchain required for consumers
- 🎯 ESM & CommonJS: works in modern Electron and classic Node
📦 Installation
npm install node-system-bridgePrebuilt native binaries are shipped for macOS (Intel & Apple Silicon) and Windows x64. Linux support is planned.
🚀 Quick Start
ESM (recommended, Electron 28+)
// main.mjs / Electron main (ESM)
import { Process } from 'node-system-bridge'
// Use the real executable path, not just the .app bundle
const calcPath = '/System/Applications/Calculator.app/Contents/MacOS/Calculator'
const pid = await Process.launchApp(calcPath)
console.log('Calculator PID:', pid)
const isRunning = await Process.isRunning(pid)
console.log('Is running:', isRunning)
await Process.killProcess(pid)CommonJS
// main.cjs
const { Process } = require('node-system-bridge')
const chromePath = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
Process.launchApp(chromePath, ['https://github.com'])
.then(pid => {
console.log('Chrome PID:', pid)
})Path notes (important)
Always pass an executable path, not just a bundle/folder:
// macOS
await Process.launchApp('/Applications/Safari.app/Contents/MacOS/Safari')
// Windows
await Process.launchApp('C:\\Program Files\\MyApp\\app.exe')
// Linux
await Process.launchApp('/usr/bin/firefox')Using with Electron & asar (important)
When you package your Electron app with asar, native .node binaries must be unpacked,
otherwise they cannot be loaded at runtime.
This library already detects Electron and will prefer loading from app.asar.unpacked when it sees a path like:
.../resources/app.asar/node_modules/node-system-bridge/...It will automatically try:
.../resources/app.asar.unpacked/node_modules/node-system-bridge/node-system-bridge.<platform>.nodeSo in your packager config (for example electron-builder), make sure node-system-bridge is unpacked:
{
"build": {
"asarUnpack": [
"node_modules/node-system-bridge/**"
]
}
}After that, you can simply import in Electron main / preload:
// ESM
import { System } from 'node-system-bridge'
// or CommonJS
const { System } = require('node-system-bridge')🛠️ Modules & API Overview
Process
// Start an app
Process.launchApp(appPath: string, args?: string[]): Promise<number>
// Kill a process
Process.killProcess(pid: number): Promise<void>
// Check if a process is running
Process.isRunning(pid: number): Promise<boolean>
// Get all processes
Process.getAllProcesses(): Promise<ProcessInfo[]>
interface ProcessInfo {
pid: number
name: string
cpuUsage: number
memory: number
parentPid?: number
cmd: string[]
exe?: string
cwd?: string
}// Launch Chrome and filter all Chrome processes
const pid = await Process.launchApp(
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
['--new-window', 'https://github.com']
)
const all = await Process.getAllProcesses()
const chromeProcesses = all.filter(p =>
p.name.toLowerCase().includes('chrome')
)Mouse
import { Mouse } from 'node-system-bridge'
// Simple click
Mouse.click(100, 200)
// Smooth move & scroll
Mouse.moveToSmooth(500, 300)
Mouse.scroll(-5)Keyboard & Clipboard
import { Keyboard, Clipboard } from 'node-system-bridge'
// Human‑like typing
Keyboard.typeText('Hello World')
// Type from clipboard
Clipboard.writeText('From clipboard')
Keyboard.typeFromClipboard('fast')
// Special key
Keyboard.pressKey('enter')Window
// Bring the main window of a process to front (non‑always‑on‑top)
Window.bringToFront(pid: number): Promise<void>import { Process, Window } from 'node-system-bridge'
const chromePath = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
const pid = await Process.launchApp(chromePath)
// wait for window creation
await new Promise(r => setTimeout(r, 2000))
await Window.bringToFront(pid)System info
System.getSystemInfo(): Promise<SystemInfo>import { System } from 'node-system-bridge'
const info = await System.getSystemInfo()
console.log({
hostname: info.hostname,
platform: info.platform, // "win32" | "darwin" | "linux"
arch: info.arch, // "x64" | "arm64"
manufacturer: info.manufacturer,
model: info.model,
cpuBrand: info.cpuBrand,
macs: info.macs,
source: info.source // "wmi" | "wmic" | "basic" | ...
})🌍 Platform Support
| Platform | Arch | Min Version | Status | |---------|------|------------|------------| | macOS | x64 | 10.13+ | ✅ Supported | | macOS | ARM64 | 11.0+ | ✅ Supported | | Windows | x64 | 10+ | ✅ Supported | | Linux | x64 | 3.10+ | 🚧 Planned |
Current npm package ships macOS + Windows prebuilt binaries. Linux will be added in future releases.
📋 Requirements
- Node.js: 16.0.0+
- Electron: 12.0.0+ (25+ recommended)
- OS:
- Windows 10+
- macOS 10.13+
- Linux (X11, planned)
📄 License
MIT License — see LICENSE.
Made with ❤️ using Rust and Node.js.
