MeshCore Open: a Flutter client for LoRa mesh radios
Open-source Flutter client for MeshCore LoRa mesh networking devices
At a glance
- What is it?
- MeshCore Open is an MIT licensed Flutter client that talks to MeshCore LoRa radios over Bluetooth Low Energy, USB serial or TCP, with channels, a node map and a repeater hub on top. The transport you pick decides which build you can use, because the browser version is USB only.
- Who is it for?
- MeshCore Open fits builders and field operators who already run MeshCore companion firmware and want one client across phones, desktops and a Chrome tab, and the MIT licence keeps commercial use open. It does not fit teams that need Bluetooth Low Energy in a browser, image features on a device without a translation or inference backend, or Android notification replies off Android.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Dart, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Three transports, three different reach
MeshCore Open does not implement LoRa itself. It is the client side of a MeshCore setup, and the radio does the actual long range work while the app does the talking to it. The project describes itself as a cross platform application for communicating with MeshCore LoRa mesh radios over Bluetooth Low Energy, USB serial or TCP, and the choice among those three is the first decision an adopter has to make.
The protocol layer visible in the project layout is the Nordic UART Service over Bluetooth Low Energy. That means the app expects a radio that presents a NUS style serial profile rather than any arbitrary BLE device, and a radio running companion firmware is a stated prerequisite before a connection will even be attempted. USB serial covers tethered setups where the radio is plugged into a laptop, and TCP covers the case where the radio is already reachable over a network link.
Each transport brings its own failure surface. Bluetooth fails through range and pairing, USB fails through driver and permission handling, and TCP fails through address and port reachability. The app covers all three in the same interface, so a user moving from a phone in the field to a laptop at a base camp keeps the same channels, contacts and map. A platform support table in the project documentation states that the BLE, USB and TCP companion paths are all implemented on Android, Linux, Windows and macOS, while iOS covers BLE and TCP but not USB.
The browser build is USB only and demands Chrome
The web client is the sharpest constraint in the whole project. It runs in Chrome, and in Chromium based browsers that identify as Chrome, such as Edge or Brave. It talks to a radio over Web Serial. Bluetooth Low Energy and TCP are both marked as unavailable in the browser, and Firefox and Safari are excluded because they do not support Web Serial.
That narrows the practical scenarios considerably. A web deployment cannot scan for nearby mesh nodes over Bluetooth, and it cannot reach a radio on a TCP link. If your only access to a radio is Bluetooth, the browser build is not an option and you need a native build. The web client also needs a secure origin for Web Serial to work, so a plain file served over an insecure channel is not going to be enough.
The feature matrix is explicit that the browser edition still carries the core functionality, the mesh network tools, the map and location views, device management and the repeater hub. In other words, the browser client is a full participant in the mesh, just a single transport. The project also pins a specific Flutter release for the web deployment and keeps the Dart SDK constraint at `^3.9.2`, so rebuilding the web client yourself is a deliberate act rather than a casual one.
A shared PSK and matching radio settings come first
Connecting to a radio is only the start of the workflow. Once the app synchronizes with the device, the user opens a channel to broadcast or opens Contacts to send a direct message, and at that point compatibility becomes the deciding factor. Peers need compatible radio settings, and channels need the same PSK.
That requirement is a hard one and worth stating plainly. A channel in this system is not a public radio channel in the traditional sense, it is a keyed group, and a node that does not hold the same pre shared key simply will not hear it. The same applies to private messages, which the project describes as end to end encrypted conversations with individual contacts using the MeshCore protocol.
The channel model is broad. The feature list names public, hashtag, private and community channels, so a deployment can run an open discussion, a topic scoped by hashtag, a private group, or a community space. Messages inside a channel can carry compressed images with optional recovery packets, and threads support inline replies plus reactions. Regions add a second scoping layer, letting a flood and a reply be limited to the region a message is known to have travelled through. None of that works until the peers agree on keys and radio parameters, which is why the first real use of this app is a configuration task as much as a messaging one.
Building from source means running two short scripts
Downloads, the Obtainium route and the web client are all gathered on the project installation site, so most people never touch a source build. When you do build, the interesting part of the repository is a small package.json at the root. It is not a Node dependency manifest in any meaningful sense, it holds two scripts, one to build and one to deploy.
"scripts": {
"build": "dart run build_pipe:build",
"deploy": "bun x wrangler deploy"
}The build script hands off to a Dart package called build_pipe, and the deploy script shells out to wrangler through bun. The presence of a wrangler.toml at the repository root, alongside a web directory, a cloudflare workers style deployment path and a package.json with a bun based deploy command, points to the web client being hosted rather than bundled by the Flutter build itself. The repository also carries platform folders for android, ios, linux, macos and windows, a test directory, a scripts directory and a tools directory, alongside l10n.yaml and untranslated.json for localization.
The three step first use sequence in the project documentation is short enough to repeat exactly as written, and it is worth following in order, because the first step is a hardware and firmware prerequisite rather than an app action.
1. Use a MeshCore radio running companion firmware with the transport you intend to use.
2. Open the app, scan for BLE devices or select USB/TCP, and connect.
3. After synchronization, open a channel to broadcast or open Contacts to send a direct message. Peers need compatible radio settings; channels need the same PSK.Offline maps need a Stadia Maps key that you supply
The map and location section of the app is more demanding than the messaging section. There is a live map view that visualizes mesh network nodes in real time, filtering by node type such as chat, repeater or sensor and by time range. Coordinates and custom markers can be shared with contacts, and the app supports the Military Grid Reference System format for people whose local usage is grid based rather than decimal degrees.
The part that costs money is offline tiles. The project states that map tiles can be downloaded for offline use in remote areas using a configured Stadia Maps source and API key, and points to a map setup document for the details. Offline tiles are the whole point for off grid deployments, since a mesh user in the field frequently has no usable data connection, and downloading a region means choosing the source and entering a key before the tiles exist on disk. The project does not bundle a tile source of its own, so this is a configuration step the adopter has to complete before the map is useful away from coverage.
Map data, image models and cached tiles are described as files on disk, while messages and contacts live in JSON in SharedPreferences. That split is worth knowing if you plan to back up an install, since the durable conversational record and the heavy cached assets do not sit in the same place.
Notification replies stop at the Android boundary
Almost every capability in the feature list is available on every platform, which makes the exceptions more meaningful. The platform table lists notification replies as supported on Android only, explicitly including Android Auto and watches, and marks every other platform as unsupported for that row.
The feature is a genuinely different interaction model. The project describes hearing messages and replying by voice in Android Auto, and replying from the notification shade or from Wear OS and Galaxy watches. On other platforms, notifications are not part of the picture at all. If your workflow depends on talking to a mesh from a moving vehicle or from a watch on your wrist, this client on iOS, Linux, Windows, macOS or the web will not cover that case, and no configuration change appears in the documentation that would change it.
The mesh network section is broader. The app shows routing paths and signal quality for each contact, allows manual path overriding and automatic route rotation, tracks SNR in real time, discovers nearby nodes automatically, and can connect to and manage repeater nodes for extended range. A repeater hub section adds a command line interface to repeater nodes, settings for repeater behaviour, power limits and network options, a statistics dashboard covering traffic, connected clients and system health, and remote administration of repeaters from anywhere on the mesh.
Beta tagged releases and a recent last push
The project is under MIT licence, which keeps commercial use and redistribution open for anyone embedding this client in their own tooling. The repository is not archived, and the last push was on 2026-10-19, so the code was changing days before this review.
The release naming is the thing to read carefully. The recent tags are BETA-99.0.0 from 2026-10-12, PRE-BETA-9.5.2 from 2026-09-28 and PRE-BETA-9.5.1 from 2026-08-11. The project is therefore shipping pre beta and beta builds rather than a stable line, and the version numbers jump from the 9.x pre beta series to a 99 series beta. A version scheme that changes shape between release families is a sign that a downstream packager should pin an exact tag and re test on each bump instead of tracking a branch.
The documentation set is broad for a client of this size, split across user documentation, a scanner and connection guide, a troubleshooting file and separate guides for image messages, regions, notifications and map and location setup. The top level also carries AGENTS.md, CLAUDE.md, CONTRIBUTING.md, a TESTFLIGHT_GUIDE.md and a flake.nix, which points to a fairly deliberate contribution and build environment. What the documentation set does not spell out, from what is visible here, is a migration path between the pre beta and beta numbering, so treat the jump as a breaking change until told otherwise.
Editorial conclusion
MeshCore Open fits builders and field operators who already run MeshCore companion firmware and want one client across phones, desktops and a Chrome tab, and the MIT licence keeps commercial use open. It does not fit teams that need Bluetooth Low Energy in a browser, image features on a device without a translation or inference backend, or Android notification replies off Android. Before you commit, verify that your radio firmware exposes a transport the app can reach, that every peer uses the same channel PSK and compatible radio settings, and that you are willing to run a beta tagged release, since the last published build is BETA-99.0.0.
Frequently asked questions
How do I install MeshCore Open on my phone or desktop?
The project installation site collects the available downloads, the Obtainium option and the web client. Building from source is also possible, and the repository ships a package.json whose build script runs dart run build_pipe:build.
Can I use MeshCore Open in a browser with a Bluetooth radio?
No. The web client connects over USB with Web Serial and needs Chrome or a Chromium browser that identifies as Chrome, while Bluetooth Low Energy and TCP are marked as unavailable in the browser. Firefox and Safari do not support Web Serial.
What must two peers match before they can talk on a channel?
Peers need compatible radio settings, and every node joining a channel needs the same PSK. Channels come in public, hashtag, private and community forms, and private messages are end to end encrypted with the MeshCore protocol.
Does offline map download work out of the box?
No. Tiles are downloaded using a configured Stadia Maps source and API key, so you have to supply the source and key through the map setup before tiles are available for offline use.
Is the app still being worked on?
The repository is not archived and the last push was on 2026-10-19. The most recent published build is BETA-99.0.0 from 2026-10-12, following PRE-BETA-9.5.2 from 2026-09-28.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/zjs81-meshcore-open)Was this useful?