# Using Strong Skipping Correctly

Use this skill to reason about Jetpack Compose's Strong Skipping Mode, the default...

- Repository: https://github.com/skydoves/compose-performance-skills (524 stars)
- Category: Mobile
- License: Apache-2.0
- Last updated: 2026-06-16
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add skydoves/compose-performance-skills --skill using-strong-skipping-correctly -g -a claude-code -y`
Codex: `npx skills add skydoves/compose-performance-skills --skill using-strong-skipping-correctly -g -a codex -y`
Cursor: `npx skills add skydoves/compose-performance-skills --skill using-strong-skipping-correctly -g -a cursor -y`
Gemini CLI: `npx skills add skydoves/compose-performance-skills --skill using-strong-skipping-correctly -g -a gemini-cli -y`

## Description

Use this skill to reason about Jetpack Compose's Strong Skipping Mode, the default since Kotlin 2.0.20, including what it changes about skippability, when it does and does not auto-`remember` lambdas, and which escape hatches (`@DontMemoize`, `@NonSkippableComposable`, `@NonRestartableComposable`, `@ReadOnlyComposable`) apply where. Covers verifying the mode is active, auditing lambda capture sites, and the gaps where strong skipping does not memoize (`LazyListScope.items {}`, `Modifier.pointerInput {}`, object expressions, non-@Composable scopes). Use when the developer asks "do I still need @Stable?", "does this composable skip?", "why does this still recompose despite strong skipping", "when do I need @DontMemoize or @NonSkippableComposable?", is migrating from older Compose, or sees auto-remembered lambdas in compiler output.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Using Strong Skipping Correctly, make every restartable composable skippable, intentionally

Strong Skipping Mode is the Compose compiler behavior that became the default with the Kotlin Compose compiler plugin shipped in **Kotlin 2.0.20**. It changes two things at once: every restartable composable becomes skippable regardless of param stability (unstable params are compared with `===`, stable params with `equals`), and every **capturing** lambda literal written inside a `@Composable` function is automatically wrapped in `remember(captures) { ... }`. Both behaviors are on by default; neither requires opt-in flags on Kotlin 2.0.20+. Lambdas with no captures are already compiler-emitted singletons and are NOT wrapped, only capturing lambdas need (and get) the auto-`remember` treatment.

That sounds like "stability no longer matters", and for a lot of UI code it almost is. But the change leaves three sharp edges: stable types still need correct `equals` semantics so the `===` fallback does not invalidate every recompose, lambdas in non-@Composable scopes (`LazyListScope.items { }`, `Modifier.pointerInput { }`, plain object expressions) are not auto-memoized, and a few intentional cases need explicit opt-out via `@DontMemoize` or `@NonSkippableComposable`. This skill walks the verification, audit, and escape-hatch decisions for working in a strong-skipping world.

## When to use this skill

The rest: https://github.com/skydoves/compose-performance-skills/blob/HEAD/recomposition/using-strong-skipping-correctly/SKILL.md
