Contributing
Guidelines for contributing to the Meshtastic Android/Desktop/iOS project.
Branch Naming
Branches use conventional-commit style prefixes:
| Prefix | Use for |
|---|---|
feat/<scope> | New user-visible behavior |
fix/<scope> | Bug fixes |
refactor/<scope> | Code structure changes |
chore/<scope> | Tooling, deps, CI, cleanup |
docs/<scope> | Documentation only |
build/<scope> | Build system changes |
ci/<scope> | CI workflow changes |
test/<scope> | Test additions or fixes |
deps/<scope> | Dependency updates |
Numeric spec prefixes (e.g., 003-app-docs-markdown) are also valid for spec-driven work.
Examples:
feat/desktop-ble-transportfix/bluetooth-reconnect003-app-docs-markdown
Development Workflow
- Fork the repository (external contributors) or create a branch (maintainers).
- Implement your changes following the architecture guidelines.
- Test locally:
./gradlew spotlessCheck detekt kmpSmokeCompile test allTests - Commit with clear, descriptive messages.
- Push and open a Pull Request.
Commit Messages
Follow conventional commit style:
feat(docs): add in-app documentation browser
fix(ble): handle reconnection timeout
refactor(navigation): migrate to typed routes
test(search): add keyword ranking tests
Pull Request Checklist
Before submitting:
- Code compiles on all targets:
./gradlew kmpSmokeCompile - All tests pass:
./gradlew allTests - Code style passes:
./gradlew spotlessCheck - Static analysis passes:
./gradlew detekt - New code has appropriate test coverage
- No
android.*imports incommonMain - Koin modules registered if new DI is added
- Routes added to
Routes.ktif new navigation is introduced - Documentation updated if user-facing behavior changes
Code Style
- Formatting: Enforced by Spotless (KtLint rules)
- Static analysis: Detekt with project-specific configuration
- Imports: No wildcard imports; organized automatically by Spotless
- Line length: 120 characters maximum
Run formatting:
./gradlew spotlessApply
Architecture Rules
- Feature modules must not depend on other feature modules
commonMainmust not containandroid.*,java.io.*, or platform-specific imports- Prefer interface + DI over
expect/actualfor complex platform behaviors - All navigation routes must be
@Serializableand defined inRoutes.kt - Use Koin annotations (
@Single,@Factory,@Module) for dependency injection
Verification
Full pre-merge verification:
./gradlew spotlessCheck detekt kmpSmokeCompile test allTests
For docs-specific changes, also run:
./gradlew generateDocsBundle validateDocsBundle
Getting Help
- Meshtastic Discord —
#app-developmentchannel - GitHub Issues — for bug reports and feature requests
- GitHub Discussions — for questions and ideas