Skip to main content

project-overview

The Meshtastic-Android codebase map - module directory, namespacing conventions, JDK and SDK requirements, and the mandatory bootstrap steps. Read this first in any session that will build, test or navigate the repo: the bootstrap here has to run before any Gradle task, and skipping it is what makes the first build fail.

Source facts

Repository
meshtastic/Meshtastic-Android
Last source activity
October 21, 2026 at 16:00
Detected SKILL.md language
English
Stars
1,924
Forks
539

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
project-overview
description
The Meshtastic-Android codebase map - module directory, namespacing conventions, JDK and SDK requirements, and the mandatory bootstrap steps. Read this first in any session that will build, test or navigate the repo: the bootstrap here has to run before any Gradle task, and skipping it is what makes the first build fail.
# Skill: Project Overview & Codebase Map ## Description Module directory, namespacing conventions, environment setup, and troubleshooting for Meshtastic-Android. - **Build System:** Gradle (Kotlin DSL). JDK 25 REQUIRED. Target SDK: API 37. Min SDK: API 26. - **Flavors:** `fdroid` (OSS only) · `google` (Google Maps, Firebase Crashlytics and Datadog RUM) - **Android-only Modules:** `core:barcode` (CameraX), `core:nfc` (NFC hardware), `feature:widget` (Glance home-screen widget), and `baselineprofile` (Macrobenchmark). Shared contracts are abstracted into `core:ui/commonMain`. ## Codebase Map | Directory | Description | | :--- | :--- | | `androidApp/` | Main application module. Contains `MainActivity`, Koin DI modules, and app-level logic. Uses package `org.meshtastic.app`. | | `build-logic/` | Convention plugins for shared build configuration (e.g., `meshtastic.kmp.feature`, `meshtastic.kmp.library`, `meshtastic.kmp.jvm.android`, `meshtastic.koin`). | | `config/` | Detekt static analysis rules (`config/detekt/detekt.yml`) and Spotless formatting config (`config/spotless/.editorconfig`). | | `docs/` | The user + developer documentation bundle, not agent docs. `docs/en/` is the English source (`user/`, `developer/`); `docs/<locale>/user/` are Crowdin translations; the rest is the Jekyll site scaffolding. Consumed three ways — in-app via `syncDocsToComposeResources`, GitHub Pages via `docs-deploy.yml`, and meshtastic.org via `scripts/sync-android-docs.js`. | | `core/model` | Domain models and common data structures. | | `core:common` | Low-level utilities, I/O abstractions (Okio), and common types. | | `core:database` | Room KMP database implementation. | | `core:datastore` | Multiplatform DataStore for preferences. | | `core:repository` | High-level domain interfaces (e.g., `NodeRepository`, `LocationRepository`). | | `core:domain` | Pure KMP business logic and UseCases. | | `core:data` | Core manager implementations and data orchestration. | | `core:network` | KMP networking layer using Ktor, MQTT abstractions, and shared transport (`StreamFrameCodec`, `TcpTransport`, `SerialTransport`, `BleRadioTransport`). | | `core:di` | Common DI qualifiers and dispatchers. | | `core:navigation` | Shared navigation keys/routes for Navigation 3 using `@Serializable sealed interface` hierarchies. `DeepLinkRouter` for typed backstack synthesis, and `MeshtasticNavSavedStateConfig` with `subclassesOfSealed()` for automatic polymorphic backstack persistence. | | `core:ui` | Shared Compose UI components (`MeshtasticAppShell`, `MeshtasticNavDisplay`, `MeshtasticNavigationSuite`, `AlertHost`, `SharedDialogs`, `PlaceholderScreen`, `MainAppBar`, dialogs, preferences) and platform abstractions. | | `core:service` | KMP service layer; Android bindings stay in `androidMain`. | | `core:takserver` | Meshtastic ↔ TAK (ATAK/iTAK) bridge — local CoT server and CoT ⇄ mesh conversion. | | `core:prefs` | KMP preferences layer built on DataStore abstractions. | | `core:barcode` | Barcode scanning (Android-only). | | `core:nfc` | Android-only NFC hardware implementation (an Android library, not KMP). The shared NFC abstractions are the `LocalNfc*Provider` composition locals in `core:ui`. | | `core/ble/` | Bluetooth Low Energy stack using Kable. | | `core/resources/` | Centralized string and image resources (Compose Multiplatform). | | `core/testing/` | Shared test doubles, fakes, and utilities for `commonTest` across all KMP modules. | | `core/konsist/` | Architecture rules as Konsist tests (`jvmTest` only), such as the `CancellationException` import and the `expect` declarations. | | `feature/` | Feature modules (e.g., `settings`, `map`, `map-maplibre`, `map-terrain`, `coverage`, `messaging`, `node`, `intro`, `connections`, `firmware`, `wifi-provision`, `discovery`, `docs`, `widget`). Most are KMP and use the `meshtastic.kmp.feature` convention plugin; `widget` (Glance) is Android-only. | | `feature/coverage` | Site Planner coverage computed on the device with `kp1812` over Mapterhorn terrain, returned as GeoJSON for the map. | | `screenshot-tests/`, `docs-screenshots/` | Compose preview screenshot modules: the CI visual-regression gate, and the generate-only docs images (see `testing-ci` §3b). | | `store-screenshots/` | Instrumented capture of the store-listing screenshots from the debug app on a device or emulator. | | `schema-strings/` | JVM generator for `values/schema_strings.xml` from the protobufs field metadata (`:schema-strings:sync`); its `test` fails when the file is stale against the pin it recorded, and skips the check when that pin no longer matches the catalog. | | `baselineprofile/` | Macrobenchmark Baseline Profile generation for `:androidApp` (AOT-compiled cold-start journey). Android-only. | | `feature/wifi-provision` | KMP WiFi provisioning via BLE (Nymea protocol). Uses `core:ble` Kable abstractions. | | `feature/firmware` | Fully KMP firmware update system: Unified OTA (BLE + WiFi), native Nordic Secure DFU protocol (pure KMP), USB/UF2 updates, and `FirmwareRetriever` with manifest-based resolution. Desktop is a first-class target. | | `desktopApp/` | Compose Desktop application. Thin host shell relying on feature modules for shared UI. Full Koin DI graph, TCP, Serial/USB, and BLE transports. Versioning via `config.properties` + `GitVersionValueSource`. | ## Namespacing - **Standard:** Use the `org.meshtastic.*` namespace for all code. - **Legacy:** Maintain the `com.geeksville.mesh` Application ID. ## Environment Setup 1. **JDK 25 MUST be used** to prevent Gradle sync/build failures. 2. **Secrets (optional):** `androidApp/build.gradle.kts` configures the secrets plugin as `propertiesFileName = "secrets.properties"` with `defaultPropertiesFileName = "secrets.defaults.properties"`, so a clone builds every flavor with no secrets file at all — the tracked defaults supply placeholders. Create `secrets.properties` in the repo root (git-ignored) only to override one: ```properties MAPS_API_KEY=<your real key> # without this, Google Maps tiles do not load datadogApplicationId=dummy_id datadogClientToken=dummy_token ``` ## Workspace Bootstrap (MUST run before any build) Agents **MUST** perform these steps automatically at the start of every session before running any Gradle task. Do not wait for the user to tell you. 1. **Android SDK:** `ANDROID_HOME` may not be set in agent workspaces. Detect and export it: ```bash # Check common macOS/Linux locations in order of preference if [ -z "$ANDROID_HOME" ]; then for dir in "$HOME/Library/Android/sdk" "$HOME/Android/Sdk" "/opt/android-sdk"; do if [ -d "$dir" ]; then export ANDROID_HOME="$dir"; break; fi done fi ``` All `./gradlew` invocations must include `ANDROID_HOME` in the environment. If the SDK cannot be found, ask the user for the path. 2. **Secrets:** nothing to do. `secrets.defaults.properties` is tracked and is the plugin's declared fallback, so no bootstrap step is required for any flavor. `local.properties` is not read for secrets (only the vendored plugin's unused default constant still names it). ## Troubleshooting - **Build Failures:** Check `gradle/libs.versions.toml` for dependency conflicts. - **Configuration Cache:** Add `-Dorg.gradle.isolated-projects=false --no-configuration-cache` if cache-related issues persist. Both flags are required: Isolated Projects (on by default here) implies the configuration cache, and Gradle 9.7+ fails the build if you disable the cache without also disabling Isolated Projects. - **Koin Injection Failures:** Verify the component is included in `AppKoinModule`.
View on GitHub