JavaScript port of the Reticulum Network Stack (RNS) — wire-compatible with the Python reference implementation.
Reticulum is a cryptography-based networking stack for building anonymous, decentralised networks over any physical medium. This port enables RNS-based applications in the JavaScript ecosystem, including browsers.
Browser clients connect via reticulum-websocket — a Python WebSocket bridge that gives browsers access to the full RNS network.
- Full wire-format compatibility with Python RNS nodes (verified via interop tests)
- Browser-compatible core — crypto, protocol, and storage run in browsers
- WebSocket transport — browsers connect to an RNS node via WebSocket
- All core protocol features: Identity, Destination, Packet, Announce, Link (encrypted channels), Resource (large transfers), Channel (typed messaging)
- All interface types: TCP client/server, UDP, AutoInterface (IPv6 multicast), WebSocket, Local shared instance
- IFAC (Interface Access Codes) for interface-level authentication
- Transport forwarding for multi-hop routing
- Pluggable storage with Node filesystem and browser IndexedDB backends
- Node.js >= 18 (tested on 24)
- npm (comes with Node.js)
# Install Node dependencies
npm install
# Run tests
npm test # 374 tests
# Build browser bundle
npm run build:browser # → dist/reticulum.umd.js (~73KB gzipped)To connect browsers (or Node.js clients) to the RNS network, you need the WebSocket bridge from reticulum-websocket:
git clone https://github.com/aerik/reticulum-websocket.git
cd reticulum-websocket
python -m venv .venv
.venv/Scripts/pip install rns websockets # Windows
# .venv/bin/pip install rns websockets # Linux/macOSSee the reticulum-websocket repo for bridge configuration and usage.
import { Reticulum, Identity, Destination, DEST_SINGLE, DEST_IN } from 'reticulum-js';
const rns = new Reticulum({
interfaces: [{
name: 'Network',
type: 'TCPClientInterface',
enabled: true,
target_host: 'rns.beleth.net',
target_port: 4242,
}],
});
await rns.start();
// Listen for announces
rns.transport.on('announce', (info) => {
console.log('Announce:', info.identity.hexHash, info.appData);
});
// Create identity and announce
const identity = Identity.generate();
const dest = new Destination(identity, DEST_IN, DEST_SINGLE, 'myapp', 'service');
rns.announce(dest, new TextEncoder().encode('Hello RNS!'));<script src="dist/reticulum.umd.js"></script>
<script>
const R = window.Reticulum;
const transport = new R.Transport();
const ws = new R.WebSocketClientInterface('Browser', 'ws://localhost:8765');
transport.registerInterface(ws);
await ws.start();
// Now receiving RNS packets from the network via the bridge
</script>See examples/browser-chat.html for a complete working chat application.
Browser Node.js Bridge RNS Network
┌──────────────────┐ ┌──────────────────┐ ┌──────────┐
│ Identity, Crypto │ │ Full RNS Stack │ │ Python │
│ Packet, Link │◄──WS────►│ + WebSocket Srv │◄──TCP────►│ RNS │
│ Transport │ │ + Transport │ │ Nodes │
│ (browser bundle) │ │ + Forwarding │ │ │
└──────────────────┘ └──────────────────┘ └──────────┘
| Document | Contents |
|---|---|
| docs/architecture.md | Module structure, protocol layers, data flow |
| docs/crypto.md | Cryptographic primitives, key formats, encryption scheme |
| docs/packet-format.md | Wire format, flags byte, header layouts |
| docs/interfaces.md | All interface types, configuration, framing |
| docs/link-protocol.md | Link handshake, session keys, encrypted channel |
| docs/browser.md | Browser bundle, WebSocket transport, IndexedDB storage |
| docs/python-interop.md | Python WebSocket interface, interop testing |
| docs/cli.md | CLI tools: rnstatus, rnpath |
| docs/api.md | API reference for all public classes |
| Package | Purpose | Browser? |
|---|---|---|
@noble/curves |
X25519, Ed25519 (pure JS) | Yes |
@noble/hashes |
SHA-256, HMAC, HKDF (pure JS) | Yes |
@msgpack/msgpack |
MessagePack for request/response and storage | Yes |
ws |
WebSocket server (Node.js only) | No |
No external bz2 dependency — a vendored pure-JS bzip2 decoder (src/vendor/bz2.js) handles Resource decompression in both Node and browser without Buffer polyfills.
LXMF (Messaging) — the next layer to build. LXMF is the messaging protocol used by Sideband and NomadNet for chat. All building blocks are in place (Identity, Link, Resource). LXMF would add message formatting, delivery to lxmf.delivery destinations, and propagation node support for offline delivery. See github.com/markqvist/LXMF.
MIT