Build on the mesh

npm install @offline-protocol/mesh-sdk

The Offline Protocol mesh SDK is a TypeScript API over a Rust core. Transport over five radios, identity, discovery, shared state, and telemetry behind one object, with MLS encryption on by default. React Native on iOS and Android, Python on desktop, Java on the JVM, Ruby on RubyGems, a C API for any language that calls C, Rust crates everywhere else, early native Swift and Android packages, a preview Flutter plugin with the React Native surface, and an experimental browser build. Current release v0.31.0.

Illustration: the twelve-line quickstart on the left, and on the right the events it produces on a device: the mesh starts, a neighbour is discovered over Bluetooth LE, an MLS session opens, and the message is delivered in two hops.

Twelve lines from install to a delivered message, with encryption, retry, and routing already on.

The API, by layer

Everything in the SDK, in the order the platform is built. Each row links to how it works; the symbols are the entry points.

Events

One handler, protocol.on(name, fn). What the protocol emits and what each event carries.

EventFiresCarries
neighbor_discoveredA peer is found on any transportpeer_id, transport
message_receivedA message arrives, already decryptedsender, content
message_deliveredThe recipient's acknowledgment comes backmessage_id, latency_ms, hop_count
message_failedThe retry budget is exhaustedreason, retry_count
transport_switchedDORS moves traffic to another transportfrom, to, reason
file_progressEach chunk of a transfer is acknowledgedfile_id, percentage
file_receivedThe last chunk lands on the recipientfile_id, file_name
service_discoveredA provider answers a discovery queryprovider_peer_id, service_id, version, hop distance
data_changedA document change is durable on this devicespace_id, doc_id
group_role_changedA member is promoted or demotedgroup id, member, role

Defaults you can change

The behaviour under the API, the value it ships with, and where to set it.

SettingDefaultWhere
encryption.enabledtrue. MLS on every session, keys exchanged on discoveryOfflineProtocol options
requireEncryptiontrue. A send that cannot be encrypted fails with a typed errorOfflineProtocol options
switchHysteresis15 points before a rival transport winsDORS config
switchCooldownSecs20 s between switchesDORS config
stabilityWindowSecs8 s for the current transport to settleDORS config
rssiSwitchThreshold-85 dBm, below which a link is abandonedDORS config
ack timeoutAbout 10 s, up to 1,000 acknowledgments in flightReliabilityConfig
retry backoff1 s doubling to 5 min, up to 10 attemptsReliabilityConfig
outbox retention7 days for a message with no path yetReliabilityConfig
message TTL8 hops; up to 5,000 message ids remembered for 7 days to drop duplicatesReliabilityConfig
chunk size, max file4 KiB chunks over Bluetooth LE, 32 KiB over the Wi-Fi peer link, 256 KiB over the internet; 100 MiB per fileSet by the engine, not configurable in 0.31.0
document cap1 MiB compacted, warning at 768 KiB, 32 KiB per sync frameDataStore
flushIntervalMs, scrubIdsBatch cadence and identifier hashing, with mlsVerbosity, metricsCadenceMs, and includeDeviceId beside themTelemetryConfig, via enableTelemetry

Requirements

