Offline-first mesh messenger for blackouts, disasters and crowded places. Bluetooth LE mesh when there is no network. Nostr when there is. No accounts, no phone numbers, no servers.
Download APK · Protocol spec · Roadmap · Contributing · Security · 中文说明
Design prototype in dark mode. The app implements this direction.
When the network goes down, the phones in a building, a stadium or a neighbourhood can still talk to each other over Bluetooth. Every phone relays for every other phone, so a message hops from person to person until it reaches someone it was meant for. That is what the bitchat protocol does, and its protocol, code and whitepaper are public domain.
openchat is an independent, MIT-licensed client for that same network, built with three differences in mind:
- For people who have never seen IRC. The people who install a mesh messenger during an outage are not terminal people. Three taps from install to first message, with the phone offline, is the bar. The mesh itself is made visible: a signal band, a delivery path on every message, hop counts, identity emblems, and a designed "nobody nearby" screen instead of an empty list.
- Positioned for infrastructure failure, not politics. Earthquakes, typhoons, carrier outages, festival and stadium congestion, hiking and sailing. It is not a censorship-circumvention tool and is not marketed as one.
- Protocol compatible, always. An openchat phone must be a working relay for every bitchat phone and vice versa. Interop with upstream is a release gate, not a feature.
| State | |
|---|---|
| Android app | v0.6.0 preview. Builds, 161 unit tests pass, 8.8 MB APK, 18 languages |
| Interop with stock bitchat | Not yet verified. Implemented from the spec and upstream test vectors; verification against a stock bitchat client is the next milestone |
| Security audit | None. Everything on the wire is upstream's; upstream had one audit (Cure53, 2025-11) with findings still open |
| iOS | Not started |
| Release signing | v0.6.0 and later carry a dedicated release key; its certificate fingerprint is in SECURITY.md. Previews up to v0.5.0 were debug-signed. Verify the APK SHA-256 in the release notes |
Do not rely on openchat where being identified has serious consequences. The app says so on first launch. See SECURITY.md.
On the mesh, with no network at all
- Bluetooth LE mesh: every phone is both peripheral and central, with multi-hop relay, dedup, TTL and fragmentation per the wire spec.
- A signed public Nearby channel that everyone in range can read.
- Private messages end-to-end encrypted with Noise XX, with delivered and read receipts. Relaying phones cannot read them.
- Store-and-forward: an outbox plus courier envelopes that nearby phones carry for you, so a message can reach someone who was not in range when you sent it.
- History sync: late joiners receive the last 15 minutes of public messages from a neighbour.
- Photos and voice notes, public or Noise-encrypted private.
- In-person verification with bitchat's
bitchat://verifyQR code plus a Noise challenge. - Every nickname carries a
#xxxxsuffix derived from the peer ID, so two people with the same name cannot be confused.
When there is internet
- Location channels over Nostr, keyed by geohash, with one anonymous key per cell. Same relays as bitchat, so the rooms are shared.
- Private messages over Nostr between mutual favorites, in bitchat's envelope format.
- Relay traffic goes through Tor by default, fail-closed.
Safety and everyday use
- No account, no phone number, no email. Keys are generated on first launch.
- Triple-tap the title to wipe everything and start with a new identity. No confirmation dialog, by design.
- Share the app offline: send the APK to the phone next to you over Bluetooth or Quick Share. No app store needed, which matters when the app store is unreachable.
- Keeps relaying with the screen off. Block people. @mentions. IRC-style slash commands for those who want them.
- 18 languages, including right-to-left Arabic and Persian. Machine drafted; native speakers welcome.
Full feature-to-file map in android/README.md.
![]() Nearby: direct 3, reach 11, every message shows its hops |
![]() Private: a delivery path on every message, red with a retry when it fails |
![]() Nobody nearby: the most common state, so it gets a real screen |
From the clickable prototype in docs/design/ui-prototype.html; the design rationale is in docs/design/ui-direction.md. Sample nicknames are historical figures.
-
Download the APK from the latest release. Android 8.0 or newer.
-
Check the hash against the release notes before installing, especially if the file reached you phone to phone:
shasum -a 256 openchat-*.apk -
Grant Bluetooth and nearby-devices permission. Android requires the location permission for BLE scanning; openchat does not read your location for the mesh.
-
Open the Me tab and tap Share the app to pass the installer to the phones around you. Do this before the outage.
| bitchat | openchat | |
|---|---|---|
| Wire protocol | bitchat's | Identical. Same packets, same Noise handshake, same Nostr envelopes |
| Code | iOS: public domain. Android: GPL-3.0 | Written from scratch in Kotlin. No bitchat source is used. The GPL Android code was never read |
| Licence | Unlicense / GPL-3.0 | MIT |
| Who it is for | "IRC vibes", by design | People who have never seen IRC |
| Positioning | General purpose | Infrastructure failure |
| Relationship | — | Independent client. Not affiliated with or endorsed by the bitchat project |
The protocol was reverse-documented from the public-domain iOS source into docs/protocol-spec.md, a byte-level specification that did not exist before. If you are building anything that talks to bitchat, that document and docs/bitchat-protocol-notes.md may be useful on their own.
| Document | What it is |
|---|---|
| docs/protocol-spec.md | Byte-level wire spec openchat implements: headers, TLVs, Noise XX, courier envelopes, sync, Nostr embedding |
| docs/bitchat-protocol-notes.md | What the upstream protocol actually does, with numbers, audit history and open issues |
| docs/phase0-findings.md | 183 App Store reviews and 764 upstream issues classified; the go/no-go that started this |
| docs/design/ui-direction.md | The UI direction: two layers, five elements, why the mesh is visible |
| docs/roadmap.md | Phases, exit criteria and the conditions under which this project stops |
| CHANGELOG.md | Every release, with commit and APK hash |
Requires JDK 17 and the Android SDK with platform 36.
cd android
echo "sdk.dir=$HOME/Library/Android/sdk" > local.properties
./gradlew :app:testDebugUnitTest :app:assembleDebugThe debug APK lands in app/build/outputs/apk/debug/. Release previews
are built with assembleRelease (R8, ARM only, about 9 MB).
Issues, interop reports, translations and field notes are all welcome. Three rules are firm, and CONTRIBUTING.md explains why:
- Clean room. If you have read bitchat-android source code, you cannot contribute Kotlin here. The MIT licence depends on it.
- Interop is a release gate. Nothing ships that breaks compatibility with a stock bitchat phone.
- Positioning is not negotiable. No circumvention features or marketing, no security claims that have not been audited.
Commits are signed off under the Developer Certificate of Origin. There is no CLA.
Android first, from scratch, against the spec. Then interop verification against stock bitchat, then iOS, then one real pilot in a disaster-preparedness drill or a crowded venue. Each phase has an exit criterion and a kill condition in docs/roadmap.md.
"openchat" is a working name and collides with several unrelated LLM projects on GitHub. A final name is pending; the repository will redirect when it changes.
MIT for everything in this repository, see LICENSE. No upstream code is included. Third-party components and their licences are listed in NOTICE.
Built on the work of the bitchat contributors, whose decision to put the protocol in the public domain made an independent client possible. Not affiliated with or endorsed by them.


