Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .skills/compose-ui/strings-index.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 2 additions & 9 deletions .skills/new-branch/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ This replaces the ad-hoc prose that used to be retyped at the start of every ses
1. **Clean worktree.** If `git status --porcelain` is non-empty, ask the user before proceeding.
2. **Upstream remote present.** `git remote -v` must list `upstream` pointing at
`meshtastic/Meshtastic-Android`. If only `origin` exists on a fork, treat `origin` as upstream.
3. **Submodules initialised.** `core/proto/src/main/proto` must be populated — see AGENTS.md
workspace bootstrap rules.
4. **Secrets bootstrapped.** If `local.properties` is missing, copy `secrets.defaults.properties`
3. **Secrets bootstrapped.** If `local.properties` is missing, copy `secrets.defaults.properties`
(required for `google` flavor builds).

## Standard Recipe
Expand All @@ -30,10 +28,7 @@ git fetch upstream --prune --tags
# 2. Create the branch from upstream/main (never from a local stale main)
git switch -c <branch-name> upstream/main

# 3. Ensure submodules track the new base
git submodule update --init --recursive

# 4. Sanity check
# 3. Sanity check
git --no-pager log -1 --oneline
```

Expand All @@ -58,7 +53,6 @@ When the user says *"rebase #NNNN"* or *"dust off PR NNNN"*:
git fetch upstream --prune
gh pr checkout <NNNN> # checks out the PR head locally
git rebase upstream/main
git submodule update --init --recursive
# Resolve conflicts, then:
git push --force-with-lease
```
Expand All @@ -67,7 +61,6 @@ Never use plain `--force`. Always `--force-with-lease` to avoid clobbering colla

## Post-Branch Checklist
- [ ] Branch name follows conventional prefix.
- [ ] Submodules up to date.
- [ ] `local.properties` exists.
- [ ] `ANDROID_HOME` exported (see AGENTS.md workspace bootstrap).
- [ ] Optional: run `./gradlew assembleDebug` once to catch environment regressions before editing.
Expand Down
14 changes: 5 additions & 9 deletions .skills/project-overview/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Module directory, namespacing conventions, environment setup, and troubleshootin

- **Build System:** Gradle (Kotlin DSL). JDK 21 REQUIRED. Target SDK: API 36. Min SDK: API 26.
- **Flavors:** `fdroid` (OSS only) · `google` (Maps + DataDog analytics)
- **Android-only Modules:** `core:barcode` (CameraX). Shared contracts abstracted into `core:ui/commonMain`.
- **Android-only Modules:** `core:barcode` (CameraX), `feature:widget` (Glance home-screen widget), `feature:car` (Android Auto via the Car App Library, `google` flavor only), and `baselineprofile` (Macrobenchmark). Shared contracts are abstracted into `core:ui/commonMain`.

## Codebase Map

Expand All @@ -16,7 +16,6 @@ Module directory, namespacing conventions, environment setup, and troubleshootin
| `config/` | Detekt static analysis rules (`config/detekt/detekt.yml`) and Spotless formatting config (`config/spotless/.editorconfig`). |
| `docs/` | Architecture docs and agent playbooks. See `docs/kmp-status.md` and `docs/roadmap.md` for current status. |
| `core/model` | Domain models and common data structures. |
| `core:proto` | Protobuf definitions (Git submodule). |
| `core:common` | Low-level utilities, I/O abstractions (Okio), and common types. |
| `core:database` | Room KMP database implementation. |
| `core:datastore` | Multiplatform DataStore for preferences. |
Expand All @@ -28,13 +27,15 @@ Module directory, namespacing conventions, environment setup, and troubleshootin
| `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` | NFC abstractions (KMP). Android NFC hardware implementation in `androidMain`. |
| `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. |
| `feature/` | Feature modules (e.g., `settings`, `map`, `messaging`, `node`, `intro`, `connections`, `firmware`, `wifi-provision`, `widget`). All are KMP except `widget`. Use `meshtastic.kmp.feature` convention plugin. |
| `feature/` | Feature modules (e.g., `settings`, `map`, `messaging`, `node`, `intro`, `connections`, `firmware`, `wifi-provision`, `discovery`, `docs`, `widget`, `car`). Most are KMP and use the `meshtastic.kmp.feature` convention plugin; `widget` (Glance) and `car` (Android Auto, `google` flavor only) are Android-only. |
| `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`. |
Expand Down Expand Up @@ -66,12 +67,7 @@ Agents **MUST** perform these steps automatically at the start of every session
```
All `./gradlew` invocations must include `ANDROID_HOME` in the environment. If the SDK cannot be found, ask the user for the path.

2. **Proto submodule:** `core/proto/src/main/proto` is a Git submodule containing Protobuf definitions. It must be initialized or builds will fail with proto generation errors:
```bash
git submodule update --init
```

