How to Build BitChat from Source for Development
You can build BitChat from source by cloning the repository, running just check to validate your environment, and executing just build to compile the macOS debug version with xcodebuild.
BitChat is a Swift-based dual-transport messenger that combines a local Bluetooth mesh with the internet-wide Nostr protocol. To modify or contribute to the codebase, you must compile the app from the verified source tree available at permissionlesstech/bitchat. The repository uses a lightweight command-line helper (just) and native Xcode configurations that store all generated artifacts in an ignored .DerivedData folder, ensuring tracked source files remain untouched during compilation.
Prerequisites
macOS and Xcode Requirements
Building BitChat requires macOS 13 or later with a full Xcode installation, including command-line tools. The Justfile at the repository root provides a validation command to verify your setup. Running just check executes xcodebuild -version and ensures xcode-select points to the full Xcode bundle rather than standalone command-line tools.
You can verify your environment manually by checking that xcode-select -p returns a path ending in /Xcode.app/Contents/Developer.
Install the Just Command Runner
While optional, the just command runner is the recommended way to invoke build tasks. Install it via Homebrew:
brew install just
All build recipes are defined in the Justfile, including build, run, test, and clean commands that wrap xcodebuild and swift operations.
Configure Code Signing (Optional)
For signed builds, copy the example configuration and add your Apple Developer Team ID:
cp Configs/Local.xcconfig.example Configs/Local.xcconfig
Edit Configs/Local.xcconfig to include your team identifier. For unsigned local development, the build commands automatically disable code signing with CODE_SIGNING_ALLOWED=NO.
Step-by-Step Build Process
Clone the Repository
Clone the source tree and navigate into the directory:
git clone https://github.com/permissionlesstech/bitchat.git
cd bitchat
The repository includes a signed release manifest at docs/VERIFYING-A-BUILD.md that you can use to verify the checkout against published SHA-256 hashes if you require cryptographic assurance.
Validate Your Environment
Before compiling, run the safety check to confirm Xcode availability:
just check
This executes the check-clean-safety script and validates that xcodebuild is accessible and properly configured.
Build the macOS Debug Version
Compile an unsigned debug build suitable for local development:
just build
Under the hood, this executes:
xcodebuild -project "bitchat.xcodeproj" -scheme "bitchat (macOS)" -configuration Debug -derivedDataPath ".DerivedData" CODE_SIGNING_ALLOWED=NO build
All compiled artifacts land in .DerivedData/Build/Products/Debug/bitchat.app. This location is git-ignored, keeping your source directory clean.
Run the App Locally
Launch the freshly built application:
just run
The run recipe opens the .app bundle from the DerivedData folder. Alternatively, open bitchat.xcodeproj in Xcode and press the Run button (▶︎) to launch with the debugger attached.
Execute Test Suites (iOS and SwiftPM)
BitChat includes comprehensive unit tests. Run the full Swift Package Manager test suite with:
just test
This invokes swift test, covering tests located in bitchatTests/ such as VoiceRecorderTests.swift and ChatViewModelTests.swift.
To test the iOS simulator configuration:
just test-ios
This recipe targets the iPhone 17 simulator by default. View available destinations with xcodebuild -showdestinations if you need to target a different device.
Clean Build Artifacts
To remove local build outputs:
just clean
To additionally purge nested package caches within localPackages/ (including .build directories):
just nuke
Both commands respect the repository's "no-source-restoring" policy, ensuring they only delete generated files and never modify tracked source code.
Architecture Overview for Developers
Understanding the codebase structure helps when modifying functionality. The app is organized into distinct transport layers wired together by view models and coordinators.
Bluetooth Mesh Layer
The Bluetooth Mesh handles offline peer-to-peer messaging within BLE range, supporting up to 7-hop multi-relay routing. The mesh logic resides in the bitchat/ Swift module, specifically within bitchat/Noise/SecureNoiseSession.swift and Bluetooth utilities in bitchat/Utils/AppLanguageSettings.swift. This layer uses the Noise Protocol for handshake and encryption.
Nostr Internet Layer
The Nostr layer provides global reach through the Nostr relay network. Location-based channels are defined by geohash precision parameters found in bitchat/Models/RequestSyncPacket.swift.
Hybrid Transport Selection
BitChat first attempts a direct Bluetooth connection; if unavailable, it falls back to Nostr using BitChat-specific private envelopes. This selection logic is implemented using XChaCha20-Poly1305 constructions defined in bitchat/Models/NoisePayload.swift.
Security Model
End-to-end encryption on the mesh uses the Noise Protocol (implemented in bitchat/Noise/SecureNoiseSession.swift), while Nostr payloads are wrapped in custom envelopes as described in the Private Message End-to-End Encryption section of the README. The ChatViewModel and related coordinators (tested in ChatViewModelTests.swift and ChatTransportEventCoordinatorContextTests.swift) manage the switching logic between these transports.
Summary
- Prerequisites: macOS 13+, full Xcode installation, and optionally the
justcommand runner installed via Homebrew. - Environment Check: Run
just checkto validatexcodebuildand developer tool paths before compiling. - Debug Build: Execute
just buildto compile an unsigned macOS app into.DerivedData/Build/Products/Debug/bitchat.app. - Testing: Use
just testfor SwiftPM unit tests orjust test-iosfor simulator-based iOS testing. - Source Safety: All build commands use the
.DerivedDatafolder, ensuring the source tree remains unmodified; cleanup is handled viajust cleanorjust nuke. - Key Files: Build logic is centralized in
Justfile, project settings inbitchat.xcodeproj, and security implementation inbitchat/Noise/SecureNoiseSession.swift.
Frequently Asked Questions
What are the minimum system requirements to build BitChat?
You need macOS 13 or later with a complete Xcode installation, including command-line tools. The just check command validates that xcode-select points to the full Xcode bundle rather than standalone tools. You cannot build BitChat on Linux or Windows because the project relies on Apple-specific frameworks like CoreBluetooth and CryptoKit.
Do I need a paid Apple Developer account to build BitChat?
No. The just build recipe explicitly disables code signing with CODE_SIGNING_ALLOWED=NO, allowing you to compile and run the debug version locally without a developer account. However, if you want to distribute the app or run it on a physical iOS device (rather than the simulator), you must configure a Team ID in Configs/Local.xcconfig, which requires a paid Apple Developer membership.
How do I verify the source code integrity before building?
The repository includes verification instructions in docs/VERIFYING-A-BUILD.md. You can verify your checkout against the release manifest by downloading the SOURCE-MANIFEST.txt from the releases page and running shasum -a 256 -c against the listed hashes. This ensures you are compiling the exact code signed by the maintainers.
Can I build BitChat for iOS without Xcode?
No. While you can use command-line tools like xcodebuild (invoked via just build or just test-ios) without opening the Xcode GUI, you still need the full Xcode application installed. The build process relies on the iOS SDK, simulator runtimes, and Swift compiler bundled with Xcode. You cannot build the iOS target using only Swift Package Manager and the open-source Swift toolchain.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →