# How to Build BitChat from Source for Development

> Learn to build BitChat from source for development. Clone the repo, check your environment, and compile the macOS debug version using just commands.

- Repository: [permissionlesstech/bitchat](https://github.com/permissionlesstech/bitchat)
- Tags: how-to-guide
- Published: 2026-08-22

---

**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:

```bash
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:

```bash
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:

```bash
git clone https://github.com/permissionlesstech/bitchat.git
cd bitchat

```

The repository includes a signed release manifest at [`docs/VERIFYING-A-BUILD.md`](https://github.com/permissionlesstech/bitchat/blob/main/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:

```bash
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:

```bash
just build

```

Under the hood, this executes:

```bash
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:

```bash
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:

```bash
just test

```

This invokes `swift test`, covering tests located in `bitchatTests/` such as [`VoiceRecorderTests.swift`](https://github.com/permissionlesstech/bitchat/blob/main/VoiceRecorderTests.swift) and [`ChatViewModelTests.swift`](https://github.com/permissionlesstech/bitchat/blob/main/ChatViewModelTests.swift).

To test the iOS simulator configuration:

```bash
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:

```bash
just clean

```

To additionally purge nested package caches within `localPackages/` (including `.build` directories):

```bash
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`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Noise/SecureNoiseSession.swift) and Bluetooth utilities in [`bitchat/Utils/AppLanguageSettings.swift`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Models/NoisePayload.swift).

### Security Model

End-to-end encryption on the mesh uses the **Noise Protocol** (implemented in [`bitchat/Noise/SecureNoiseSession.swift`](https://github.com/permissionlesstech/bitchat/blob/main/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`](https://github.com/permissionlesstech/bitchat/blob/main/ChatViewModelTests.swift) and [`ChatTransportEventCoordinatorContextTests.swift`](https://github.com/permissionlesstech/bitchat/blob/main/ChatTransportEventCoordinatorContextTests.swift)) manage the switching logic between these transports.

## Summary

- **Prerequisites**: macOS 13+, full Xcode installation, and optionally the `just` command runner installed via Homebrew.
- **Environment Check**: Run `just check` to validate `xcodebuild` and developer tool paths before compiling.
- **Debug Build**: Execute `just build` to compile an unsigned macOS app into `.DerivedData/Build/Products/Debug/bitchat.app`.
- **Testing**: Use `just test` for SwiftPM unit tests or `just test-ios` for simulator-based iOS testing.
- **Source Safety**: All build commands use the `.DerivedData` folder, ensuring the source tree remains unmodified; cleanup is handled via `just clean` or `just nuke`.
- **Key Files**: Build logic is centralized in `Justfile`, project settings in `bitchat.xcodeproj`, and security implementation in [`bitchat/Noise/SecureNoiseSession.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/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`](https://github.com/permissionlesstech/bitchat/blob/main/docs/VERIFYING-A-BUILD.md). You can verify your checkout against the release manifest by downloading the [`SOURCE-MANIFEST.txt`](https://github.com/permissionlesstech/bitchat/blob/main/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.