3. **Init secrets:** If `local.properties` does not exist, copy `secrets.defaults.properties` to `local.properties`. Without this the `google` flavor build fails:
2. **Init secrets:** If `local.properties` does not exist, copy `secrets.defaults.properties` to `local.properties`. Without this the `google` flavor build fails:
```bash
[ -f local.properties ] || cp secrets.defaults.properties local.properties
```
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ You are an expert Android/KMP engineer. Maintain architectural boundaries, use M
- **CMP Over Android:** Use `compose-multiplatform` constraints. Pre-format floats with `NumberFormatter.format()`. Use `MeshtasticNavDisplay` and `NavigationBackHandler`.
- **Zero Lint Tolerance:** Task is incomplete if `detekt` or `spotlessCheck` fails.
- **Verify Before Push:** Treat any "push" as verify-then-push. CI has failed repeatedly due to skipped local checks.
- **Never Touch Protos or Secrets:** `core/proto` is an upstream submodule. Secrets are git-ignored.
- **Never Touch Protos or Secrets:** Protobuf models come from the upstream `org.meshtastic:protobufs` Maven dependency (pinned in `gradle/libs.versions.toml`) — bump the version upstream, never hand-edit generated proto. Secrets are git-ignored.
- **Privacy First:** Never log or expose PII, location, or cryptographic keys.
</rules>

