Agent skill

Android and KMP Baseline

by rcosteira79 in rcosteira79/android-skills

Sets house defaults for Android and Kotlin Multiplatform work and routes to the right specialized skill for Compose, networking, testing or build tooling.

MITAuto-check passedMobile

Install Android and KMP Baseline

skills CLI
$ npx skills add rcosteira79/android-skills --skill android-dev -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install rcosteira79/android-skills android-dev --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/rcosteira79/android-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/android-skills/skills/android-dev .claude/skills/android-dev && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
android-dev
GitHub stars
150
Token cost
~3k tokens
SKILL.md length
1,039 words
Files
1
Skills in repo
21
Repo updated
First seen
Licence
MIT

At a glance

Sets house defaults for Android and Kotlin Multiplatform work and routes to the right specialized skill for Compose, networking, testing or build tooling.

  • Starting any Android or Kotlin Multiplatform task
  • SKILL.md covers Skill routing, New-project UI convention…, Four-bucket state modeling and UI state and UI models live in…, plus 3 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • Fixing a bug or refactoring a ViewModel in an Android app

What it does

Defaults cover dependency injection with Hilt plus KSP, or Koin when a project already uses it, coroutines and Flow instead of LiveData in new code, kotlinx.serialization for JSON, and Coil for images. Android uses Retrofit and OkHttp with Room while shared KMP code uses Ktor with Room or SQLDelight, and Retrofit never goes in a shared module since it is Android-only; module boundaries keep the core model package free of Android dependencies and stop feature modules from depending on each other, with platform exceptions mapped to a domain type at the repository boundary.

A routing table sends more specific work to sibling skills, covering Compose detail, Material 3 UX audits, coroutines and Flow operators, the data layer and error model, Retrofit versus Ktor networking, paging, image loading, typed local storage, KMP expect and actual boundaries, RxJava migration, testing, Koin, Gradle build logic and speed, Logcat debugging, AOSP source lookup and modularization, always loaded with the full android-skills prefix rather than a short name.

When your agent uses it

  • Starting any Android or Kotlin Multiplatform task
  • Fixing a bug or refactoring a ViewModel in an Android app
  • Deciding which specialized Android skill a task should route to

Example prompts

  • “Fix this crash in my Android app's ViewModel.”
  • “Set up a new feature module following the project's Android conventions.”
  • “Which skill should I load to debug this KMP networking issue?”

What it can do on your machine

Read from SKILL.md and the folder at commit 0f9af5a. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are kotlin).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Android and KMP Baseline loads about 3k tokens when it runs. Until then it costs about 221 tokens; SKILL.md has 1,039 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~221
When it runs · the whole SKILL.md, loaded when a task matches
~3k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from rcosteira79/android-skills at commit 0f9af5a, republished under its MIT licence (© rcosteira79). 1,039 words, ~2,998 tokens.

Download SKILL.mdSave it as .claude/skills/android-dev/SKILL.md (or your agent's skills folder).
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, …).

ForLoad
Compose detail — stability, remember, modifiers, side effects, lists, animation, navigationandroid-skills:compose
M3 UX — touch targets, adaptive/foldable layouts, accessibility & M3-compliance auditandroid-skills:android-ux
Coroutines & Flow — operators, Channel vs SharedFlow, structured concurrencyandroid-skills:kotlin-coroutines, android-skills:kotlin-flows
Repository / data layer + error modelandroid-skills:android-data-layer
Networkingandroid-skills:android-retrofit (Android) · android-skills:kmp-ktor (KMP)
Pagingandroid-skills:paging
Image loadingandroid-skills:coil-compose
Preferences / typed local storageandroid-skills:datastore
KMP expect/actual boundary designandroid-skills:kmp-boundaries
RxJava → Coroutines/Flow migrationandroid-skills:rxjava-migration
Testingandroid-skills:android-testing
DI with Koinandroid-skills:koin
Build logic / convention pluginsandroid-skills:android-gradle-logic
Build speed, kapt → KSPandroid-skills:gradle-build-performance
Debugging — Logcat, crashes, ANRs, profilingandroid-skills:android-debugging
AOSP / AndroidX source lookupandroid-skills:android-source-search
Multi-module visibility & module boundariesandroid-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).
kotlin
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 fun onRefresh() { /* … */ }
}

