Transport and coordination layer for the disconnected edge. Build apps, agents, and devices that discover peers, communicate securely, and coordinate across BLE, Wi-Fi Direct, internet, Reticulum, and Nostr.
The project's README from github.com/Offline-Protocol/offline-protocol-sdk. As one markdown file: README.md.
Offline-first messaging protocol with intelligent multi-transport switching, mesh networking, and automatic end-to-end encryption
Dual-licensed: use it under AGPL-3.0-only, or buy a commercial license, your call — see the License section for the full breakdown.
What you must implement: the Rust crates are I/O-free protocol engines for everything that moves a message. They queue, route, encrypt, and select transports, but never open a socket or touch a radio for the protocol itself. A platform bridge does the actual I/O: it drains each transport's outbound queue, performs the send, reports the outcome, and injects inbound bytes. The React Native binding ships these bridges for iOS and Android (BLE, WiFi Direct, Internet, Nostr, Reticulum), and the Python binding ships BLE, Internet, LAN peer-stream (the WiFi Direct slot) and gateway client (the Reticulum slot) bridges. If you consume the Rust crates directly via
cargo add, you write the bridge yourself; the contract is documented in theoffline-protocol-transportcrate docs. The one socket the crates do open is the telemetry pipe's HTTPS upload, and only once an app enables telemetry with a key.
Every channel carries the version number of the release it came from.
| Platform | Package | Install |
|---|---|---|
| React Native (iOS, Android) | @offline-protocol/mesh-sdk on npm |
npm install @offline-protocol/mesh-sdk |
| Python (macOS, Linux, Windows) | offline-protocol-sdk on PyPI |
pip install offline-protocol-sdk |
| Rust | offline-protocol and its sibling offline-protocol-* crates on crates.io |
cargo add offline-protocol |
| Swift, iOS (preview) | offline-protocol-swift, product OfflineProtocolSDK |
Swift Package Manager, see below |
| Android, Kotlin (preview) | com.offlineprotocol:offline-protocol-sdk on Maven Central |
implementation("com.offlineprotocol:offline-protocol-sdk:0.30.0"), see below |
| C, and any language that calls C | offline_protocol.h and the native library in each GitHub release's desktop archives |
See bindings/c |
| Flutter (iOS, Android, preview) | offline_protocol plugin in this repository |
Path dependency; see bindings/flutter |
| Java (JVM 22+, desktop and server) | com.offlineprotocol:offline-protocol-java on Maven Central, over the native library in each release's desktop archives |
implementation("com.offlineprotocol:offline-protocol-java:0.30.0"), see bindings/java |
Python. Wheels are published for Python 3.10 or later on macOS arm64
(macOS 14 or later), Linux x86_64 and aarch64 (manylinux_2_34, so glibc
2.34 or later) and Windows x86_64. There is no wheel for Intel macOS, for musl
Linux such as Alpine, or for an older glibc, and no source distribution, so on
those hosts pip finds nothing to install: build from
source instead. The import name is
offline_protocol_sdk.
Swift (preview). The package needs no React Native. It is iOS only (iOS 13 or later; no macOS or Mac Catalyst slice):
dependencies: [
.package(url: "https://github.com/Offline-Protocol/offline-protocol-swift.git", from: "0.30.0")
],
targets: [
.target(name: "YourApp", dependencies: [
.product(name: "OfflineProtocolSDK", package: "offline-protocol-swift")
])
]
It is an early package. Its storage providers are not public yet, so an application cannot construct them; wiring the transports to the engine is the application's to write; and the public API is not a decided one, so names in it may change. The package repository is generated by each release, so issues and pull requests belong in this repository. See bindings/swift.
Android (preview). The library is on Maven Central and needs no React Native:
dependencies {
implementation("com.offlineprotocol:offline-protocol-sdk:0.30.0")
}
It is built from the React Native module's sources, less the files that need
React, so it carries the transport managers, as described in
bindings/kotlin, and it is as early as the Swift
package. Each release also attaches offline-protocol-X.Y.Z-android.zip, which
holds only the generated Kotlin bindings
(uniffi/offline_protocol/offline_protocol.kt, which call the library through
JNA) and the native libraries for arm64-v8a, armeabi-v7a, x86 and
x86_64.
The release also attaches native libraries for Linux (x86_64, aarch64), macOS (arm64) and Windows (x86_64), and the iOS XCFramework. Contributors, and anyone on a platform without a published package, use Building the SDK.
npm install @offline-protocol/mesh-sdk
import { OfflineProtocol, MessagePriority } from '@offline-protocol/mesh-sdk';
const protocol = new OfflineProtocol({
appId: 'my-app',
profile: 'user123',
// Encryption is enabled by default!
});
// start() also initializes MLS with the platform's secure storage,
// unless encryption.enabled is false
await protocol.start();
// Messages are automatically encrypted!
const messageId = await protocol.sendMessage({
recipient: peerAddress, // the peer's off1… address; a username reaches nobody
content: 'Hello!', // Automatically encrypted
priority: MessagePriority.Medium,
});
The Python binding supports macOS, Linux, and Windows. Install it from PyPI (the wheel platforms are above):
pip install offline-protocol-sdk
On a host without a wheel, build it from source.
from offline_protocol_sdk import ProtocolManager
from offline_protocol_sdk.offline_protocol import ProtocolConfig, OverflowPolicy
config = ProtocolConfig(
app_id="my-app",
profile="user123",
ble_enabled=False,
wifi_direct_enabled=False,
internet_enabled=True,
reticulum_enabled=False,
nostr_enabled=False,
prefer_online=True,
initial_ttl=8,
encryption_enabled=True,
auto_key_exchange=True,
store_pending=True,
require_encryption=False,
max_pending_per_peer=64,
max_pending_global=4096,
pending_ttl_ms=86_400_000, # 24 h — matches the SDK default
overflow_policy=OverflowPolicy.DROP_OLDEST,
)
protocol = ProtocolManager(
config,
# Must be removed by the application uninstaller.
state_root="/app/install-owned-data/offline-protocol",
)
See the Python binding guide for transport setup, secure storage, and complete lifecycle examples.
Encryption is fail-closed by default: if a message cannot be encrypted (e.g. MLS was never initialized), the send fails with a typed error instead of silently falling back to plaintext. Messages to peers whose secure session is still being established are queued and delivered encrypted once it is ready.
const protocol = new OfflineProtocol({
appId: 'my-app',
profile: 'user123',
encryption: {
enabled: true, // Auto-encrypt (default)
autoKeyExchange: true, // Exchange keys on peer discovery (default)
storePending: true, // Queue messages until session ready (default)
requireEncryption: true, // Fail closed, never silent plaintext (default)
},
});
To deliberately operate in plaintext (e.g. an open-broadcast mesh with no
provisioned key storage), opt out explicitly with requireEncryption: false —
each plaintext send then emits a security_warning event with the
PLAINTEXT_SEND reason code (once per peer).
cargo install uniffi --version 0.32.2 --features cli --locked (must match the workspace uniffi = "0.32" pin)cargo install uniffi-bindgen-java --version 0.5.2 --locked (the 0.5 series generates for UniFFI 0.32)ANDROID_NDK_HOME); for iOS: Xcodecd bindings/react-native
# Build for all platforms
npm run build:uniffi:all
# Or build individually
npm run build:uniffi:ios # iOS only
npm run build:uniffi:android # Android only
./scripts/generate-bindings.sh
One script generates all four languages — Swift, Kotlin, Python and Java — because
they are one artifact set produced from one UDL and carry the FFI checksums of
the library they were generated against. Regenerating a subset leaves the rest
describing a different ABI, which no build catches; the app fails at the first
call instead. npm run generate:bindings and the platform build scripts
delegate here, so every path produces the whole set. Commit all four together.
cd bindings/python
bash scripts/build-desktop.sh
pip install -e .
The desktop build produces the native .dylib, .so, or .dll for the host
platform and regenerates the bindings (all four languages, via the shared
script above).
The SDK consists of modular Rust crates:
DORS automatically selects and switches between Internet, BLE Mesh, Wi-Fi Direct, Reticulum, and Nostr based on real-time network conditions. It scores each transport on signal strength, proximity, bandwidth, congestion, energy efficiency, reliability, and available capacity, then applies hysteresis, cooldown, and stability checks to prevent flapping.
For details, see the DORS Deep Dive and DORS Configuration Guide.
The SDK implements a cluster-based, self-organizing mesh network. Devices discover peers via BLE advertisements, form clusters with scored peer connections, and bridge separate clusters automatically.
A message addressed to someone out of radio range is carried by the devices in between: each hands it onward to a bounded set of neighbors until it arrives or runs out of hops. Delivery acknowledgements travel back the same way, so a message that crossed several devices is not mistaken for a lost one. Devices only carry traffic when their own battery policy allows it, and every device caps how much it forwards — per second overall and per neighbor — so a crowded room stays usable rather than filling with repeated copies.
For details, see the Mesh Networking Guide.
See the docs/ directory for detailed guides:
Reference material for anyone implementing against the protocol or changing its behaviour:
cargo build --workspace # Build
cargo test --workspace # Test
cargo clippy --workspace -- -D warnings # Lint
cargo fmt --all # Format
See CONTRIBUTING.md for development guidelines and QUICKSTART.md for platform-specific setup.
Copyright © 2025-2026 Offline Protocol, Inc.
The Offline Protocol SDK is dual-licensed:
You may use the SDK under either license; you do not need both. Contributions are accepted under the terms described in CONTRIBUTING.md.
App-store distribution has consequences under the AGPL — see the Licensing FAQ. And this software contains encryption: EXPORT.md describes its export-control status and what app teams must handle themselves.
Neither license grants rights to the "Offline Protocol" name or logo — see TRADEMARKS.md.
Transport and coordination layer for the disconnected edge. Build apps, agents, and devices that discover peers, communicate securely, and coordinate across BLE, Wi-Fi Direct, internet, Reticulum, and Nostr.