@liminal-machines-co/serial
v0.6.4
Published
Small, fast serialport for Node — Zig-backed native core with prebuilt binaries for all major platforms.
Maintainers
Readme

@liminal-machines-co/serial
A small, fast serial port library for Node.js with a Zig-backed native core. Prebuilt native binaries for all platforms are bundled into the package, so you probably can just install and go without any build process after install.
Install
npm install @liminal-machines-co/serialUsage
import { SerialPort, ReadlineParser } from "@liminal-machines-co/serial";
const port = new SerialPort({ path: "/dev/ttyUSB0", baudRate: 115200 });
await port.open();
port.pipe(new ReadlineParser()).on("data", (line) => console.log(line));
await port.write("AT\r\n");
const ports = await SerialPort.list(); // [{ path, portType }, ...]A SerialPort is a Node Readable, so everything you know about streams
applies. See examples/ for runnable scripts.
CLI
List ports without writing any code:
npx liminal-serial list # table of available ports
npx liminal-serial list --json # machine-readable JSONPATH TYPE
/dev/cu.usbserial-1420 cu
/dev/cu.Bluetooth-Incoming-Port cuParsers
Transform streams you compose onto a port with .pipe():
ReadlineParser— split on a delimiter (default\n)ByteLengthParser— fixed-sizelength-byte framesInterByteTimeoutParser— emit after an inter-byte gapRegexParser— split on a pattern
Testing without hardware
MockSerialPort is a drop-in for SerialPort, so
you can test your serial logic with no device attached:
import { MockSerialPort } from "@liminal-machines-co/serial";
const port = new MockSerialPort({ path: "/dev/mock", baudRate: 9600 });
port.mockReply("PING", "PONG\n");
await port.open();
await port.write("PING"); // emits "PONG\n" on 'data'
port.getWrittenData(); // Buffer of everything written
port.simulateFault("disconnect");Platform support
| Platform | Enumeration | Serial IO | | ------------------ | ----------- | --------------------------------- | | macOS (arm64, x64) | ✅ | ✅ | | Linux (x64, arm64) | ✅ | ✅ | | Windows (x64) | ⏳ planned | ⏳ planned (loads; methods throw) |
Windows cross-compiles and loads today (its import library is generated from
node_api.def), but native serial IO and port enumeration aren't wired up yet —
a great first contribution if you're on Windows.
Contributing
You'll need Zig 0.16.0 and Node ≥ 18.
npm install
npm run build:native # build the addon for your host -> prebuilds/
npm run build:prebuilds # cross-compile every targetReleases go out via npm version + a git tag — see RELEASING.md.
Architecture, decisions, and conventions live in CLAUDE.md.
Tests
Tests run on the Bun runner in three suites:
npm test # unit: mock + parsers, pure JS, no hardware
npm run test:integration # native addon over a socat PTY pair (needs socat + a host build)
npm run test:hardware # against a real device (opt-in, see below)
npm run typecheck:test # type-check the test sourcesUnit (
src/**/*.test.ts) — mock and parsersIntegration (
test/integration/) — drives the real native binding through a virtual serial pair made withsocat, and checks the line config (dataBits/parity/stopBits) reaches the device viastty. Runnpm run build:nativefirst; skips automatically ifsocator a binary is missing.Hardware (
test/hardware/) — an opt-in suite that talks to a real device flashed with the firmware inarduino/test-device/. Point it at a port to run it:SERIAL_TEST_PORT=/dev/cu.usbmodem1101 npm run test:hardwareWith
SERIAL_TEST_PORTunset it skips, so it never runs in CI or by accident. It exercises the firmware protocol (PING→PONG, ID, ECHO, LINES, BINARY) through the publicSerialPortAPI.
Overview
src/napi/*.zig— the native addon.root.zigregisters the module;serial_port_posix.zigimplementsNativeSerialPort(background read thread → threadsafe function; async-work Promises for write/drain);enumerate.ziglists ports by scanning/dev.src/*.ts— the JS layer:SerialPort(aReadable),MockSerialPort, parsers, and option validation.index.js— loads the right prebuilt.nodevianode-gyp-build.- Line config uses ZigEmbeddedGroup/serial; N-API headers come from node-api-headers.
License
MIT