@Composable
fun FooScreen(viewModel: FooViewModel = hiltViewModel(), onNavigate: (String) -> Unit) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()
    val lifecycle = LocalLifecycleOwner.current.lifecycle
    LaunchedEffect(Unit) {
        lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
            viewModel.effects.collect { effect ->
                when (effect) {
                    is FooEffect.NavigateTo -> onNavigate(effect.id)
                    is FooEffect.ShowSnackbar -> { /* show snackbar */ }
                }
            }
        }
    }
    FooContent(uiState = uiState, actions = viewModel)   // VM passed as FooActions — FooContent sees only the interface
}

Kotlin 2.4+: collapse the _uiState/uiState pair with explicit backing fields (val uiState: StateFlow<FooUiState> + field = MutableStateFlow(…)) — uiState only, never the effects Channel. Full idiom + version gate: android-skills:kotlin-flows.

Four-bucket state modeling

Screens with rich interactions (forms, calculators, multi-step wizards) get unmanageable when state is one flat data class. Slice UiState into four explicit buckets, and derive computed values as class properties, not constructor parameters:

kotlin
data class CheckoutUiState(
    // 1. Editable input — what the user types
    val email: String = "",
    val cardNumber: String = "",
    // 3. Persisted snapshot — last value read from the repository / stored cross-screen
    val savedShippingAddress: Address? = null,
    // 4. Transient UI-only — flags that must NOT survive the screen
    val isSubmitting: Boolean = false,
    val showCardScannerOverlay: Boolean = false,
) {
    // 2. Derived — getters, NOT constructor params, so no caller can copy() into an
    //    inconsistent state (e.g. emailValid = false next to a valid email).
    val emailValid: Boolean get() = email.isValidEmail()
    val canSubmit: Boolean get() = emailValid && cardNumber.passesLuhn() && !isSubmitting
}

The bucket dictates lifecycle and persistence, not the field. Persisting isSubmitting keeps the spinner forever after process death; computing canSubmit outside the class lets it drift from the inputs; persisting cardNumber cross-screen leaks PII. Mixing the buckets produces bugs that look architectural.

Show full SKILL.md (486 more words)Show less

UI state and UI models live in different files

UiState is the screen's contract with its ViewModel, not a UI model — it gets its own file (or the ViewModel's, if that's the project's layout). Never sweep UI models into it. "Each type has a single owner / it's one unit of change / the real seam is role-per-file" argues for exactly this mistake: the state and the models it holds are different roles.

Group the models by composition, never by screen:

  • Models composing one bigger model share that model's file, named after the bigger model — ChallengeDetailUi.kt holds ChallengeDetailUi plus the ChallengeTaskUi / SponsorshipUi it is built from.
  • Independent models each get their own file.
  • FooModels.kt / FooUiModels.kt is never the answer — reaching for a grab-bag name proves no aggregate root was found, which means the types are independent and belong in their own files.

Kotlin's "related declarations may share a file named after the primary declaration" is the mechanism, not a licence to nominate the state as that primary declaration and sweep the models in behind it.

Reuse the project's existing mechanism

Before adding any new mechanism — an event dispatcher, an effects Channel/SharedFlow, a use-case layer, or a parallel state field — open a sibling ViewModel in the same feature and reuse what's already there. The easy miss here is duplicating an existing mechanism instead of widening it — adding a second shouldDisplayUndoX flag beside the existing one rather than generalizing the one that's there. If existing code contradicts a "best practice," follow the code and flag the inconsistency; never silently override the project's architecture.

Comments — earn every one

The test for every comment: could a reader quickly infer what it says from the code beside it? If yes, it's redundant — delete it. A comment survives only by carrying what the code cannot: a non-obvious why — a decision, constraint, workaround, or gotcha. Never narrate what the code does; clear names and small functions already say it. "What a well-known type or call does" is a what the reader can look up, not a why.