Expand Down
1 change: 0 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
JDK 21 is required. **Bootstrap before any Gradle task** (don't wait to be told) — full details in `.skills/project-overview/SKILL.md`:
```bash
[ -z "$ANDROID_HOME" ] && export ANDROID_HOME="$HOME/Library/Android/sdk" # often unset in agent workspaces
git submodule update --init # proto submodule; builds fail without it
[ -f local.properties ] || cp secrets.defaults.properties local.properties # google flavor fails without it
```

Expand Down
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@ This is a tool for using Android (and Compose Desktop) with open-source mesh rad

If you have questions or feedback please [Join our discussion forum](https://github.com/orgs/meshtastic/discussions) or the [Discord Group](https://discord.gg/meshtastic). We would love to hear from you!

## Features

Highlights from the latest release:

- **Full-text message search** across your conversation history.
- **Mesh network discovery** to surface nodes and channels around you.
- **Android Auto** support for hands-free use while driving (`google` flavor).
- **Air-quality telemetry** — PM1.0, PM2.5, PM10, and CO₂ readings from supported sensors.
- **Device hardware links** via [msh.to](https://msh.to) for quick access to hardware details.
- **App Functions / system-AI integration** so on-device assistants can trigger common workflows.

## Get Meshtastic

Expand Down Expand Up @@ -76,7 +85,7 @@ The app follows modern Android development practices, built on top of a shared K
- **State Management:** Unidirectional Data Flow (UDF) with ViewModels, Coroutines, and Flow.
- **Dependency Injection:** Koin with Koin Annotations (K2 Compiler Plugin).
- **Navigation:** JetBrains Navigation 3 (Multiplatform routing with RESTful deep linking).
- **Data Layer:** Repository pattern with Room KMP (local DB), DataStore (prefs), and Protobuf (device comms).
- **Data Layer:** Repository pattern with Room KMP (local DB), DataStore (prefs), and Protobuf (device comms). Protobuf models are consumed from the upstream `org.meshtastic:protobufs` Maven artifact, pinned in `gradle/libs.versions.toml`.

### Bluetooth Low Energy (BLE)
The BLE stack uses a multiplatform interface-driven architecture. Platform-agnostic interfaces live in `commonMain`, utilizing the **Kable** multiplatform BLE library to handle device communication across all supported targets (Android, Desktop). This provides a robust, Coroutine-based architecture for reliable device communication while remaining fully KMP compatible. See [core/ble/README.md](core/ble/README.md) for details.
Expand Down Expand Up @@ -106,7 +115,6 @@ Each module has its own README with details on its responsibilities, API surface
| [core/nfc](core/nfc/README.md) | NFC support |
| [core/prefs](core/prefs/README.md) | Legacy preference helpers |
| [core/barcode](core/barcode/README.md) | Barcode / QR scanning |
| [core/proto](core/proto/README.md) | Protobuf submodule wrapper |
| [feature/messaging](feature/messaging/README.md) | Messaging UI feature |
| [feature/map](feature/map/README.md) | Map UI feature |
| [feature/node](feature/node/README.md) | Node detail UI feature |
Expand All @@ -115,8 +123,11 @@ Each module has its own README with details on its responsibilities, API surface
| [feature/intro](feature/intro/README.md) | Onboarding / intro UI feature |
| [feature/wifi-provision](feature/wifi-provision/README.md) | Wi-Fi provisioning UI feature |
| [feature/connections](feature/connections/README.md) | Device discovery & connection management (BLE / USB / TCP) |
| [feature/discovery](feature/discovery) | Mesh network discovery |
| [feature/docs](feature/docs/README.md) | In-app documentation browser with Chirpy AI assistant |
| [feature/widget](feature/widget/README.md) | Android home-screen Glance widget (live mesh stats) |
| [feature/car](feature/car) | Android Auto integration (Car App Library, `google` flavor) |
| [baselineprofile](baselineprofile/README.md) | Macrobenchmark Baseline Profile generation for `:androidApp` |

## Translations

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,8 @@
<string name="dns">DNS</string>
<!-- DOC -->
<string name="doc_clear_search">Clear search</string>
<string name="doc_keywords_android_auto">android auto,car,head unit,driving,hands free,messaging</string>
<string name="doc_keywords_app_functions">system ai,gemini,assistant,functions,automation,voice</string>
<string name="doc_keywords_connections">bluetooth,usb,tcp,pairing,serial,wifi</string>
<string name="doc_keywords_desktop">desktop,linux,macos,windows,serial</string>
<string name="doc_keywords_discovery">discovery,topology,network,scan,neighbor</string>
Expand All @@ -474,6 +476,8 @@
<string name="doc_search_placeholder">Search documentation…</string>
<string name="doc_section_developer">Developer Guide</string>
<string name="doc_section_user">User Guide</string>
<string name="doc_title_android_auto">Android Auto</string>
<string name="doc_title_app_functions">App Functions</string>
<string name="doc_title_connections">Connections</string>
<string name="doc_title_desktop">Desktop App</string>
<string name="doc_title_discovery">Discovery</string>
Expand Down
46 changes: 29 additions & 17 deletions docs/assets/screenshots/README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,52 @@
# Screenshots

This directory contains screenshot assets referenced by the documentation pages.
This directory is the **single source of truth** for screenshot assets referenced by the
documentation pages. It is consumed by both:

Screenshots are sourced from the Compose Preview Screenshot Testing reference images
in `screenshot-tests/src/screenshotTestDebug/reference/`. Light-mode variants are
copied here for use by the Jekyll docs site and in-app documentation browser.
- the **Jekyll docs site** (markdown references `../../assets/screenshots/{name}.png`), and
- the **in-app docs browser** — `:feature:docs:syncDocsToComposeResources` bundles this
directory into compose resources at `files/docs/assets/screenshots/`.

`DocImageWiringTest` (in `:feature:docs`) fails the build if a doc page references an image
that is not present here.

## Updating Screenshots

After changing a UI component, regenerate reference images and copy them here:
Most screenshots are generated from the Compose Preview Screenshot Testing reference images
in `screenshot-tests/src/screenshotTestDebug/reference/`. After changing a UI component:

```bash
./gradlew :screenshot-tests:updateDebugScreenshotTest
./gradlew :screenshot-tests:updateDebugScreenshotTest # regenerate reference images
./gradlew :screenshot-tests:copyDocsScreenshots # refresh this directory
```

Then copy the relevant light-mode PNGs from the reference directory. The
`copyDocsScreenshots` task automates bulk copying based on the manifest:
`copyDocsScreenshots` copies **only** the light-mode reference images that have a semantic
alias in `screenshot-tests/docs-screenshot-aliases.properties`, renaming them on the way.
Commit the refreshed PNGs together with the reference-image changes.

```bash
./gradlew :screenshot-tests:copyDocsScreenshots
```
## Adding a Screenshot for a New Doc Page

1. Add (or reuse) a `Preview*`/`*Preview` composable with representative mock data in the
feature module, and a `Screenshot*` wrapper in `screenshot-tests` (see
`DiscoveryScreenshotTests.kt` for the pattern). If the component renders timestamps, give
it a `timeTextOverride`-style parameter so renders stay deterministic across machines.
2. Make sure the test class is covered by `screenshot-tests/docs-screenshots-manifest.txt`.
3. Map the semantic name in `screenshot-tests/docs-screenshot-aliases.properties`:
`{page-id}_{description}.png=Screenshot{Name}_Light_{hash}_0.png`
4. Run the two Gradle tasks above and reference the image from the doc page.

## Naming Convention

```
{page-id}_{description}.png
```

Examples:
- `onboarding_welcome.png`
- `connections_bluetooth_scan.png`
- `firmware_disclaimer.png`
Examples: `onboarding_welcome.png`, `connections_bluetooth_scan.png`, `discovery_preset_result.png`.

## Guidelines

- PNG format, light-mode only (dark variants live in reference directory)
- PNG format, light-mode only (dark variants live in the reference directory)
- Name screenshots to match the docs page they appear in
- Keep filenames lowercase with underscores

- A few screenshots (`connections_wifi_*.png`) are manual captures with no CST source yet;
they are hand-maintained until matching previews exist
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/connections_bluetooth_scan.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/connections_connecting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/connections_empty_state.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/docs-browser_chirpy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/docs-browser_page.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/docs-browser_toc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/firmware_checking.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/firmware_disclaimer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/firmware_error.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/messages_quick_chat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/screenshots/messages_search_bar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/nodes_battery_info.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/screenshots/nodes_detail_minimal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/nodes_environment_metrics.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/nodes_node_list.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/nodes_position.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/onboarding_welcome.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/settings_app_info.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/settings_appearance.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/settings_persistence.png
Binary file modified docs/assets/screenshots/settings_slider.png
Binary file modified docs/assets/screenshots/settings_switch.png
Loading