A decentralized peer-to-peer messaging app with dual transport architecture: local Bluetooth mesh networks for offline communication and internet-based Nostr protocol for global reach. No accounts, no phone numbers, no central servers. It's the side-groupchat.
Install from the App Store, or build from source you have verified. A compiled build from anywhere else cannot be verified — see Verifying bitchat for how to check source against the per-release hash manifest, and for what to do if that is the only build you can get.
This matters more than it usually would: this repository has been the target of takedown demands, and when a repository or releases page disappears, mirrors appear that nobody can check.
License
This project is released into the public domain. See the LICENSE file for details.
Features
Dual Transport Architecture: Bluetooth mesh for offline + Nostr protocol for internet-based messaging
Location-Based Channels: Geographic chat rooms using geohash coordinates over global Nostr relays
Intelligent Message Routing: Automatically chooses best transport (Bluetooth → Nostr fallback)
Decentralized Mesh Network: Automatic peer discovery and multi-hop message relay over Bluetooth LE
Privacy First: No accounts, no phone numbers, no servers. Note that the mesh does use a persistent per-device identifier derived from your identity key — see on identity and metadata for what a nearby radio can observe
BitChat uses a hybrid messaging architecture with two complementary transport layers:
Bluetooth Mesh Network (Offline)
Local Communication: Direct peer-to-peer within Bluetooth range
Multi-hop Relay: Messages route through nearby devices (max 7 hops)
No Internet Required: Works completely offline in disaster scenarios
Noise Protocol Encryption: End-to-end encryption, with forward secrecy for live sessions (store-and-forward mail is sealed without it — see the whitepaper)
Binary Protocol: Compact packet format optimized for Bluetooth LE constraints
Automatic Discovery: Peer discovery and connection management
Adaptive Power: Battery-optimized duty cycling
Nostr Protocol (Internet)
Global Reach: Connect with users worldwide via internet relays
Location Channels: Geographic chat rooms using geohash coordinates
290+ Relay Network: Distributed across the globe for reliability
BitChat Private Envelopes: App-specific encrypted private messages over Nostr relays
Ephemeral Keys: Fresh cryptographic identity per geohash area
BitChat's private-envelope format is proprietary and is not NIP-17,
NIP-44, or NIP-59 compatible. It uses Nostr as a relay transport but only
interoperates with BitChat clients: private payloads travel inside kind-1059
events whose v2:-prefixed content is a BitChat-specific XChaCha20-Poly1305
construction, not NIP-44 encryption.
Channel Types
mesh #bluetooth
Transport: Bluetooth Low Energy mesh network
Scope: Local devices within multi-hop range
Internet: Not required
Use Case: Offline communication, protests, disasters, remote areas
Location Channels (block #dr5rsj7, neighborhood #dr5rs, country #dr)
Transport: Nostr protocol over internet
Scope: Geographic areas defined by geohash precision
block (7 chars): City block level
neighborhood (6 chars): District/neighborhood
city (5 chars): City level
province (4 chars): State/province
region (2 chars): Country/large region
Internet: Required (connects to Nostr relays)
Use Case: Location-based community chat, local events, regional discussions
Direct Message Routing
Private messages use intelligent transport selection:
Local.xcconfig.example derives unique app and App Group identifiers from that
team ID. The entitlement files already reference $(APP_GROUP_ID), so tracked
project or entitlement files do not need to be edited.
Useful command-line checks from the repository root:
# macOS Debug build without signing
xcodebuild -project bitchat.xcodeproj -scheme "bitchat (macOS)" \
-configuration Debug CODE_SIGNING_ALLOWED=NO build
# Full SwiftPM test suite
swift test# iOS simulator tests
xcodebuild -project bitchat.xcodeproj -scheme "bitchat (iOS)" \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 17'test
If iPhone 17 is unavailable, choose an installed simulator from:
just build and just run use the current bitchat (macOS) scheme and keep
Xcode output in the ignored .DerivedData/ directory. They never patch source,
project, configuration, or entitlement files.
just clean removes only .DerivedData/ and .build/. It does not invoke Git
or restore tracked files, so uncommitted work is preserved. just test runs the
SwiftPM suite and just test-ios runs the iPhone 17 simulator suite.
Localization
App localizations live in bitchat/Localizable.xcstrings.
Share extension strings are separate in bitchatShareExtension/Localization/Localizable.xcstrings.
Prefer keys that describe intent (app_info.features.offline.title) and reuse existing ones where possible.
Run xcodebuild -project bitchat.xcodeproj -scheme "bitchat (macOS)" -configuration Debug CODE_SIGNING_ALLOWED=NO build to compile-check any localization updates.