Up-to-date mirror of Bitchat software
  • Swift 99%
  • Python 0.4%
  • Shell 0.3%
  • Rust 0.2%
Find a file
callebtc 04995f68e4
Port the Android globe geohash picker to iOS (#1807)
* Port the Android globe geohash picker to iOS

Adds the 3D globe picker from bitchat-android: a map button next to the
geohash field opens a full-screen orthographic globe (Natural Earth land,
borders and cities, geohash grid, crosshair) with drag/fling, pinch, tap
and double-tap, precision buttons and a fly-in to the current geohash.
Selecting teleports like typing a geohash.

Beyond a straight port:
- Fix ocean painted as land: the point-in-ring test counted the
  antimeridian seam as a crossing for Eurasia, flipping its fill over the
  Pacific and Atlantic. Android has the same bug.
- Motion detail only steps down within one gesture, so layers no longer
  flash on and off while dragging.
- The geohash grid and city dots draw at every detail level instead of
  vanishing while the globe moves.

Extracts GeohashCoverage so the sheet and picker share the cell-size
string, and adds the picker strings in all locales.

* Let the globe reach polar targets past the drag limit

A polar cell's center can lie past the ±89° drag limit (zzzz is at
89.91°). The animated intro clamped its latitude there and selected
zzzf, while the Reduce Motion path kept zzzz. Animations now always
reach their target; dragging keeps the limit on the far side and never
snaps a polar view back to it.
2026-10-25 02:55:00 +02:00
.github/workflows ci: prevent manual source manifests from overwriting releases (#1636) 2026-09-24 09:35:29 +02:00
bitchat Port the Android globe geohash picker to iOS (#1807) 2026-10-25 02:55:00 +02:00
bitchat.xcodeproj build(deps): bump swift-secp256k1 from 0.21.1 to 0.24.0 (#1782) 2026-10-23 20:22:42 +02:00
bitchatShareExtension Require review before importing shared content (#1430) 2026-07-26 11:40:17 +02:00
bitchatTests Port the Android globe geohash picker to iOS (#1807) 2026-10-25 02:55:00 +02:00
Configs Bump version to 1.8.0 (#1796) 2026-10-23 22:17:57 +02:00
docs docs: why rotating the service UUID does not work (#1704) 2026-09-24 09:35:39 +02:00
localPackages Fix geochat timeline scrolling and cut per-row render work (#1790) 2026-10-23 20:24:06 +02:00
relays Automated update of relay data - Sun Jul 26 06:54:16 UTC 2026 2026-07-26 06:54:16 +00:00
scripts Validate relay-directory changes in PR CI (#1711) 2026-09-24 09:35:18 +02:00
.gitattributes Prevent Github Languages stats skewing (#630) 2025-09-16 06:42:36 -07:00
.gitignore Pin announce signing keys to stop mesh identity spoofing (#1349) 2026-07-26 11:38:24 +02:00
.periphery.baseline.json Link layer slice 5: BLELinkEvent — the port has a name, the delegates have their own files (#1551) 2026-07-30 09:27:34 +01:00
.periphery.yml Quality pass on the 1.7.0 batch: fix confirmed bugs, bump to 1.7.1 (#1418) 2026-07-09 16:44:02 +02:00
.swiftlint.yml Make SwiftLint blocking in CI now that the violation backlog is zero (#1646) 2026-08-08 12:12:30 +02:00
BRING_THE_NOISE.md Perf: Add final to classes that are not inherited (#574) 2025-09-11 19:17:04 +02:00
Justfile Fix $$ escaping that broke every Xcode just recipe (#1525) 2026-07-30 17:56:32 +01:00
LICENSE Add public domain license and copyright headers 2025-07-04 16:21:49 +02:00
Package.resolved build(deps): bump swift-secp256k1 from 0.21.1 to 0.24.0 (#1782) 2026-10-23 20:22:42 +02:00
Package.swift Port the Android globe geohash picker to iOS (#1807) 2026-10-25 02:55:00 +02:00
PRIVACY_POLICY.md Keep working when the network is hostile, and make the app verifiable (#1486) 2026-07-26 19:45:37 +02:00
README.md chore: fix receive typo and refresh relay count in README (#1510) 2026-07-30 17:56:52 +01:00
SECURITY.md Add a real security policy (#1489) 2026-07-26 21:33:59 +02:00
WHITEPAPER.md docs: correct inaccurate privacy and metadata claims (#1485) 2026-07-26 19:02:26 +02:00

icon_128x128@2x

bitchat

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.

bitchat.free

📲 App Store

📲 Play Store

Getting a copy you can trust

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 the whitepaper on identity and metadata for what a nearby radio can observe
  • Private Message End-to-End Encryption: Noise Protocol for mesh, BitChat private envelopes for Nostr fallback
  • IRC-Style Commands: Familiar /slap, /msg, /who style interface
  • Universal App: Native support for iOS and macOS
  • Emergency Wipe: Triple-tap to instantly clear all data
  • Performance Optimizations: LZ4 message compression, adaptive battery modes, and optimized networking

Technical Architecture

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
  • 440+ 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:

  1. Bluetooth First (preferred when available)

    • Direct connection with established Noise session
    • Fastest and most private option
  2. Nostr Fallback (when Bluetooth unavailable)

    • Uses recipient's Nostr public key
    • BitChat's app-specific private-envelope encryption
    • Routes through global relay network
  3. Smart Queuing (when neither available)

    • Messages queued until transport becomes available
    • Automatic delivery when connection established

For detailed protocol documentation, see the Technical Whitepaper.

Setup

Option 1: Using Xcode

open bitchat.xcodeproj

For a signed device build, create your ignored local configuration and replace the example team ID with your Apple Developer Team ID:

cp Configs/Local.xcconfig.example Configs/Local.xcconfig

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:

xcodebuild -showdestinations -project bitchat.xcodeproj -scheme "bitchat (iOS)"

Option 2: Using just

brew install just
just check
just run

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.