Use when reviewing a diff, branch, or PR in a Jetpack Compose Android app (Clean Architecture + MVVM + Hilt). Reviews changed Kotlin/Compose code for correctness bugs and idiom violations, then routes each Compose/Kotlin concern to the bundled focused skills (compose-*, kotlin-*). Triggers on "review my changes", "review this PR", "code review", "check my branch before pushing".
How this skill is triggered — by the user, by Claude, or both
Slash command
/android-compose-review:android-compose-code-review [base-branch | PR<number>] e.g. staging, main, PR92[base-branch | PR<number>] e.g. staging, main, PR92The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Orchestrator skill. It does **two jobs**:
Orchestrator skill. It does two jobs:
Do not duplicate the focused skills' content here. When a concern matches the routing table, invoke that skill and apply it.
StateFlow for UI state, lifecycle-aware collection.These are this-project hooks — check each path first; skip silently if the project doesn't have it:
codegen/android-codegen-rules.md / codegen/android-non-ui-rules.md exist, generated API → Repository → UseCase layers must conform to them.unit_testing_rules/ (or a *testing_rules*.md) exists, follow its coverage bar (commonly ≥ 90% line coverage on Repository / UseCase / ViewModel). Otherwise apply the generic rule: new Repository/UseCase/ViewModel logic should have tests.PR<n> (e.g. PR92) → gh pr diff <n> and gh pr view <n>.staging, main) → git diff <branch>...HEAD (three-dot: changes introduced on this branch vs the merge-base).git diff "$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null | sed 's@^origin/@@' || echo main)"...HEAD.
List changed files; classify each as UI (@Composable), state-holder (ViewModel / state holder), domain (UseCase), data (Repository / API / DAO), or DI. For a large diff (≳20 files), fan out parallel reviewers over clusters, then synthesize and dedupe.file:line. For each, name the skill or rule it came from. Verify high-confidence/blocking findings against source before reporting; prefer concrete findings over speculation.| Label | Meaning |
|---|---|
🔴 blocking | Bug, crash, data loss, security issue, or broken architecture boundary. Must fix before merge. |
🟠 important | Real defect risk or idiom violation that will bite later (e.g. unstable params on a hot composable). Fix strongly advised. |
🟡 nit | Minor style / readability; optional. |
🔵 suggestion | Refactor / simplification opportunity. |
🌟 praise | Something done well — call it out. |
Invoke the named skill (bundled in this plugin) when the diff shows the concern:
| If the diff shows… | Invoke |
|---|---|
Recomposition cost, hot composables, composables.txt / compiler reports | /android-compose-review:compose-recomposition-performance (router) |
Unstable params, skippability, @Stable/@Immutable, collection params | /android-compose-review:compose-stability-diagnostics |
Scroll/animation/gesture State read in composition, value-form layout/draw modifiers, cross-phase back-writes | /android-compose-review:compose-state-deferred-reads |
LaunchedEffect / DisposableEffect / rememberCoroutineScope / rememberUpdatedState / snapshotFlow / snackbar / navigation effects | /android-compose-review:compose-side-effects |
Bare var in a composable, remember { mutableStateOf() }, mutableStateListOf, @ReadOnlyComposable | /android-compose-review:compose-state-authoring |
| Where state should live: local vs hoisted vs state holder vs ViewModel | /android-compose-review:compose-state-hoisting |
| Screen composable taking a ViewModel, collecting state/effects, wiring callbacks while also rendering | /android-compose-review:compose-state-holder-ui-split |
Modifier param, modifier chain order, hardcoded root layout, single-conditional wrappers | /android-compose-review:compose-modifier-and-layout-style |
| Reusable component with proliferating content params / boolean shape flags | /android-compose-review:compose-slot-api-pattern |
AnimatedVisibility, animate*AsState, Transition, AnimatedContent, Crossfade | /android-compose-review:compose-animations |
@Preview, screenshot tests, semantics assertions, UI test for a state-driven composable | /android-compose-review:compose-ui-testing-patterns |
Stored CoroutineScope, launch from init/non-suspend API, runBlocking, broad catch around suspend | /android-compose-review:kotlin-coroutines-structured-concurrency |
StateFlow / SharedFlow / Channel / stateIn / SharingStarted / one-shot events / .value | /android-compose-review:kotlin-flow-state-event-modeling |
If evidence spans multiple rows, apply each matching skill.
These skills are bundled in this plugin, so normally all 13 resolve. But if a routed skill is unavailable (plugin partially installed, or this skill copied somewhere without its siblings), do not silently drop the concern. Instead:
⚠️ Degraded coverage section in the report naming the missing skill and the concern checked at reduced depth. A silent skip reads as "clean" and is the failure mode this section exists to prevent.| Missing skill | Inline fallback check (reduced depth) |
|---|---|
compose-recomposition-performance | Flag expensive work in a composable body not wrapped in remember; flag @Composable functions recomposing on every frame-rate state read. |
compose-stability-diagnostics | Flag List/Set/Map/lambda-bearing data classes passed as composable params without @Immutable/@Stable or an immutable collection type. |
compose-state-deferred-reads | Flag scroll/animation/gesture State read directly in composition; flag value-form offset(x,y) / background() where a lambda form would defer the read. |
compose-side-effects | Flag LaunchedEffect/DisposableEffect with wrong or missing keys; flag side work in the composable body that belongs in an effect; flag missing cleanup. |
compose-state-authoring | Flag bare var in a @Composable; flag mutableStateOf not wrapped in remember. |
compose-state-hoisting | Flag state held too high and passed down, or business logic living in the composable instead of a holder/ViewModel. |
compose-state-holder-ui-split | Flag a screen composable that both collects state/effects from a ViewModel and renders layout — should split into stateful + stateless. |
compose-modifier-and-layout-style | Flag missing Modifier param on a reusable composable; flag suspicious modifier order (e.g. clickable before clip/padding). |
compose-slot-api-pattern | Flag a reusable component accumulating primitive content params + boolean shape flags instead of a content: @Composable () -> Unit slot. |
compose-animations | Flag manual frame/Animatable loops where animate*AsState/AnimatedContent/Crossfade fit; flag animations not driven off state. |
compose-ui-testing-patterns | Flag new state-driven composables with no @Preview and no semantics-based test. |
kotlin-coroutines-structured-concurrency | Flag stored CoroutineScope, runBlocking on a UI/main path, launches from init, and broad catch around suspend calls. |
kotlin-flow-state-event-modeling | Flag one-shot events modeled as StateFlow; flag raw .value mutation where update {} is correct; flag missing stateIn/SharingStarted. |
To confirm all 13 routed skills are present in this plugin install, run:
"${CLAUDE_PLUGIN_ROOT}/scripts/verify-skills.sh"
It exits non-zero and names any missing skill. Add it to CI to keep the bundle intact.
The focused skills handle idiom. This pass handles will it work:
Timer/thread/listener that outlives the ViewModel.collectAsStateWithLifecycle() (not raw collectAsState) so collection stops in background.SimpleDateFormat/String.format without an explicit Locale), toInt() vs toIntOrNull(). Scrutinize every cross-layer field mapping.this.## Review: <branch or PR>
<N> files reviewed · <M> findings (<x> blocking, <y> important)
### 🔴 Blocking
- `path/Foo.kt:42` — <issue>. <why>. [correctness | <skill-name>]
Fix: <one line>
### 🟠 Important
- ...
### 🟡 Nits / 🔵 Suggestions
- ...
### 🌟 Praise
- ...
### ⚠️ Degraded coverage ← omit this section entirely if all routed skills were present
- `compose-stability-diagnostics` not available — stability checked at reduced depth via inline fallback.
**Verdict:** <approve | approve-with-nits | request-changes>
Keep findings concrete and cite file:line. Prefer a few high-confidence findings over a long uncertain list, unless the user asked for an exhaustive review.
npx claudepluginhub ictech-projects/android-claude-skills --plugin android-compose-reviewGuides collaborative design exploration before implementation: explores context, asks clarifying questions, proposes approaches, and writes a design doc for user approval.
Creates structured, bite-sized implementation plans from specs or requirements before writing code. Useful for breaking down multi-step tasks into testable steps with file structure and task boundaries.
Resolves in-progress git merge or rebase conflicts by analyzing history, understanding intent, and preserving both changes where possible. Runs automated checks after resolution.