Composables

Android Kotlin Architecture

Community

haidrrrry

Enforces Clean Architecture, MVVM/MVI, and unidirectional data flow for Android apps. Covers UiState, UiEvent, UiEffect, UseCase boundaries, module structure, and atomic ViewModel state via _state.update. Use when structuring features, refactoring ViewModels, splitting modules, or asking "MVVM vs MVI", "where does state live", "UseCase when".

Overview

Repository
haidrrrry/compose-kotlin-agent-skills
Publisher
haidrrrry
Stars
65
Forks
8
Bundled files
0
License
MIT
Updated
Jul 8, 2026

Installation

tmp=$(mktemp -d)
git clone --depth 1 https://github.com/haidrrrry/compose-kotlin-agent-skills.git "$tmp"
mkdir -p ~/.claude/skills
cp -R "$tmp/skills/android-kotlin-architecture" ~/.claude/skills/android-kotlin-architecture
rm -rf "$tmp"

Instructions

Android Kotlin — Architecture Module

Parent kit: ../../SKILL.md · Index: ../../AGENTS.md

Read First

File When
../../references/01-architecture.md Full MVVM/MVI patterns, container/content composables
../../references/04-coroutines-flow.md StateFlow, Channel effects, stateIn
../../references/05-hilt-di.md @HiltViewModel, repository wiring
../../references/06-room-db.md Repository + Room offline-first

MVI Contract (Mandatory)

@Immutable
data class FeatureUiState(
    val items: List<ItemUi> = emptyList(),
    val isLoading: Boolean = false,
    val error: UiError? = null
)

sealed interface FeatureUiEvent {
    data class SearchChanged(val query: String) : FeatureUiEvent
    data object Refresh : FeatureUiEvent
    data class ItemClicked(val id: String) : FeatureUiEvent
}

sealed interface FeatureUiEffect {
    data class ShowMessage(@StringRes val messageRes: Int) : FeatureUiEffect
    data class NavigateToDetail(val id: String) : FeatureUiEffect
}

class FeatureViewModel @Inject constructor(
    private val repository: FeatureRepository
) : ViewModel() {

    private val _state = MutableStateFlow(FeatureUiState())
    val state: StateFlow<FeatureUiState> = _state.asStateFlow()

    private val _effects = Channel<FeatureUiEffect>(Channel.BUFFERED)
    val effects: Flow<FeatureUiEffect> = _effects.receiveAsFlow()

    fun onEvent(event: FeatureUiEvent) {
        when (event) {
            is FeatureUiEvent.SearchChanged -> onSearchChanged(event.query)
            FeatureUiEvent.Refresh -> refresh()
            is FeatureUiEvent.ItemClicked -> emitNavigate(event.id)
        }
    }

    private fun onSearchChanged(query: String) {
        _state.update { it.copy(searchQuery = query) }  // ONLY mutation style allowed
    }

    private fun refresh() {
        viewModelScope.launch {
            _state.update { it.copy(isLoading = true, error = null) }
            repository.sync()
                .onSuccess { _state.update { it.copy(isLoading = false) } }
                .onFailure { e ->
                    _state.update { it.copy(isLoading = false, error = e.toUiError()) }
                }
        }
    }

    private fun emitNavigate(id: String) {
        viewModelScope.launch { _effects.send(FeatureUiEffect.NavigateToDetail(id)) }
    }
}

Module Layout (Large Apps)

app/
feature-<name>/
  presentation/   # Composables + ViewModel
  domain/         # Models, repository interfaces, UseCases
  data/           # Room, Ktor, mappers
core/
  core-ui/        # Design system
  core-domain/
  core-testing/

Feature modules must not depend on other feature modules — only core-* and domain contracts.

UseCase Rule

Use UseCase Skip UseCase
Logic shared by 2+ ViewModels Single-line repo delegate
Multi-repo orchestration One ViewModel, one repo
Needs isolated unit tests CRUD with no extra rules

Anti-Patterns (Architecture)

Banned Fix
_state.value = newState _state.update { it.copy(...) }
God ViewModel (>200 lines) Split screen or extract UseCases
ViewModel in composable params Pass onEvent lambdas
Domain model with @Entity Entity in data/, map in repository
Collecting Flow in init without stateIn stateIn(WhileSubscribed(5_000))

FAQ

What does Android Kotlin Architecture do?

Enforces Clean Architecture, MVVM/MVI, and unidirectional data flow for Android apps. Covers UiState, UiEvent, UiEffect, UseCase boundaries, module structure, and atomic ViewModel state via _state.update. Use when structuring features, refactoring ViewModels, splitting modules, or asking "MVVM vs MVI", "where does state live", "UseCase when".

Who made Android Kotlin Architecture?

haidrrrry (a community member) publishes it in the haidrrrry/compose-kotlin-agent-skills repository on GitHub.

Is Android Kotlin Architecture free?

Yes. Android Kotlin Architecture is open source, published by haidrrrry under the MIT license.

What comes with Android Kotlin Architecture?

Just its instructions. Everything the agent needs is in one SKILL.md file.

Which agents can use Android Kotlin Architecture?

Any coding agent that reads SKILL.md files, including Claude Code, Codex, Cursor, GitHub Copilot and Gemini CLI. The agent loads the skill when a task matches its description.

What are agent skills?

An agent skill is a folder with a SKILL.md file: instructions that teach a coding agent how to do one kind of task, and optionally files it can read while it works. The agent keeps only the skill's name and description in mind and reads the rest when a task calls for it.

How are agent skills different from MCP servers?

An MCP server gives an agent new tools to call, code that runs somewhere and returns results. A skill gives it knowledge: how to approach a task with the tools it already has. Many agents use both.

How can my agent test my Android app?

Robomori lets coding agents create, start and control Android emulators and devices from one command, so they can install your app, take screenshots and check dark mode, font sizes and languages.

You're subscribed

The next lesson lands in on Wednesday.