A typed, ergonomic TypeScript client for MeshCore Companion Radio devices.
meshcore-ts is a thin, typed wrapper over the official
@liamcottle/meshcore.js — it does
not reimplement the protocol. That library does the wire work; this one
delegates to it and adds a first-class TypeScript surface: typed methods, named
events, normalized values, and proper errors. So you talk to a MeshCore node over
WiFi or USB without wrangling raw numeric byte codes and Uint8Arrays — and you
get upstream protocol updates for free.
import { MeshCoreClient, TxtType } from "@dpup/meshcore-ts";
const client = MeshCoreClient.tcp("192.168.1.50", 5000); // or .serial("/dev/ttyACM0")
client.on("contactMessage", (msg) => console.log(`${msg.pubKeyPrefix}: ${msg.text}`));
await client.connect();
const self = await client.getSelfInfo();
console.log(`Connected to "${self.name}" — ${self.publicKey}`);
const alice = await client.findContactByName("alice");
if (alice) await client.sendTextMessage(alice, "hello from typescript", TxtType.Plain);Save as index.ts and run with bunx tsx index.ts (the snippet uses top-level await, so it needs an ESM/TS runner).
- 🧩 Fully typed — typed methods, events, and data models (
Contact,Channel,SelfInfo,RepeaterStats, …). - 📡 Named events —
client.on("contactMessage", …)instead ofconnection.on(0x83, …). - 🔤 Normalized data — hex-string keys & paths,
Datetimestamps, realbooleanflags. - 🛡️ Safe by default — typed errors (
MeshCoreError/…DeviceError/…TimeoutError) and request timeouts so a silent device never hangs your program. - 🔌 Node transports — TCP/WiFi and USB serial, with simple factories.
- 🪝 Escape hatch — the raw
meshcore.jsconnection stays reachable viaclient.raw.
npm install @dpup/meshcore-ts # or: bun add @dpup/meshcore-ts / pnpm add @dpup/meshcore-tsESM-only, Node.js ≥ 18. The @liamcottle/meshcore.js dependency is installed automatically.
- Guide — concepts and recipes: connecting, events & auto-sync, messaging, contacts, errors & timeouts, remote nodes.
- API reference — the complete, generated reference: every method, event, model, error, and enum with full signatures.
Any method that takes a contact accepts a Contact, a hex public-key string, or
raw Uint8Array bytes. The client auto-drains incoming messages and emits
contactMessage / channelMessage / channelData events by default — see the
guide for the full event catalog and options. When
autoSync is on, attach an error listener so background-drain failures aren't
lost.
- All protocol logic lives in
@liamcottle/meshcore.js. This package owns only the types, normalization, and safety layered on top. - Node-focused, ESM-only. Transports are TCP/WiFi and USB serial. This mirrors
meshcore.jsand keeps theserialportdependency out of browser bundles; browser BLE/WebSerial transports are intentionally not exposed.
examples/list-contacts.ts— connect and print self info + contacts.examples/monitor.ts— a live, color-coded traffic monitor.
bun examples/monitor.ts 172.16.0.23 5000 30 # monitor a node for 30 secondsbun install
bun run typecheck # tsc --noEmit (strict)
bun run test # vitest unit tests (no hardware needed)
bun run build # emit dist/ (ESM + .d.ts)
bun run docs # regenerate docs/api.md from the sourceSee AGENTS.md for architecture and contribution notes.
MIT © Dan Pupius