Write the fewest comments that pass that test — this holds even when a task says "make it readable" or "for juniors." Readability comes from naming and structure; a comment a newcomer needs in order to follow what the code does is a signal to rename or extract, not to annotate.

Keep a genuine why (// rethrow first — a broad catch would swallow CancellationException), a justifying comment at a surprising call site, KDoc on a public API that adds information beyond its signature, and TODO(owner-or-link). Honor an explicit request for documentation.

Delete on sight — each is trivially inferable from the code beside it:

kotlin
// ---- domain model ----                                 // section-divider / banner (any width)
/** The user profile as the app cares about it. */        // KDoc restating the class name
val uiState = _uiState.asStateFlow()  // private mutable, public read-only   (restates the idiom)
} catch (e: IOException) {  // no connectivity, timeout, DNS failure   (restates what the type means)

KMP

Inject a CoroutineDispatcher everywhere rather than calling Dispatchers.Main / Dispatchers.IO directly: Dispatchers.Main isn't guaranteed on every KMP target without the -ktx artifacts, and injection is also what makes dispatcher-swapped tests possible. Use expect/actual for platform specifics (file I/O, push tokens, biometrics); on iOS prefer immutable shared state.

© rcosteira79, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in plugins/android-skills/skills/android-dev of rcosteira79/android-skills.

Open the folder on GitHubat commit 0f9af5a

Compare with similar skills

Android and KMP Baseline next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Android and KMP Baseline compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Android and KMP Baseline this skillrcosteira79/android-skills150—~3kAutomated safety check: PassMIT
Claude Android NinjaDrjacky/claude-android-ninja124—~5.2kAutomated safety check: PassApache-2.0
Expo Brownfield Integrationmweinbach/agent-coworker1562 repos~900Automated safety check: NotesCustom licence
Android Audio E2Ehyochan/react-native-nitro-sound961—~814Automated safety check: PassMIT
Upgrade React NativeShopify/flash-list7.2k—~1.9kAutomated safety check: PassMIT
Kotlin Tooling Agp9 MigrationJetBrains/skills3632 repos~5.6kAutomated safety check: PassApache-2.0

Similar skills

  • Claude Android Ninja

    Drjacky/claude-android-ninja

    Build and migrate Android apps with Kotlin, Jetpack Compose, MVVM, Hilt, Room 3 (KSP, SQLiteDriver, Flow/suspend DAOs), Navigation3, and multi-module Gradle.

    124 GitHub stars~5.2k tokensUpdated 8 days ago
    MobileAuto-check passed
  • Expo Brownfield Integration

    mweinbach/agent-coworker

    Helps add Expo and React Native to an existing native iOS or Android app, and choose between a prebuilt AAR or XCFramework and a fully integrated build.

    156 GitHub starsUsed in 2 repos~900 tokens
    MobileAuto-check: notes
  • Android Audio E2E

    hyochan/react-native-nitro-sound

    Build and run device-backed Android end-to-end checks for react-native-nitro-sound permissions, recording, playback, listeners, pause/resume, seek, speed, audio focus, lifecycle behavior, and rapid…

    961 GitHub stars~814 tokensUpdated 7 days ago
    MobileAuto-check passed
  • Upgrade React Native

    Shopify/flash-list

    Official

    Upgrade the React Native fixture app to a new version. An agent skill from Shopify/flash-list.

    7.2k GitHub stars~1.9k tokensUpdated 6 days ago
    MobileAuto-check passed
  • Official

    Migrates Kotlin Multiplatform (KMP) projects to Android Gradle Plugin 9.0+.

    363 GitHub starsUsed in 2 repos~5.6k tokens
    MobileAuto-check passed
  • Agp 9 Upgrade

    arindamxd/camerax-android

    Upgrades, or migrates, an Android project to use Android Gradle Plugin (AGP) version 9.

    132 GitHub starsUsed in 4 repos~883 tokens
    MobileAuto-check passed

More from rcosteira79/android-skills

All 21 skills in this repo
  • Guides writing correct, performant Compose and Compose Multiplatform UI across Android, desktop, iOS and web, from state and animation to design-to-code and crash fixes.

    150 GitHub stars~2.6k tokensUpdated 18 days ago
    Auto-check passed
  • Kotlin Multiplatform Boundaries

    rcosteira79/android-skills

    Helps choose how common Kotlin Multiplatform code reaches platform APIs: expect/actual, a common interface with platform bindings, or separate platform screens.

    150 GitHub stars~1.5k tokensUpdated 18 days ago
    Auto-check passed
  • Android Data Layer and Room in KMP

    rcosteira79/android-skills

    Sets out the repository pattern's error-propagation model for Android and Kotlin Multiplatform, plus the Room setup for commonMain.

    150 GitHub stars~1.2k tokensUpdated 18 days ago
    Auto-check passed
  • Android Debugging

    rcosteira79/android-skills

    Android and KMP debugging techniques for crashes, ANRs, memory leaks, R8 traces, Gradle failures and Compose recomposition, built on finding the root cause first.

    150 GitHub stars~2.6k tokensUpdated 18 days ago
    Auto-check passed
  • Android Gradle Build Logic

    rcosteira79/android-skills

    Sets up Android Gradle convention plugins in a build-logic composite build, including the version catalog wiring and shared configuration that are easy to get wrong.

    150 GitHub stars~959 tokensUpdated 18 days ago
    Auto-check passed
  • Android Retrofit

    rcosteira79/android-skills

    A skill your agent uses when setting up or working with Retrofit in Android — service interface definitions, coroutines integration, OkHttp configuration, Hilt module setup, and error handling in…

    150 GitHub stars~942 tokensUpdated 18 days ago
    Auto-check passed

Categories

Questions about Android and KMP Baseline

What does Android and KMP Baseline do?

Sets house defaults for Android and Kotlin Multiplatform work and routes to the right specialized skill for Compose, networking, testing or build tooling. serialization for JSON, and Coil for images. Android uses Retrofit and OkHttp with Room while shared KMP code uses Ktor with Room or SQLDelight, and Retrofit never goes in a shared module since it is Android-only; module boundaries keep the core model package free of Android dependencies and stop feature modules from depending on each other, with platform exceptions mapped to a domain type at the repository boundary.

When should I use Android and KMP Baseline?

Android and KMP Baseline fits situations like: starting any Android or Kotlin Multiplatform task; fixing a bug or refactoring a ViewModel in an Android app; deciding which specialized Android skill a task should route to.

How do I install Android and KMP Baseline in Claude Code?

Run `npx skills add rcosteira79/android-skills --skill android-dev -a claude-code`. Or copy the skill folder (plugins/android-skills/skills/android-dev in rcosteira79/android-skills) into .claude/skills/android-dev in your project. Claude Code loads it when a task matches its description.

How do I install Android and KMP Baseline in Codex?

Run `npx skills add rcosteira79/android-skills --skill android-dev -a codex`. Or copy the skill folder (plugins/android-skills/skills/android-dev in rcosteira79/android-skills) into .agents/skills/android-dev in your project. Codex loads it when a task matches its description.

Can I use Android and KMP Baseline in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add rcosteira79/android-skills --skill android-dev -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/android-dev, .gemini/skills/android-dev, .github/skills/android-dev and .opencode/skills/android-dev in your project.

What does Android and KMP Baseline need to run?

SKILL.md names no scripts, command-line tools or credentials: Android and KMP Baseline is instructions for the agent only.

Does Android and KMP Baseline access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Android and KMP Baseline safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Android and KMP Baseline use?

Android and KMP Baseline is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Android and KMP Baseline use?

About 3k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Android and KMP Baseline?

Skills that share tags, products or a category with Android and KMP Baseline: Claude Android Ninja (Drjacky/claude-android-ninja, 124 stars), Expo Brownfield Integration (mweinbach/agent-coworker, 156 stars), Android Audio E2E (hyochan/react-native-nitro-sound, 961 stars) and Upgrade React Native (Shopify/flash-list, 7.2k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Android and KMP Baseline?

rcosteira79 (a GitHub user) maintains it in rcosteira79/android-skills, which has 150 GitHub stars. The repository holds 21 skills in this directory. The repository was last updated on September 19, 2026.

Source: rcosteira79/android-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.