How to Contribute to the BitChat Project: A Complete Developer Guide
Contribute to BitChat by forking the repository, setting up a Swift/Xcode environment, running the test suite, and submitting pull requests that follow the dual-transport architecture (Bluetooth mesh + Nostr protocol).
BitChat is a Swift-based, peer-to-peer messaging app that combines Bluetooth Mesh for offline communication and the Nostr protocol for online routing. This guide walks through the exact steps to contribute to BitChat, referencing the actual source files in permissionlesstech/bitchat so you can navigate the codebase with confidence.
Prerequisites for Contributing to BitChat
Before writing any code, ensure your environment matches the project's requirements:
- Xcode 15+ or Swift 5.9+
- macOS for iOS/macOS builds
- just (optional task runner) for convenient commands like
just test-ios - Git and a GitHub account
The project uses standard SwiftPM for dependency management, defined in [Package.swift](https://github.com/permissionlesstech/bitchat/blob/main/Package.swift).
Understanding BitChat's Codebase Architecture
BitChat's source code is organized into logical groups. Knowing these helps you locate where to make changes when you contribute to BitChat.
Step-by-Step: How to Contribute to BitChat
1. Fork and Clone the Repository
Click Fork on GitHub, then clone your fork:
git clone https://github.com/<your-username>/bitchat.git
cd bitchat
2. Configure Local Build Settings
Copy the example configuration to avoid modifying tracked files:
cp Configs/Local.xcconfig.example Configs/Local.xcconfig
The entitlements already use $(APP_GROUP_ID), so no additional changes are needed.
3. Build and Test Before Making Changes
Verify everything works on a clean clone:
# macOS debug build (no code signing required)
xcodebuild -project bitchat.xcodeproj -scheme "bitchat (macOS)" \
-configuration Debug CODE_SIGNING_ALLOWED=NO build
# Run full SwiftPM test suite
swift test
For iOS-specific testing, use:
just test-ios
4. Find an Issue to Work On
Check the Issues tab on GitHub for:
- Bug reports
- Feature requests
- Documentation gaps
5. Create a Feature Branch
Follow standard Git flow:
git checkout -b feat/add-new-command
6. Implement Your Change
Edit the appropriate Swift files. The exact files depend on your contribution type.
7. Run Tests Again
Ensure your changes don't break existing functionality. The CI will reject PRs that reduce test coverage.
8. Commit, Push, and Open a PR
Write a concise commit message, push your branch, and open a Pull Request against main.
9. Address Review Feedback
Apply requested tweaks, push new commits, and wait for merge.
Code Examples: Common Contribution Patterns
Adding a New Slash Command
Edit [bitchat/Models/CommandInfo.swift](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Models/CommandInfo.swift):
enum CommandInfo: String {
case help = "/help"
case slap = "/slap"
// NEW: greet command
case greet = "/greet"
}
Extending the Nostr Private Envelope
Edit [bitchat/Nostr/NostrProtocol.swift](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Nostr/NostrProtocol.swift):
extension NostrProtocol {
static let privateEnvelopeKind = 1059 // existing BitChat envelope kind
// NEW: custom encryption identifier
static let customEncryptionTag = "xchaCha20-poly1305"
}
Writing a Unit Test for Your Feature
Create [bitchatTests/CommandInfoTests.swift](https://github.com/permissionlesstech/bitchat/blob/main/bitchatTests/):
import XCTest
@testable import bitchat
final class CommandInfoTests: XCTestCase {
func testGreetCommandIsRecognized() {
XCTAssertEqual(CommandInfo(rawValue: "/greet"), .greet)
}
}
Adding User-Facing Strings
Update bitchat/Localizable.xcstrings:
{
"app_info.features.greet.title": {
"type": "text",
"value": "Send a friendly greeting"
}
}
Best Practices for BitChat Contributors
- Stay on the
mainbranch — CI runs on every PR againstmain - Never edit tracked configuration files directly — use
Local.xcconfigfor local overrides - Write tests — coverage requirements are enforced in CI
- Respect the dual-transport architecture — new features must work over both Bluetooth mesh and Nostr; add transport-agnostic logic to the
Synclayer (e.g.,GossipSyncManager)
Key Documentation Resources
| Resource | Purpose |
|---|---|
[README.md](https://github.com/permissionlesstech/bitchat/blob/main/README.md) |
Project overview and quick-start |
[docs/ARCHITECTURE_V2.md](https://github.com/permissionlesstech/bitchat/blob/main/docs/ARCHITECTURE_V2.md) |
Detailed architecture diagrams |
[WHITEPAPER.md](https://github.com/permissionlesstech/bitchat/blob/main/WHITEPAPER.md) |
Cryptography, privacy, and mesh design |
Summary
- Fork and clone
permissionlesstech/bitchatto begin - Use
Local.xcconfigfor local build settings without modifying tracked files - Build with
xcodebuildorjust test-iosto verify your environment - Reference the six code groups (Core networking, Nostr, Bluetooth, Models, Tests, Documentation) to find where changes belong
- Add tests for every feature — CI enforces coverage requirements
- Maintain dual-transport compatibility — use
GossipSyncManagerfor transport-agnostic logic
Frequently Asked Questions
What programming language is BitChat written in?
BitChat is written in Swift and uses SwiftPM for dependency management. The minimum required version is Swift 5.9 or Xcode 15.
Do I need an iOS device to contribute to BitChat?
No. You can build and test the macOS target without code signing using CODE_SIGNING_ALLOWED=NO, or run the SwiftPM test suite with swift test. Physical iOS devices are only needed for testing Bluetooth mesh functionality.
Where should I add new networking features in BitChat?
Add transport-agnostic logic to [Sync/GossipSyncManager.swift](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Sync/GossipSyncManager.swift). This is the canonical location for features that must work over both Bluetooth mesh and Nostr relays. Transport-specific code belongs in [Nostr/NostrProtocol.swift](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/Nostr/NostrProtocol.swift) or the BLE implementation files.
How does BitChat handle configuration without exposing secrets?
The project uses a layered configuration system. Copy Configs/Local.xcconfig.example to Configs/Local.xcconfig for your local settings. This file is gitignored, so your changes stay local. The entitlements reference $(APP_GROUP_ID) which resolves through this local config.
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 →