flutter_pear
The full Pear peer-to-peer stack as a Dart-idiomatic Flutter plugin. Build serverless, end-to-end-encrypted P2P apps — discovery, encrypted connections, append-only logs, key/value stores, file drives, and multi-writer sync — without writing a line of Kotlin, Swift, or JavaScript.
Platforms: Android (stable, published) · iOS (SIMULATOR-VALIDATED — see iOS platform notes before shipping) · macOS/Linux/Windows desktop (new in 0.3.0 — a real Hyperswarm join, reaching
connected, is confirmed on real hardware for all three; see Desktop dev setup and each platform's own notes for exactly what's covered). Requires Flutter SDK ≥ 3.24 (bundles Dart ≥ 3.5).Status: pre-1.0, published on pub.dev (v0.3.0). The Bare Kit worklet is real (not a stand-in), and every data-structure wrapper (Corestore/Hypercore, Hyperbee, Hyperdrive, Autobase, blind pairing) is implemented and fake-tested end-to-end, with real-worklet validation on a real Android emulator, the iOS Simulator, and real macOS/Linux/Windows desktop hardware. Physical two-device mobile hardware validation is a documented follow-up, not a release gate. See the full repository README for the complete API coverage table.
Something stuck? Check Troubleshooting. Still stuck? Open an issue.
Unofficial. Not affiliated with Holepunch.
Install
flutter pub add flutter_pear
Native binaries and the P2P runtime resolve automatically — Gradle on Android, SwiftPM (with a CocoaPods compat path) on iOS. No manual NDK, ABI, or Podfile edits on either platform.
Pre-1.0: minor versions may break the API without notice. Pin an exact version once you depend on this for real.
Time to hello world (TTHW): P50 ≤ 5 minutes / P90 ≤ 10 minutes of active work, zero flutter_pear-specific build-wiring steps beyond one copy-paste Info.plist block on iOS — "hello world" means the first Android-to-iOS message, not just a successful build.
Quick start — chat over Hyperswarm
Two phones that share a topic find each other over the internet and exchange end-to-end-encrypted messages, no server:
import 'dart:convert';
import 'package:flutter_pear/flutter_pear.dart';
final pear = await Pear.start();
// A topic is a 32-byte rendezvous key both peers agree on out of band.
// unsafeTopicFromString is a GLOBAL, demo-only shortcut -- every device
// worldwide using the same string lands in the same room. Real apps
// derive a topic from a PearPairing invite instead.
final topic = PearCrypto.unsafeTopicFromString('my-secret-room');
final swarm = await pear.join(topic);
swarm.connections.listen((PearConnection conn) {
conn.data.listen((bytes) {
print('peer: ${utf8.decode(bytes)}');
});
conn.write(utf8.encode('hello from Flutter'));
});
// ... later
await swarm.leave();
await pear.dispose();
Expected output on each phone, once the other side's message arrives:
peer: hello from Flutter
Everything is Futures and Streams; keys are a PearKey value type with hex helpers (z-base-32 is planned, not yet implemented).
Enable iOS on an existing Android app
Already on flutter_pear 0.1.x, Android-only? Five steps get you to iOS:
flutter create --platforms=ios .— plain Flutter, nothingflutter_pear-specific.flutter pub add flutter_pear:^0.2.0— explicit, not a bareflutter pub upgrade: that command cannot cross the already-published^0.0.1caret. If you previously pinnedflutter_pear_baredirectly in your ownpubspec.yaml, bump it the same way; ifpub addreports a stale lock conflict, deletepubspec.lockand re-resolve.- Paste this into
ios/Runner/Info.plist(copied from iOS platform notes — see that page for why, and for the full symptom table if you skip this step):
Adjust the description to your own app's actual local-network use — Apple requires it be accurate, not necessarily this exact wording.<key>NSLocalNetworkUsageDescription</key> <string>flutter_pear demos connect directly to your other devices over the local network to exchange chat messages and files.</string> flutter runon an iOS Simulator.- Exchange your first message with an Android peer — same
Pear.start()/join()code as above, no platform branching required for the happy path.
Received-file locations (if your app uses PearDrive/file transfer) differ by platform, matching what flutter_pear_example's own file-drop demo does: iOS saves into a Documents subtree (path_provider's getApplicationDocumentsDirectory()), visible in the Files app; Android saves into the app's private files directory (Context.getFilesDir()/received/), not independently visible — open or share it through your app's own affordance (a FileProvider content URI + ACTION_VIEW, in the example app's case). Neither location is where the worklet's own protocol storage lives — see Storage roots for that.
First-build download UX
Native binaries fetch once, then cache:
- Android: downloads Bare Kit's native binaries, cached under each app's
build/flutter_pear_bare/bare-kit/; delete that directory, or runflutter clean, to force a re-download. - iOS (SwiftPM, the default): downloads the repacked
BareKit.xcframework(~107 MB), cached under~/Library/Caches/org.swift.swiftpm; delete that directory, or runflutter clean, to force a re-download. - iOS (CocoaPods compat path): downloads the same artifact into
ios/Pods/flutter_pear_bare/barekit_cache/<version>/; deleteios/Pods/and re-runpod installto force a re-download.
Both platforms fetch from the same upstream holepunchto/bare-kit release; iOS's SwiftPM/CocoaPods binary-target mechanisms need a single ready-made BareKit.xcframework zip rather than Android's raw ~354 MB multi-platform prebuilds.zip, so flutter_pear republishes just that one framework, repacked and checksum-pinned — see barekit-pin.json for the exact pin chain.
Download-size disclosure (accept-and-disclose, standing decision — pub.dev downloads every dependency's committed files regardless of your target platform, flutter/flutter#130210): flutter_pear_bare's committed iOS addon .xcframeworks (bundled for every consumer, Android-only included) add ~21 MB to that package's own tracked content — measured directly (git ls-files + du), not a pub.dev-computed archive size. The example app's iOS build produces a Runner.app of ~59.7 MB (measured on the simulator archive) — this is an absolute number, not a delta: v0.1 had no iOS build at all to diff against.
Learn more
- Concepts — topics vs. invites, the worklet model, replication, lifecycle.
- How-tos: chat, file sync, pairing.
- iOS platform notes — background execution, the Local Network permission, storage roots.
- Desktop dev setup — building a
flutter_pearapp from Windows or Linux. - Background execution (Android) — what Android actually permits.
- Error catalog — every error code's problem, cause, and fix.
- Troubleshooting — install-time failures that runtime error codes can't catch.
- Full repository README — API coverage table, testing your app, development setup, contributing.
License
flutter_pear is MIT © 2026 Andrew Loable — see LICENSE.
It bundles the Pear stack (Bare Kit + Hyper* modules), which is MIT /
Apache-2.0 — all permissive, no copyleft. Redistributed attributions ship in
THIRD_PARTY_LICENSES (generated at build time). See LICENSING.md
for the full dependency breakdown and obligations.
Libraries
- flutter_pear
- Dart-idiomatic Flutter API for the Pear P2P stack.