How to Contribute to the BitChat Project: A Complete Developer Guide
Contributing to BitChat requires setting up a Swift development environment with Xcode, running just check to validate your setup, and following a 12-step workflow that includes building the app, running tests with just test, linting with SwiftLint, and scanning for dead code with Periphery before submitting a pull request.
BitChat is an open-source, dual-transport messaging app that combines Bluetooth mesh networking with Nostr protocol integration. This guide walks you through the complete contribution workflow as implemented in the permissionlesstech/bitchat repository, from initial setup to merged pull request.
Fork and Clone the Repository
Start by creating your own copy of the codebase. Fork the repository on GitHub, then clone your fork locally:
git clone https://github.com/<your-username>/bitchat.git
cd bitchat
Working on a fork keeps the upstream history clean and allows you to propose changes through pull requests.
Install Development Dependencies
BitChat's build system relies on several tools that must be installed before you can compile or test the code:
- Xcode 13+ — provides the Swift toolchain used by CI
- just — runs reproducible build and test commands (
brew install just) - SwiftLint — enforces style guidelines (
brew install swiftlint) - Periphery — detects unused Swift symbols (
brew install periphery)
These tools are referenced throughout the Justfile and CI configuration, ensuring consistency between local development and automated checks.
Validate Your Environment
Before making changes, confirm your setup is complete:
just check
This command verifies that Xcode is selected, xcodebuild is available, and you have a full Xcode installation. A full install is required because BitChat's Bluetooth and UI tests depend on frameworks that ship only with the complete Xcode bundle, not the command-line tools alone.
Build and Run the App Locally
Verify the project compiles with your current configuration:
just build # macOS Debug build (no signing needed)
just run # launches the built app
The macOS build is the fastest way to test changes during development. If the app launches successfully, you can proceed to automated testing.
Run the Test Suite
BitChat uses Swift Package Manager for dependency management and testing. Execute the full test suite with:
just test
This runs unit tests for core logic including cryptography, sync mechanisms, and mesh routing. The same command executes in CI via .github/workflows/swift-tests.yml, so local failures will block your pull request.
iOS Simulator Tests
For changes affecting the UI layer or Bluetooth handling, run iOS-specific tests:
just test-ios
This targets the "iPhone 17" simulator by default, validating iOS-specific code paths that the macOS build cannot exercise.
Enforce Code Quality Standards
BitChat maintains strict quality gates that run automatically in CI. You must pass these locally before submitting.
Lint with SwiftLint
swiftlint lint --strict
The .swiftlint.yml configuration intentionally disables several rules (line_length, type_name, force_try) but CI will reject any violations of enabled rules. Respect the disabled rules in your code — they may be enabled in future versions.
Scan for Dead Code
periphery scan
Periphery detects unused Swift symbols. The repository includes a baseline file (.periphery.baseline.json) that documents known dead code. New dead code must either be removed or added to the baseline with justification.
Update Documentation
BitChat relies on self-contained documentation in the docs/ directory. Update relevant files when you:
- Add public-facing features
- Change build steps
- Modify architecture patterns
Key documentation files include:
docs/VERIFYING-A-BUILD.md— build verification stepsdocs/BITCHAT-ARCHITECTURE.md— technical architecture overviewREADME.md— project overview and quick start
Keeping documentation current prevents broken builds for downstream users.
Commit and Push Your Changes
Create a descriptive branch name that indicates the change type:
git checkout -b feature/mesh-routing-improvements
# or
git checkout -b fix/swiftlint-warnings
After making changes and running all local checks:
git add .
git commit -m "feat: improve mesh routing efficiency for large networks"
git push origin feature/mesh-routing-improvements
Use clear commit messages that describe what changed and why.
Open and Complete a Pull Request
On GitHub, open a pull request against the main branch. Include in your description:
- Concise summary of changes
- Related issue number (if applicable)
- Verification checklist: tests pass, lint passes, docs updated
CI automatically runs the full test matrix, lint, and Periphery checks. A green check suite is required before maintainers can merge. Respond promptly to reviewer feedback, re-running just test and swiftlint locally before pushing updates.
Key Contribution Practices
Follow these practices to ensure smooth integration:
- Never commit generated files — use
just cleanorjust nuketo purge.DerivedData,.build, and package caches - Run performance checks — execute
scripts/check-perf-floors.shif you modify message handling, compression, or routing algorithms - Add unit tests — place tests in
bitchatTests/following the existing module structure (Sync,Models,VoiceCapture) - Preserve
Local.xcconfig.example— only modify the actualLocal.xcconfigwhich is ignored by Git
Essential Files for Contributors
| File | Purpose |
|---|---|
Justfile |
Developer command shortcuts (just build, just test, just check) |
.swiftlint.yml |
Style configuration and disabled rules |
.periphery.yml |
Dead-code scan configuration |
.github/workflows/swift-tests.yml |
CI matrix definition |
Package.swift |
SwiftPM dependencies and targets |
bitchat/ |
Core app source |
bitchatTests/ |
Unit and integration tests |
docs/ |
Architecture and verification documentation |
scripts/ |
Performance and validation scripts |
Summary
- Fork and clone the repository to your GitHub account
- Install Xcode, just, SwiftLint, and Periphery for the complete toolchain
- Run
just checkto validate your environment before making changes - Build with
just buildand test withjust testto verify functionality - Enforce quality with
swiftlint lint --strictandperiphery scan - Update documentation in
docs/when changing public APIs or build steps - Submit a clean pull request with descriptive commits and a green CI check suite
Frequently Asked Questions
What is the minimum Xcode version required to contribute to BitChat?
BitChat requires Xcode 13 or later. The project uses Swift features and frameworks that depend on the toolchain shipped with recent Xcode versions. CI specifically validates against the latest stable Xcode, so staying current avoids unexpected build failures.
Why does BitChat use just instead of Make or npm scripts?
The Justfile provides reproducible, cross-platform command shortcuts that work identically on developer machines and CI runners. Commands like just test abstract the underlying xcodebuild or swift test invocation, ensuring everyone runs the same test configuration regardless of local setup differences.
What happens if I forget to run SwiftLint before committing?
CI will fail the lint check and block your pull request from merging. Run swiftlint lint --strict locally to catch violations early. The --strict flag treats warnings as errors, matching the CI behavior exactly. Fix violations before pushing, or use swiftlint --fix for auto-correctable issues.
How do I handle dead code that Periphery reports but I can't remove?
Add intentional dead code to .periphery.baseline.json with a comment explaining why it must remain. The baseline file is part of the repository and reviewed in pull requests. Justification examples include: public API surfaces reserved for future use, or symbols referenced only through runtime reflection that static analysis cannot detect.
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 →