BindingRuns onNeeds
@offline-protocol/mesh-sdkiOS and Android through React Native. BLE with background restoration on iOS; BLE and WiFi Direct with a foreground service on Android. With the peer stream on, iPhones, Android phones, and Python hosts on one Wi-Fi network find each other.React Native 0.70+, iOS 13+, Android API 24+, Node 18+ for tooling
offline-protocol-sdkPython on PyPI for macOS, Linux, and Windows hosts, with BLE, internet, and peer-stream bridges, and a local API service that fronts one engine for several local applications. With the lan and http extras the service finds other hosts on the LAN and serves an HTTP front, so programs that do not use the SDK call each other across devices. pip install "offline-protocol-sdk[lan,http]"Python 3.10 to 3.13. Wheels for macOS arm64 (macOS 14+), Linux x86_64 and aarch64 (glibc 2.34+), and Windows x86_64; no Intel macOS or musl (Alpine) wheel
OfflineProtocolSDKEarly native Swift package for iOS, from offline-protocol-swift, built from the same bridge sources as the React Native module. Its public API is not settled yet, and wiring transports to the engine is the app's job.Swift Package Manager, iOS 13+, iOS only, Swift 5.10+
Android libraryEarly native Kotlin library for Android, the same bridge sources and status as the Swift package. On Maven Central as com.offlineprotocol:offline-protocol-sdk; the app wires transports and storage to the engine.Android API 24+, four ABIs
offline-protocol-javaJava on Maven Central as com.offlineprotocol:offline-protocol-java, for the JVM on desktop and server, generated from the same interface definition as the Swift, Kotlin, and Python bindings. The jar holds no native code: the native library for your platform comes from the desktop archives on each GitHub release.JDK 22+, run with --enable-native-access; Linux, macOS arm64, or Windows library
offline_protocol.hA C API over the same native library: create an engine from a JSON configuration, call any method by name with JSON parameters, and receive events as JSON. It works from C, C++, Go through cgo, C# through P/Invoke, and Zig. The header ships in each desktop archive on the GitHub release; the iOS XCFramework carries the same functions, and the Android libraries do not.A JSON library of your own; Linux x86_64 or aarch64, macOS arm64, Windows x86_64
offline_protocolPreview Flutter plugin for iOS and Android, built from the same bridge sources as the React Native module. MeshSdk gives Dart the React Native module's native surface, Nostr and Reticulum configurations start those transports, and on Android the mesh runs in the same foreground service. Not on pub.dev yet, so add it as a path dependency from the SDK repository.Flutter 3.10+, iOS 13+, Android API 24+, a one-time native build from source
offline_protocol gemRuby on RubyGems as offline_protocol, for scripts, tooling, and servers, generated from the same interface definition as the Swift, Kotlin, Python, and Java bindings and calling the native library through the ffi gem. The gem holds no native code: the native library for your platform comes from the desktop archives on each GitHub release.Ruby 3.3+ and the ffi gem; Linux, macOS, or Windows library
offline-protocol-webExperimental browser build: a full node in a Web Worker, with durable storage in origin-private files, WebRTC links between devices, a nearby room for browsers on one network, Nostr over the application's relays, and in Chromium a Web Bluetooth link to a phone or a board. The crate is on crates.io; build the JavaScript in bindings/web from the SDK repository.A secure context (HTTPS or localhost); tested in Chromium, Firefox, and WebKit
Rust cratesThirteen crates on crates.io, with a documented bridge contract for your own transport, and built-in file stores sealed under a store key for hosts with no platform keystore. Native libraries for Linux, macOS arm64, and Windows are attached to each GitHub release.Rust 1.87+
offline-protocol-leafA no_std profile that speaks MLS on a Cortex-M part beside your radio stack. CI also compiles it for ESP32 RISC-V parts, Cortex-M0, and WASI; your firmware supplies the radio, storage, entropy, and clock. Embedded and OEM.Time at pairing, hardware entropy, durable storage, authorization

Reference material

ResourceWhat it isWhere
Developer portalSign up, create an organization and an application, and take an API key.dev.offlineprotocol.com
DocumentationGuides, the API reference, and integration notes for every binding. Current release: SDK v0.31.0.offlineprotocol.com/docs
Protocol specificationWire format, envelopes, identity, control frames, data sync, and the gateway contract, independent of any one implementation.docs/spec
Conformance vectorsTwelve vector files a second implementation can test against.docs/spec/conformance.md
Threat modelAssets, adversaries, controls, and the residual risks stated plainly.docs/security/threat-model.md
Architecture decisionsThirty-one records on why the non-obvious choices are what they are.docs/adr
ChangelogEvery release, with the reasoning attached.CHANGELOG.md
Offline Protocol CLIThe offline command: log in, wire a project, add packages, and run the local MCP server.offlineprotocol.com/developers/cli
MCP serverConnect Claude Code, Codex, Cursor, or any MCP client, locally or hosted.offlineprotocol.com/developers/mcp
Live demoWatch the SDK pick a transport: scores, thresholds, and the event stream, in your browser.offlineprotocol.com/sandbox

Every app you ship extends the network. Devices you ship relay for every other app on the mesh, and theirs relay for yours.