by Meet-Miyani
AI agent skill for Jetpack Compose & Compose Multiplatform (KMP/CMP). MVI architecture, Navigation 3, Koin/Hilt, Ktor, Room, DataStore, Paging 3, Coil, coroutines/Flow, animations, performance, accessibility, testing, and cross-platform patterns. Works with Codex, Cursor, Claude Code.
# Add to your Claude Code skills
git clone https://github.com/Meet-Miyani/compose-skillThis skill covers the full Compose app development lifecycle — from architecture and state management through UI, networking, persistence, performance, accessibility, cross-platform sharing, build configuration, and distribution. Jetpack Compose and Compose Multiplatform share the same core APIs and mental model. Not all Jetpack libraries work in commonMain — many remain Android-only. A subset of AndroidX libraries now publish multiplatform artifacts (e.g., lifecycle-viewmodel, lifecycle-runtime-compose, datastore-preferences), but availability and API surface vary by version. Before adding any Jetpack/AndroidX dependency to commonMain, verify the artifact is published for all required targets by checking Maven Central or the library's official documentation. CMP uses expect/actual or interfaces for platform-specific code. MVI (Model-View-Intent) is the recommended architecture, but the skill adapts to existing project conventions.
Do not force migration. If a project already follows MVI with its own conventions (different base class, different naming, different file layout), respect that. Adapt to the project's existing patterns. The architecture pattern — unidirectional data flow with Event, State, and Effect — is what matters, not a specific base class or framework. Only suggest structural changes when the user asks for them or when the existing code has clear architectural violations (business logic in composables, scattered state mutations, etc.).
When helping with Jetpack Compose or Compose Multiplatform code, follow this process:
references/ only when deeper guidance is needed. Use the Quick Routing in the Detailed References section to pick the right file.Before recommending any new dependency or version upgrade, verify:
group:artifact:version) exist and are current.commonMain). Do not assume a Jetpack library works in commonMain unless verified.How to verify:
If verification is not possible (no documentation tool, no network access, docs unavailable), provide the standard or latest known dependency snippet anyway. Add a brief comment (e.g., // Verify latest version) so the user isn't blocked.
When adding a new dependency, upgrading major versions, or verifying latest API patterns, use a documentation MCP tool (e.g., Context7) if available. Before invoking, verify the tool's exact name and parameter schema — tool names vary across environments.
Alternative: Users can add use context7 (or equivalent) to their prompt. Bundled references remain the primary source for architectural patterns and MVI guidance; use documentation tools for API-specific and version-specific queries.
Both MVI and MVVM use unidirectional data flow: UI renders state → user acts → ViewModel updates state → UI re-renders. The difference is how UI actions reach the ViewModel.
sealed interface Event + single onEvent() entry pointonTitleChanged(), save())Both patterns use:
StateFlowChannelDefault recommendation: Preserve the project's existing pattern when it is coherent. For new projects, choose based on team preference and screen complexity. See Architecture & State Management for the decision guide, then mvi.md or mvvm.md for implementation details.
These boundaries apply to both MVI and MVVM:
collectAsStateWithLifecycle(), collects effects via CollectEffect (see compose-essentials.md), binds navigation/snackbar/platform APIsonEvent, MVVM: individual callbacks), renders the screen, adapts callbacks for leaf composablesonEvent() as the single entry point; MVVM: implement named functions for user actionsFor calculator/form screens, split state into four buckets:
| Concern | Where | Example |
|---|---|---|
| Raw field text | state fields | "12", "12.", "" |
| Parsed/derived | state computed props or fields | val hasRequiredFields: Boolean |
| Validation | state.validationErrors or similar | mapOf("name" to "Required") |
| Loading/refresh | state flags | isSaving = true |
| One-off UI commands | Effect via Channel | snackbar, navigate, share |
| Scroll/focus/animation | local Compose state | LazyListState, focus requester |
Apply these unless the project already follows a different coherent pattern.
| Concern | Default |
|---|---|
| ViewModel | One ViewModel per screen (commonMain for CMP, feature package for Android-only). MVI: onEvent(Event) entry point; MVVM: named functions |
| State source of truth | StateFlow<FeatureState> owned by the ViewModel |
| Event handling | MVI: onEvent(event) with when expression; MVVM: named functions. Both map user actions to state updates, effect emissions, and async launches |
| Side effects | Effect sent via Channel<Effect>(Channel.BUFFERED) for UI-consumed one-shots (navigate, snackbar). Async work (network, persistence) launched in viewModelScope |
| Async loading | Keep previous content, flip loading flag, cancel outdated jobs, update state on completion |
| Dumb UI contract | Render props, emit explicit callbacks, keep only ephemeral visual state local |
| Resource access | Semantic keys/enums in state; resolve strings/icons close to UI. CMP uses Res.string / Res.drawable (not Android R). See Resources |
| Platform separation | CMP: share in commonMain, expect/actual (verify Kotlin 1.9 vs 2.0+ via build.gradle.kts or ask user) or interfaces, Koin DI by default. Android-only: standard package, Hilt or Koin DI |
| Navigation | ViewModel emits semantic navigation effect; route/navigation layer executes it |
| Persistence (settings) | DataStore Preferences in commonMain for key-value settings; Typed DataStore (JSON) for structured settings objects; Room for relational/queried data. See DataStore |
| Testing | ViewModel event→state→effect tests via Turbine in commonTest; validators/calculators tested as pure functions; platform bindings tested per target |
import ... as ... aliases to resolve name clashesMutableState, controllers, lambdas, or platform objects in screen statecom.example.pkg.SomeClass.method()) — always import at file topDo not load reference files for basic Compose usage. If you already know how to build the required UI or logic, write the code immediately. Load exactly one reference file only when the task involves advanced concepts (e.g., Paging 3, Nav 3 setup). Pick the right file below — do not load files speculatively.
@Resource routes or type-safe API definitions → networking-ktor.md § Type-Safe ResourcesRun ./scripts/validate.sh to scan the skill package against the agentskills.io spec. It checks token budgets, broken links, file structure, and content quality. Fix any errors before committing.
This is an AI agent skill — not a library, not documentation. Install it once, and your AI coding agent (Codex, Cursor, Claude Code) gains production-grade knowledge of the entire Compose app development lifecycle: architecture, UI, state, navigation, networking, persistence, performance, accessibility, cross-platform, build configuration, distribution, and code review.
The skill covers Android, iOS, Desktop, and Web targets with the same architectural principles.
| Concern | Without | With |
|:--------|:--------|:-----|
| State management | Scattered mutableStateOf in composables | Single StateFlow<State> owned by ViewModel |
| Business logic | Mixed into UI layer | Isolated in ViewModel's onEvent() handler |
| One-shot actions | Boolean flags in state | Channel<Effect> for navigation, snackbar |
| Recomposition | Frequent, hard to diagnose | Minimized via state shape and read boundaries |
| Navigation | Ad-hoc calls from composables | Semantic effects, route layer executes |
| Networking | Inconsistent error handling | Ktor + Result/ApiResult wrapper, DTO mappers |
| Persistence | Raw SharedPreferences | DataStore + Room with MVI integration |
| Accessibility | Missing or incorrect semantics | contentDescription, touch targets, WCAG contrast |
| Cross-platform | Android-only or inconsistent | commonMain with expect/actual for platform APIs |
| Build config | Hardcoded versions | Version catalog, AGP 9+ patterns, conventions |
| Testing | Manual UI testing | ViewModel event→state→effect via Turbine |
| Code review | Inconsistent patterns | Anti-pattern detection with documented fixes |
Pick your agent and run one command. The clone target becomes the skill folder — agents detect SKILL.md at the root automatically.
Only three things matter for the skill to work:
SKILL.md,agents/, andreferences/. Everything else in this repo (README, LICENSE, scripts, assets, .github) is for documentation, validation, and CI — the agent never reads them. If you prefer a minimal install, you only need those three.
Why is
SKILL.mdat the root? All three agents (Codex, Cursor, Claude Code) look forSKILL.mdat the top level of the skill directory. This repo is structured so that cloning it directly into the skill path gives you a ready-to-use skill — no moving files or extra nesting required.
Skill installation paths may change as agents evolve. The locations below are accurate at the time of writing — for the latest instructions, refer to each agent's official docs or ask your agent "How do I add a skill?"
| Client | User-global | Per-repo |
|:-------|:------------|:---------|
| Codex | ~/.codex/skills/compose-skill | .codex/skills/compose-skill |
| Cursor | ~/.cursor/skills/compose-skill | .cursor/skills/compose-skill |
| Claude Code | ~/.claude/skills/compose-skill | .claude/skills/compose-skill |
| Other agents | Upload SKILL.md, agents/, and references/ as project knowledge | — |
# Replace <path> with the install location from the table above
git clone https://github.com/Meet-Miyani/compose-skill.git <path>
# Examples:
git clone https://github.com/Meet-Miyani/compose-skill.git ~/.cursor/skills/compose-skill
git clone https://github.com/Meet-Miyani/compose-skill.git .codex/skills/compose-skill
| Problem | Fix |
|:--------|:----|
| Folder named compose-skill-main | Rename to compose-skill (GitHub ZIP downloads add -main) |
| SKILL.md not at root of skill folder | Don't nest inside another directory — clone directly into the skill path |
| Skill not detected after install | Restart the agent / IDE |
| Client | How to verify |
|:-------|:--------------|
| Codex | Run /skills — compose-skill appears in the list |
| Cursor | Settings → Rules — skill appears under Agent Decides |
| Claude Code | Run /skills or ask "What skills are available?" |
Once installed, the skill activates automatically when your prompt matches its triggers (@Composable, StateFlow, ViewModel, KMP, Ktor, recomposition, DataStore, etc.). You can also invoke it explicitly — the syntax varies by client:
| Client | Explicit invocation | Automatic |
|:-------|:-------------------|:----------|
| Codex CLI | $compose-skill in your prompt | Yes |
| Codex IDE extension | $compose-skill in chat | Yes |
| Codex App | /compose-skill in chat | Yes |
| Cursor | /compose-skill in Agent chat | Yes |
| Claude Code | /compose-skill in chat | Yes |
Codex CLI / IDE extension — dollar-sign prefix:
$compose-skill Refactor this screen to MVI with proper state modeling.
Codex App / Cursor / Claude Code — slash prefix:
/compose-skill How do I set up Paging 3 with MVI in a KMP project?
compose-skill/
│
│ ## Required (the skill itself) ─────────────────────
├── SKILL.md # Skill definition — agent reads this
├── agents/
│ └── openai.yaml # Codex UI metadata
└── references/ # 37 deep-dive reference files
│ # (loaded on-demand by SKILL.md)
├── architecture.md
├── coroutines-flow.md
├── compose-essentials.md
├── material-design.md
├── image-loading.md
├── lists-grids.md
├── paging.md
├── paging-offline.md
├── paging-mvi-testing.md
├── navigation.md
├── navigation-3.md
├── navigation-2.md
├── navigation-3-di.md
├── navigation-2-di.md
├── navigation-migration.md
├── performance.md
├── animations.md
├── ui-ux.md
├── testing.md
├── room-database.md
├── datastore.md
├── networking-ktor.md
├── networking-ktor-auth.md
├── networking-ktor-testing.md
├── networking-ktor-architecture.md
├── dependency-injection.md
├── koin.md
├── hilt.md
├── cross-platform.md
├── resources.md
├── ios-swift-interop.md
├── accessibility.md
├── clean-code.md
├── anti-patterns.md
├── gradle-build.md
└── ci-cd-distribution.md
│
│ ## Optional (repo extras) ──────────────────────────
├── README.md # This file (not read by agents)
├── LICENSE # MIT License
├── assets/
│ └── compose-multiplatform-icon.svg # Logo for README
└── scripts/
└── validate.sh # Skill scanner / validation tool
No comments yet. Be the first to share your thoughts!