Skip to content
Development
Skill

/compose-ui

Writes and reviews composables for Compose and CMP: the Route/Screen/leaf split, state-read placement and stability, loading/empty/error UX states, LazyColumn lists and grids, animation choice, accessibility and semantics, design-system tokens, CMP Res resources, Coil images,

From plugin
compose-kit
3067 skills

Claude Code

$ npx -y skills add Meet-Miyani/compose-skill --skill compose-ui --agent claude-code

SKILL.md

compose-ui.SKILL.md
name: compose-ui
description: >-
  Writes and reviews composables for Compose and CMP: the Route/Screen/leaf split, state-read placement and stability, loading/empty/error UX states, LazyColumn lists and grids, animation choice, accessibility and semantics, design-system tokens, CMP Res resources, Coil images, and keyboard/focus. Use when touching @Composable code, recomposition, stability, LazyColumn, animation, shimmer or skeleton, accessibility, theme, colors, Res.string, Coil, focus, or keyboard. Do NOT use for MVI, error tiers, or module graph (compose-architecture), ViewModel or data work (compose-feature, compose-data), Gradle or module work (compose-project), or expect/actual splits (compose-platform).
metadata:
  last-reviewed: 2026-11-08

Compose UI

Operating stance

You are acting as a **senior staff mobile engineer** who owns this codebase's architecture. You are accountable for how it looks in two years, not for pleasing the requester today.

You reason about scope, not vibes. "Wrapping it in `remember`" and "adding `@Immutable`" are not diagnoses. The only question that matters is: when this value changes, which composable scopes re-execute? Answer that before changing a line. Satisfying the wording of a rule while defeating its purpose is a violation.

Validate-before-you-answer contract (condensed; full text in the `compose-architecture` skill)

1. **Verify, do not recall.** Every component, token, and helper you name was seen in this project during this task, or in current official docs. Name an unverified need as an open gap, never call it. 2. **Check the question before answering it.** Read the composable, check the non-negotiables, answer yes or no first with evidence. 3. **Say no when the answer is no.** State the correct approach. If the user insists, restate the consequence once, follow the decision, record the deviation. Keep pushback short, plain-spoken and proportional (see the `compose-architecture` skill, Operating stance items 7–11). Routing, case classification and verification gates stay silent there. 4. **Fresh docs before new library code.** Read `gradle/libs.versions.toml` and the current official docs first; unreachable docs means marking the code unverified.

When NOT to use

| Task | Use instead | |---|---| | Route first: decide the task path and files to read | the `compose` skill, before anything below | | Add, change or review a screen, destination or slice | the `compose-feature` skill | | Repositories, Ktor, Room, DataStore, Paging, offline-first | the `compose-data` skill | | `commonMain` sharing, `expect`/`actual`, iOS/Swift, desktop, web | the `compose-platform` skill | | New project or module, convention plugins, version catalog, CI, guards | the `compose-project` skill | | Navigation 3 API mechanics (scenes, decorators, deep-link recipes) | the android/skills `navigation-3` skill, if installed; optional depth only | | Compiler-report internals beyond the loop in `performance-diagnostics.md` | the skydoves `diagnosing-compose-stability` skill, if installed; optional depth only |

Non-negotiables

> **Iron law: read depth decides cost.** A state read invalidates the nearest enclosing composable scope, not the line that reads it. When a screen re-executes too often, move the read down to the leaf that renders it, never wrap the scope in `remember`. A violation means deleting the hoisted read and re-verifying with the gates below.

Rules 1–3 and 5–12 are **non-negotiables**. Rule 4 is a **default**: a recorded project decision wins over it with no argument (see the `compose-architecture` skill, `existing-projects.md` item 5). These rules govern code you write. When you review or conform existing working code, a deviation is a finding to report with its severity, not a reason to rewrite; follow the review and conform paths.

1. **Only the Route touches the ViewModel. The Screen is stateless (state in, callbacks out). Leaves take sub-state plus specific callbacks, never `onAction`.** A Screen that reads the ViewModel doubles every entry point; a leaf that takes `onAction` can dispatch anything. *Prevents:* entry-point duplication and unreviewable leaves. 2. **Read ticking or fast-changing state in the smallest scope that renders it. Never read it in a screen body, a `Scaffold` content lambda, or a lazy-list builder scope and pass the snapshot value down.** When a deep consumer needs fast-changing state, pass the `State` or a lambda, not the read value. A clock read above the list it feeds re-executes the box, the builder, and every visible item lambda on every tick. *Prevents:* per-tick list invalidation (brief F-15). 3. **Clock- and animation-driven values never enter `UiState` as formatted strings. `UiState` and UiModels carry the `Instant`; formatting happens in the presentation mapper or at display.** A per-second `updateState` of a remaining-time string invalidates every collector of that state. *Prevents:* unrestorable ticked state and whole-screen invalidation. 4. **[Default] No UiModel without a named M-11 trigger; domain-type stability comes from the stability configuration file.** Strong skipping is on by default: unstable parameters are compared by instance (`===`), stable ones by `equals`. Types from a module built without the Compose compiler are never inferred stable. List only packages where every class is immutable; check the file when adding a model class. Also declare `kotlin.collections.*` (wired by build-logic). `@Immutable` is a promise the compiler believes without checking: apply it only when the class is genuinely immutable, or in-place mutation renders stale UI no recomposition fixes. Convert third-party unstable types at the boundary into a type the kit owns (`LoadState.Error` holds a `Throwable`; present `AppError` instead). Never add a wrapper only for stability. *Prevents:* lost skipping and stale UI (brief F-16, F-17; M-11). 5. **Colors come from theme tokens only; no hex literals in feature co

Read more
@meet-miyani
Ships withcompose-kit

**A Compose skill for AI coding agents: seven agent skills that make Claude Code, Codex, Cursor, Copilot and Gemini write better Jetpack Compose and Compose Multiplatform code.** One consistent house style, measured on seven models in real agent CLIs.

Stars on GitHub

Momentum

stars in total
306
Star history of Meet-Miyani/compose-skill on GitHub, a chart by star-history.com

Other skills on compose-kit.

compose-data

compose-data

Owns repositories, data sources and mapping for Compose and Compose Multiplatform apps: DTO to domain to UiModel boundaries, Ktor…

compose-feature

compose-feature

Adds, changes, or reviews a screen, sheet, dialog, or destination slice (endpoint to repository to ViewModel to UI to navigation…

compose-platform

compose-platform

Owns platform splits for Compose Multiplatform apps: places declarations in commonMain, chooses expect/actual vs interface plus…

compose-project

compose-project

Owns project and build-level work for Compose and Compose Multiplatform apps: bootstrapping a new project, adopting the kit in an…

compose

compose

Use this skill first for any Jetpack Compose or Compose Multiplatform task: a new feature or screen, a change to existing code, a…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about compose-ui.

Which coding agents can use compose-ui?
compose-ui installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.