Skip to content
Development
Skill

/android-dev

Use this skill as the baseline for ALL Android and Kotlin Multiplatform (KMP) work — whenever the user mentions Android, Kotlin (in an Android context), KMP, CMP, commonMain, androidMain, iosMain, AndroidManifest, Gradle, build.gradle, Hilt, Dagger, Room, Retrofit, Ktor,

BOOST
From plugin
android-skills
16221 skills
Install
$ npx -y skills add rcosteira79/android-skills --skill android-dev --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/android-dev

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use this skill as the baseline for ALL Android and Kotlin Multiplatform (KMP) work — whenever the user mentions Android, Kotlin (in an Android context), KMP, CMP, commonMain, androidMain, iosMain, AndroidManifest, Gradle, build.gradle, Hilt, Dagger, Room, Retrofit, Ktor,

SKILL.md

android-dev.SKILL.md
name: android-dev
description: >
  Use this skill as the baseline for ALL Android and Kotlin Multiplatform (KMP) work —
  whenever the user mentions Android, Kotlin (in an Android context), KMP, CMP, commonMain,
  androidMain, iosMain, AndroidManifest, Gradle, build.gradle, Hilt, Dagger, Room, Retrofit,
  Ktor, ViewModel, LiveData, StateFlow, SharedFlow, Compose, Activity, Fragment, Intent, ADB,
  Logcat, MVVM, MVI, repository pattern, or any Android SDK / Jetpack / AndroidX API. Always
  load this skill alongside the more specific skills (android-skills:compose,
  android-skills:kotlin-flows, android-skills:kmp-ktor, android-skills:android-retrofit,
  etc.): it routes to them and adds the few baseline rules that are easy to get wrong. Casual
  mentions like "fix this bug in my Android app," "refactor this ViewModel," "my KMP project,"
  or any work inside an Android project directory should trigger this skill.

Android / KMP baseline

House defaults — apply them without reminders or re-derivation; where the project's actual conventions differ, follow the project:

  • **DI:** Hilt + KSP (or `android-skills:koin` when the project uses Koin). **Async:** Coroutines/Flow — no `LiveData` in new code. **JSON:** `kotlinx.serialization`. **Images:** Coil.
  • **Network/local:** Android uses Retrofit/OkHttp + Room; KMP shared uses Ktor + Room or SQLDelight. Retrofit is Android-only — never in a shared module.
  • **Modules:** feature-vertical packages and modules; `:core:model` has zero Android deps; `:feature:*` modules never depend on each other.
  • **Errors:** mapped to a domain type at the repository boundary — platform exceptions never leak past it; UI state explicitly models loading / success / error (see `android-skills:android-data-layer`).

Skill routing

Load the specific skill for the task, always with the **fully-qualified `android-skills:` prefix** — never the short name (`compose`, `koin`, …).

| For | Load | |---|---| | Compose detail — stability, `remember`, modifiers, side effects, lists, animation, navigation | `android-skills:compose` | | M3 UX — touch targets, adaptive/foldable layouts, accessibility & M3-compliance audit | `android-skills:android-ux` | | Coroutines & Flow — operators, `Channel` vs `SharedFlow`, structured concurrency | `android-skills:kotlin-coroutines`, `android-skills:kotlin-flows` | | Repository / data layer + error model | `android-skills:android-data-layer` | | Networking | `android-skills:android-retrofit` (Android) · `android-skills:kmp-ktor` (KMP) | | Paging | `android-skills:paging` | | Image loading | `android-skills:coil-compose` | | Preferences / typed local storage | `android-skills:datastore` | | KMP `expect`/`actual` boundary design | `android-skills:kmp-boundaries` | | RxJava → Coroutines/Flow migration | `android-skills:rxjava-migration` | | Testing | `android-skills:android-testing` | | DI with Koin | `android-skills:koin` | | Build logic / convention plugins | `android-skills:android-gradle-logic` | | Build speed, kapt → KSP | `android-skills:gradle-build-performance` | | Debugging — Logcat, crashes, ANRs, profiling | `android-skills:android-debugging` | | AOSP / AndroidX source lookup | `android-skills:android-source-search` | | Multi-module visibility & module boundaries | `android-skills:modularization` | | Platform PDF annotation / page-object editing (API 36.1 / SDK ext 18) | `android-skills:pdf-annotations` |

New-project UI convention (greenfield)

For a **new** project or feature with no established convention. In existing code, match what's already there — see *Reuse the project's existing mechanism* below.

The UI layer is MVVM with an MVI-style state/effect split:

  • **One immutable `UiState` per screen**, exposed as `StateFlow<UiState>` and structured with the four buckets below. The content composable renders it and emits callbacks — nothing else.
  • **One effects stream for fire-once imperatives** — navigate, snackbar/toast, scroll-to, share-sheet, haptics. Use `Channel(Channel.BUFFERED).receiveAsFlow()`, **not** `SharedFlow`: an effect emitted while the screen is backgrounded buffers and replays on resume instead of being dropped. Collect it in a `LaunchedEffect` (lifecycle-scoped via `repeatOnLifecycle`), never `collectAsStateWithLifecycle`. Channel-vs-`SharedFlow` rationale: `android-skills:kotlin-flows`.
  • **State vs effect — "does it survive a config change?"** Anything still true after rotation / process death is **state** (an error to show = a field in `UiState`); anything the UI runs once and forgets is an **effect**. This is the `durable-state-over-events` rule in `compose/references/state-management.md`: keep durable things in state; the effect stream is only for one-shot imperatives.
  • **Promote callbacks to a `@Stable Actions` interface at ~4–5+** (or when the same set is threaded through several composable layers). Below that, individual lambdas are simpler — don't abstract early. The ViewModel implements the interface; the content composable depends on `FooActions`, **never** the ViewModel, so it stays pure and previewable (a no-op `object : FooActions {}` in previews).
data class FooUiState(/* the four buckets — see below */)

sealed interface FooEffect {
    data class NavigateTo(val id: String) : FooEffect
    data class ShowSnackbar(val message: String) : FooEffect
}

@Stable                                       // promote here once lambdas pile up (~4-5+)
interface FooActions {
    fun onItemClick(id: String)
    fun onRefresh()
}

class FooViewModel(/* … */) : ViewModel(), FooActions {
    private val _uiState = MutableStateFlow(FooUiState())
    val uiState: StateFlow<FooUiState> = _uiState.asStateFlow()

    private val _effects = Channel<FooEffect>(Channel.BUFFERED)   // not SharedFlow — buffers while backgrounded
    val effects = _effects.receiveAsFlow()

    override fun onItemClick(id: String) { /* _uiState.update { … } */ _effects.trySend(FooEffect.NavigateTo(id)) }
    override
Read more
Ships withandroid-skills

Android & KMP development skills for Claude Code, Codex, and Copilot CLI — architecture, Compose, coroutines, flows, networking, persistence, dependency injection, testing, debugging, and Gradle.

Get the whole plugin

Other skills on android-skills.