Skill: DI and Navigation 3 Architecture
SkillDev toolsLets your agent look up the Android app for controlling Meshtastic mesh radio devices.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Skill: DI and Navigation 3 Architecture skill
About this capability
Android application for Meshtastic
What this skill tells your AI
The instructions your AI receives, as published by meshtastic/meshtastic-android in .skills/navigation-and-di/SKILL.md and read by ahel’s review.
Description
This skill covers dependency injection (Koin Annotations 4.2.x) and JetBrains Navigation 3 (1.1.x) architecture, constraints, and anti-patterns within the Meshtastic-Android KMP codebase.
Dependency Injection (Koin)
Guidelines
- Annotations First: Use
@Module,@ComponentScan, and@KoinViewModelannotations directly incommonMainshared modules to encapsulate dependency graphs per feature. - App Root Assembly: Don't assume feature/core
@Moduleclasses are active automatically. Ensure they are included by the app root module (@Module(includes = [...])) inandroidApp/src/main/kotlin/org/meshtastic/app/di/AppKoinModule.ktanddesktopApp/.../DesktopKoinModule.kt. - No Platform Bleed: Don't put Android framework dependencies (
Context,Activity,Application) into sharedcommonMainbusiness logic. Inject interfaces instead. - Resolution: Resolve app-layer wrappers via
koinViewModel()or injected bindings within Compose navigation graphs.
Anti-Patterns
- A1 Module Compile Safety: Do not enable
compileSafety. It is a single boolean that enables A1 per-module checks — there is no separate A3 full-graph mode. Runtime graph verification is handled byKoinVerificationTestandDesktopKoinTestinstead. - Default Parameters: Do not expect Koin to inject default parameters automatically. The K2 plugin's
skipDefaultValues = truebehavior skips parameters with default Kotlin values.
Koin Startup Pattern (K2 Compiler Plugin)
The project uses the K2 Compiler Plugin (koin-compiler-plugin, not KSP). The canonical startup uses the plugin's typed startKoin<T>() stub, which the plugin transforms at compile time via IR:
// Bootstrap class — separate from @Module, references the root module graph
@KoinApplication(modules = [AppKoinModule::class])
object AndroidKoinApp
// In Application.onCreate()
startKoin<AndroidKoinApp> {
androidContext(this@MeshUtilApplication)
workManagerFactory()
}
@KoinApplicationgoes on a dedicated bootstrap object, not on a@Moduleclass.startKoin<T>()(fromorg.koin.plugin.module.dsl) is a compiler plugin stub — if the plugin isn't applied, it throwsNotImplementedError.stopKoin()uses the standard runtime API (org.koin.core.context.stopKoin).compileSafetymust stay disabled — it enables A1 per-module checks that break our inverted-dependency architecture. There is no separate A3 full-graph flag.
Navigation 3
Guidelines
- Types: Use Navigation 3 types consistently (
NavKey,NavBackStack,EntryProviderScope). - Typed Routes: Keep route definitions in
core:navigation/src/commonMain/.../Routes.ktas@Serializable sealed interfacehierarchies. Don't use ad-hoc strings. - Graph Assembly: Define feature navigation graphs as extension functions on
EntryProviderScope<NavKey>incommonMain(e.g.,fun EntryProviderScope<NavKey>.settingsGraph(backStack)). - Host Integration: Use
MeshtasticNavDisplay(fromcore:ui/commonMain) as the Navigation 3 host. Do not configure decorators manually inside feature modules. - Back Handlers: Use
NavigationBackHandlerfromandroidx.navigationevent:navigationevent-composefor back gestures in multiplatform code. Do not use Android'sBackHandler. - Deep Links: Use
DeepLinkRouter.route()incore:navigationto synthesize typed backstacks from RESTful paths.
Anti-Patterns
- Single Backstack for Multiple Tabs: Do not use a single
NavBackStacklist for multiple tabs. UseMultiBackstack(fromcore:navigation). - Decorator Reuse Across Tabs: Do not reuse the same
NavEntryDecoratorinstances across different backstacks. When rendering an active tab inMeshtasticNavDisplay, you must supply a fresh set of decorators (usingremember(backStack) { ... }) bound to the active backstack instance to prevent permanentViewModelStoredestruction. - Custom Backstack Mutation: Do not mutate back navigation with custom stacks disconnected from the app backstack. Mutate
NavBackStack<NavKey>directly withadd(...)andremoveLastOrNull().
Reference Anchors
- App Startup / Koin Bootstrap:
androidApp/src/main/kotlin/org/meshtastic/app/MeshUtilApplication.kt - DI Bootstrap Object:
androidApp/src/main/kotlin/org/meshtastic/app/di/AndroidKoinApp.kt - DI App Wiring:
androidApp/src/main/kotlin/org/meshtastic/app/di/AppKoinModule.kt - Shared Routes:
core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/Routes.kt - Desktop Nav Shell:
desktopApp/src/main/kotlin/org/meshtastic/desktop/ui/DesktopMainScreen.kt
Signals
- GitHub stars
- 2k
- Forks
- 512
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
navigation-and-di- Source
- github.com/meshtastic/meshtastic-android