Skip to main content
PlatformArchitectures
macOSarm64
Linuxx86_64, aarch64 (glibc and musl), armv7
Windowsx86_64, aarch64
Androidaarch64, armv7
All platforms require Node.js 20.3.0 or newer. The JavaScript bindings to iroh are published on npm as @number0/iroh and shipped from iroh-ffi. They’re built with napi-rs, so the package distributes prebuilt native binaries. No Rust toolchain or local compilation is needed.

Install

npm install @number0/iroh
Requires Node.js 20.3.0 or newer. Prebuilt N-API binaries are published for:
  • macOS: arm64 (no Intel build)
  • Linux: x86_64 and aarch64 (glibc + musl), armv7 (gnueabihf + musleabihf)
  • Windows: x86_64 and aarch64
  • Android: aarch64 and armv7

Hello, iroh

import { Endpoint } from '@number0/iroh'

const ALPN = Array.from(Buffer.from('hello-iroh/0'))

const ep = await Endpoint.bind({ alpns: [ALPN] })
console.log('endpoint id:', ep.id().toString())
await ep.close()
Endpoint.bind applies the n0 preset (public discovery + default relays) by default. Pass an EndpointOptions object to override the preset, supply a fixed secret key, or set ALPNs.

A two-peer echo

A minimal sender/receiver pair over a bidirectional stream:
// main.mjs: run `node main.mjs receiver` or `node main.mjs sender <ticket>`
import { Endpoint, EndpointTicket } from '@number0/iroh'

const ALPN = Array.from(Buffer.from('hello-iroh/0'))

async function receiver() {
  const ep = await Endpoint.bind({ alpns: [ALPN] })
  console.log('ticket:', EndpointTicket.fromAddr(ep.addr()).toString())

  const incoming = await ep.acceptNext()
  const conn = await (await incoming.accept()).connect()
  const bi = await conn.acceptBi()
  const msg = await bi.recv.readToEnd(1024)
  await bi.send.writeAll(msg)
  await bi.send.finish()
  await ep.close()
}

async function sender(ticketStr) {
  const ep = await Endpoint.bind()
  const addr = EndpointTicket.fromString(ticketStr).endpointAddr()
  const conn = await ep.connect(addr, ALPN)

  const bi = await conn.openBi()
  await bi.send.writeAll(Array.from(Buffer.from('hello')))
  await bi.send.finish()
  const echoed = await bi.recv.readToEnd(1024)
  console.log('echoed:', Buffer.from(echoed).toString('utf8'))
  await ep.close()
}

const [cmd, arg] = process.argv.slice(2)
if (cmd === 'receiver') await receiver()
else if (cmd === 'sender') await sender(arg)
else console.error('usage: receiver | sender <ticket>')
Start the receiver in one terminal, copy the printed ticket, and run the sender with it in another.

Next steps

Connect two endpoints

Walkthrough of endpoints, tickets, and ALPNs with code samples in every language.

hello-iroh-ffi example app

A headless Node peer for the cross-platform dot demo. It speaks the same wire format as the Swift and Kotlin apps and prints received positions to the console.

JavaScript API reference

Generated TypeDoc reference for @number0/iroh.

iroh-ffi on GitHub

Source, examples, and issue tracker for the JavaScript (and other-language) bindings.