Agent skill

Using Strong Skipping Correctly

by rosuH in rosuH/EasyWatermark

A skill your agent uses 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…

Apache-2.0Auto-check passedMobile

Install Using Strong Skipping Correctly

skills CLI
$ npx skills add rosuH/EasyWatermark --skill using-strong-skipping-correctly -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install rosuH/EasyWatermark using-strong-skipping-correctly --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/rosuH/EasyWatermark.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/using-strong-skipping-correctly .claude/skills/using-strong-skipping-correctly && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
using-strong-skipping-correctly
GitHub stars
1.9k
Used in
1 other repo
Token cost
~5.5k tokens
SKILL.md length
1,810 words
Files
2 (incl. references)
Skills in repo
28
Repo updated
First seen
Licence
Apache-2.0

At a glance

A skill your agent uses 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…

  • Works in 5 steps: Verify strong skipping is actually active → Audit lambda capture sites inside… → Identify the gaps where strong skipping… → …
  • Reason about Jetpack Composes Strong Skipping Mode — the default since Kotlin 2.0.20 — including what it changes about skippability
  • SKILL.md covers When to use this skill, When NOT to use this skill, Prerequisites and Workflow, plus 4 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Using Strong Skipping Correctly is an agent skill from rosuH/EasyWatermark. 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…

Its SKILL.md is about 5.5k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files, including reference files (for example `references/escape-hatches.md`).

It sits in Mobile, covering Android development. It works with Kotlin and Jetpack Compose. The repository describes itself as: 🔒 🖼 Securely, easily add a watermark to your sensitive photos. 安全、简单地为你的敏感照片添加水印,防止被人泄露、利用. The licence is Apache-2.0.

When your agent uses it

  • Reason about Jetpack Composes Strong Skipping Mode — the default since Kotlin 2.0.20 — including what it changes about skippability
  • It does and does not auto-remember lambdas
  • Which escape hatches (@DontMemoize
  • @NonSkippableComposable

Example prompts

  • “do I still need @Stable?”
  • “does this composable skip?”
  • “why does this still recompose despite strong skipping”
  • “/using-strong-skipping-correctly”

Workflow steps

5 steps, taken from the step headings in SKILL.md.

  1. Verify strong skipping is actually active
  2. Audit lambda capture sites inside @Composable scopes
  3. Identify the gaps where strong skipping does NOT memoize
  4. Decide on escape hatches
  5. Prove behavior with @TraceRecomposition

What it can do on your machine

Read from SKILL.md and the folder at commit 61223db. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are kotlin and bash).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • developer.android.com
    • medium.com
    • chrisbanes.me
    • github.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Using Strong Skipping Correctly loads about 5.5k tokens when it runs, and up to ~8.6k if it reads all its reference files. Until then it costs about 219 tokens; SKILL.md has 1,810 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~219
When it runs · the whole SKILL.md, loaded when a task matches
~5.5k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~8.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from rosuH/EasyWatermark at commit 61223db, republished under its Apache-2.0 licence (© rosuH). 1,810 words, ~5,471 tokens.

Download SKILL.mdSave it as .claude/skills/using-strong-skipping-correctly/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
using-strong-skipping-correctly
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.
license
Apache-2.0. See LICENSE for complete terms.
metadata.author
Jaewoong Eum (skydoves)
metadata.keywords
jetpack-compose, performance, strong-skipping, recomposition, lambda-memoization, dont-memoize, non-skippable-composable, kotlin-2.0.20, compose-compiler

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 developer asks "do I still need @Stable?" or "does this composable skip now?".
  • A composable still recomposes on every parent tick even though the developer "thought strong skipping fixed that".
  • A lambda allocation question comes up — "is this onClick = { vm.add(it) } allocating per recompose?".
  • Migrating a project from Kotlin 1.9.x / Compose Compiler 1.5.x to Kotlin 2.0.20+ and reconciling reports that now show restartable skippable everywhere.
  • The developer encounters @DontMemoize or @NonSkippableComposable in code or compiler output and asks what they do.
  • The user mentions "strong skipping", "auto-remember", "@DontMemoize", "@NonSkippableComposable", or "skippable everywhere".

When NOT to use this skill

  • The conceptual question is "what makes a type stable in the first place?" — use ../../stability/understanding-stability-inference/SKILL.md.
  • Stability is regressing silently and the team needs a CI gate — use ../../stability/enforcing-stability-in-ci/SKILL.md.
  • Even with strong skipping on, type-level stability still matters for diagnostic clarity and for equals-based skipping to work — use ../../stability/diagnosing-compose-stability/SKILL.md to fix the underlying types.
  • The recomposition is happening but the developer cannot see it — use ../debugging-recompositions/SKILL.md to instrument first.

Prerequisites

  • Kotlin 2.0.20+ with the Compose compiler Gradle plugin applied via org.jetbrains.kotlin.plugin.compose. Strong Skipping is on by default. To turn it off on Kotlin 2.0.20+, use composeCompiler { featureFlags.add(ComposeFeatureFlag.StrongSkipping.disabled()) } (the legacy enableStrongSkippingMode = true property is @Deprecated("Use the featureFlags option instead") and still works on older Kotlin).
  • Compose Compiler reports turned on for the module under audit (see ../../stability/diagnosing-compose-stability/SKILL.md).
  • Builds running in release when reading reports — debug adds Live Literals which distort skip behavior (see ../../measurement/testing-compose-in-release-mode/SKILL.md).
  • Familiarity with the per-composable line format in *-composables.txt (restartable skippable fun Foo(...)).

Workflow

1. Verify strong skipping is actually active

Before claiming any behavior is "because of strong skipping", confirm the toolchain is on a version where it is the default, or the legacy flag is set.

bash
./gradlew :app:dependencies --configuration kotlinCompilerPluginClasspathRelease | grep -i compose

Expect the Compose compiler plugin to come from Kotlin 2.0.20 or later. In build.gradle.kts:

kotlin
plugins {
    alias(libs.plugins.kotlin.android)        // Kotlin 2.0.20+
    alias(libs.plugins.kotlin.compose)        // org.jetbrains.kotlin.plugin.compose
}

To disable strong skipping on Kotlin 2.0.20+ (the modern feature-flag DSL):

kotlin
import androidx.compose.compiler.plugins.kotlin.ComposeFeatureFlag

composeCompiler {
    featureFlags.add(ComposeFeatureFlag.StrongSkipping.disabled())
}

The legacy property composeCompiler { enableStrongSkippingMode = true } is @Deprecated("Use the featureFlags option instead") in modern Compose Compiler Gradle plugin releases. It still works (and is still the only switch on older Kotlin 1.9.x / 2.0.0–2.0.10), but new code should prefer featureFlags.add(ComposeFeatureFlag.StrongSkipping.disabled()) when opting out.

Then regenerate Compose Compiler reports and grep for a known previously-unstable signature:

bash
./gradlew :app:assembleRelease
grep -A1 "restartable" app/build/compose_compiler/app-release-composables.txt | head -40

Under strong skipping, every restartable composable should print restartable skippable, including ones that take List<Foo> or other unstable parameters. If a composable is still listed restartable without skippable, it is using @NonSkippableComposable (intentional) or the mode has been turned off (e.g. someone added featureFlags.add(ComposeFeatureFlag.StrongSkipping.disabled()) or set the legacy enableStrongSkippingMode = false).

2. Audit lambda capture sites inside @Composable scopes

Strong skipping wraps every capturing lambda literal written inside a @Composable function in remember(captures) { ... }. The captured-values list is the compiler-generated remember key. Capture-less lambdas (e.g. { vm.refresh() } where vm is a stable file-scope reference, or { /* no-op */ }) are already compiler-emitted singletons and are NOT auto-remembered — there is nothing to key on. Three consequences:

  • A capture-less lambda is a single shared instance across all recompositions of the surrounding function (singleton emitted by the compiler).
  • A lambda that captures only stable values is memoized once via remember(captures) and re-used across recompositions while the captures compare equal.
  • A lambda that captures an unstable value (e.g. a List<Foo> literal not hoisted) re-captures on every recompose because the unstable capture compares with ===, and a fresh literal is a new reference.

Inspect the suspect call site. The mental model: "what does this lambda close over, and is each capture stable by equals and identity-stable across recompositions?".

kotlin
// RIGHT — captures stable id + stable callback; auto-remembered by strong skipping
@Composable
fun Row(snack: Snack, onClick: (Long) -> Unit) {
    Button(onClick = { onClick(snack.id) }) { Text(snack.name) }
}
kotlin
// WRONG — captures a freshly allocated list literal; new reference each recompose
@Composable
fun Header(title: String) {
    Toolbar(actions = listOf(Action.Share, Action.Save)) { /* ... */ }
}
// WRONG because: `listOf(...)` allocates a new List every recompose. Even with strong
// skipping the unstable param compares with ===, fails, and Toolbar recomposes every time.
kotlin
// RIGHT — hoist the unstable literal so its identity is stable
@Composable
fun Header(title: String) {
    val actions = remember { listOf(Action.Share, Action.Save) }
    Toolbar(actions = actions) { /* ... */ }
}
3. Identify the gaps where strong skipping does NOT memoize

Auto-remember only applies to lambdas inside a @Composable function context. The following are not @Composable scopes; lambdas inside them are not auto-remembered and need a manual remember(key) if allocation matters:

  • LazyListScope.items { ... }, LazyGridScope.items { ... }, LazyVerticalGrid.items { ... }, etc. — the items block is a regular Kotlin DSL builder.
  • Modifier.pointerInput { ... }, Modifier.draggable { ... }, Modifier.scrollable { ... } — non-@Composable lambdas.
  • Object expressions and SAM conversions (e.g. object : DefaultLifecycleObserver { }).
  • Modifier.drawBehind { ... }, Modifier.drawWithCache { ... } — the lambda parameters are not @Composable.
  • Coroutine builders inside non-@Composable scopes.

For these, hoist a stable lambda yourself, keyed on whatever may change:

kotlin
// WRONG — onClick allocated per item per recompose; strong skipping does not reach here
LazyColumn {
    items(snacks, key = { it.id }) { snack ->
        SnackRow(snack, onClick = { vm.select(snack.id) })
    }
}
// WRONG because: `items { snack -> ... }` is LazyListScope, not a @Composable function.
// Strong skipping does not auto-remember the onClick lambda — a new instance allocates per row,
// per recompose, and SnackRow's `===` comparison on the lambda param fails every time.
kotlin
// RIGHT — hoist a stable handler keyed on the stable callback
LazyColumn {
    items(snacks, key = { it.id }) { snack ->
        val onClick = remember(snack.id) { { vm.select(snack.id) } }
        SnackRow(snack, onClick = onClick)
    }
}
kotlin
// RIGHT — even better: pass the id-aware callback once
LazyColumn {
    items(snacks, key = { it.id }) { snack ->
        SnackRow(snack, onClick = vm::select)   // method reference is stable
    }
}
4. Decide on escape hatches

Strong skipping is opinionated. A handful of cases legitimately need the opposite behavior. The full reference table is in references/escape-hatches.md; the high-level decision tree:

  • @DontMemoize at a lambda expression site (the annotation targets EXPRESSION only, not TYPE) — the lambda must NOT be auto-remembered. Use when the lambda intentionally captures a fresh value per call (e.g. a logger that should record the latest counter, not the one captured by the first composition). Apply it at the call site: Button(onClick = @DontMemoize { ... }), never at a parameter type position like (@DontMemoize () -> Unit).
  • @NonSkippableComposable on a function — opt the function out of skipping entirely. Use for side-effect-only composables (a logger, a debug overlay) that must run on every recompose regardless of param equality.
  • @NonRestartableComposable on a function — drop the restart scope entirely. Use only for very small composables where the restart bookkeeping costs more than the function body. Almost never needed in app code; Compose UI uses it internally.
  • @ReadOnlyComposable on a function — declare the function only reads composition values and produces no nodes, so it can run in initialization contexts (e.g. computing a value to pass into another composable). Compose's MaterialTheme.colorScheme getters use it.
kotlin
// RIGHT — logger composable that must always emit
@NonSkippableComposable
@Composable
fun RecompositionLogger(label: String) {
    SideEffect { Log.d("Recomp", "tick: $label @ ${System.currentTimeMillis()}") }
}
kotlin
// RIGHT — annotate the lambda expression that intentionally captures fresh per-call state.
// @DontMemoize is @Target(EXPRESSION) — apply it on the lambda literal, NOT on the type.
@Composable
fun TraceClicks(counter: Int, content: @Composable (() -> Unit) -> Unit) {
    content(@DontMemoize { Log.d("Click", "counter at click time = $counter") })
}
5. Prove behavior with @TraceRecomposition

Reading reports tells the story up to the function boundary. To confirm a specific composable is or is not being skipped at runtime, instrument with @TraceRecomposition from compose-stability-analyzer. Cross-link ../../measurement/tracing-recompositions-at-runtime/SKILL.md for the full setup. The two-line summary:

kotlin
@TraceRecomposition(traceStates = true)
@Composable
fun SnackRow(snack: Snack, onClick: (Long) -> Unit) { /* ... */ }

Logcat will print one line per recomposition with the changed parameters, which directly answers "did strong skipping skip this call or not?".

Show full SKILL.md (700 more words)Show less

Patterns

Pattern: stability still matters even under strong skipping

Strong skipping does not eliminate the need for @Immutable / @Stable. It changes the comparison from equals to === for unstable params. === is reference equality. If a stable type is needed in a hot path, mark it @Immutable so equals is used and structurally-equal instances skip.

kotlin
// WRONG
data class Filter(val tags: List<String>, val sort: SortOrder)

@Composable
fun FilterBar(filter: Filter) { /* ... */ }
// WRONG because: Filter is unstable (List<String> is unstable). Strong skipping makes
// FilterBar skippable, but only when `prevFilter === newFilter`. A copy() with the same
// content fails identity, recomposes the bar, every time.
kotlin
// RIGHT
@Immutable
data class Filter(val tags: ImmutableList<String>, val sort: SortOrder)

@Composable
fun FilterBar(filter: Filter) { /* ... */ }
// RIGHT because: @Immutable + ImmutableList makes Filter stable. Strong skipping uses
// equals(), and structurally-equal copies skip.
Pattern: literal collection in a hot composable param
kotlin
// WRONG
@Composable
fun Toolbar(title: String) {
    ActionRow(actions = listOf(Action.Share, Action.Save))
}
// WRONG because: a fresh List allocates per recompose. Strong skipping makes ActionRow
// skippable, but the List param fails === every time and the body re-runs.
kotlin
// RIGHT
private val ToolbarActions = persistentListOf(Action.Share, Action.Save)

@Composable
fun Toolbar(title: String) {
    ActionRow(actions = ToolbarActions)
}
Pattern: lambda inside LazyListScope.items

See workflow step 3. The short version: items { } is not @Composable, strong skipping does not reach inside it, hoist a stable callback or use a method reference.

Pattern: @DontMemoize for intentionally-fresh lambdas
kotlin
// WRONG — auto-remembered lambda captures `counter` from the FIRST composition
@Composable
fun LoggingButton(counter: Int) {
    Button(onClick = { Log.d("Btn", "counter = $counter") }) { Text("hit") }
}
// WRONG because: under strong skipping the lambda is auto-remembered, but `counter` is a
// stable Int capture, so the remember key is the int value. This is actually fine here.
// Where it bites is when the developer EXPECTS each invocation to capture fresh state but
// the lambda is being passed across a memoization boundary that hides the capture.
kotlin
// RIGHT — explicit opt-out where freshness is the contract.
// @DontMemoize is @Target(EXPRESSION) — apply on the lambda literal, never on the type.
@Composable
fun TraceContent(latest: Int, body: @Composable (() -> Unit) -> Unit) {
    body(@DontMemoize { sendTelemetry("snapshot=$latest") })
}

@DontMemoize is rarely needed in app code. Reach for it only after measuring; the default behavior is correct for almost all UI.

Pattern: @NonSkippableComposable for side-effect-only composables
kotlin
// RIGHT
@NonSkippableComposable
@Composable
fun FrameTicker(onTick: () -> Unit) {
    SideEffect { onTick() }
}

The annotation says "this composable has work to do every recomposition; do not let the skip guard short-circuit it". Use sparingly — most composables that "must run every time" are actually misplaced state reads; fix the read site first.

Pattern: pair with CI to prevent strong-skipping regressions

Strong skipping makes nearly every composable skippable in the report, which makes the report less useful for spotting regressions by eye. Combine with ../../stability/enforcing-stability-in-ci/SKILL.md so the baseline diff catches a composable that flips from skippable to not.

Mandatory rules

  • MUST verify the Kotlin / Compose compiler plugin version before claiming strong skipping is active. Print ./gradlew :app:dependencies and confirm Kotlin 2.0.20+ (default ON). On older Kotlin, confirm the legacy enableStrongSkippingMode = true flag in composeCompiler { }. If the project explicitly disables Strong Skipping via featureFlags.add(ComposeFeatureFlag.StrongSkipping.disabled()), treat the rest of this skill as not applicable.
  • MUST NOT declare a composable "skippable now thanks to strong skipping" without checking the actual *-composables.txt report. Annotations like @NonSkippableComposable and lambdas inside LazyListScope.items { } remain footguns the report makes visible.
  • MUST prefer @Immutable / @Stable over relying on reference equality for unstable types passed in hot paths. === is a poor substitute for structural equals when the producer of the value (copy(), map { }, builder DSL) does not preserve identity.
  • MUST NOT use @DontMemoize or @NonSkippableComposable without a one-line code comment explaining why. These are advanced opt-outs; the next reader will assume they are mistakes if the rationale is not co-located.
  • MUST NOT treat strong skipping as a substitute for hoisting unstable literals. A listOf(...) allocated in a composable param fails === regardless of strong skipping. Hoist into remember { ... } or a top-level persistentListOf(...).
  • PREFERRED: combine this skill with ../../stability/enforcing-stability-in-ci/SKILL.md so a composable regressing from skippable to not skippable (e.g. someone adds @NonSkippableComposable without justification) fails CI.
  • PREFERRED: when a developer asks "is my lambda allocated per recompose?", confirm the call site is inside a @Composable function before answering yes/no. The answer flips entirely at the @Composable boundary.

Skippability is a diagnostic, not a KPI: under strong skipping every composable is "skippable" in the report, but only the ones whose params actually compare equal will skip at runtime. The interesting question is no longer "is it skippable?" but "do its params compare equal across the recomposition the developer cares about?".

Verification

  • Confirmed Kotlin / Compose compiler version is 2.0.20+ (default ON) and that no featureFlags.add(ComposeFeatureFlag.StrongSkipping.disabled()) opt-out is in effect — or, on older Kotlin, that the legacy enableStrongSkippingMode = true flag is set.
  • *-composables.txt shows restartable skippable on previously-unstable-param composables.
  • Audited the suspect call site for unstable literal captures (listOf, mapOf, ad-hoc lambdas in non-@Composable scopes).
  • Any @DontMemoize / @NonSkippableComposable / @NonRestartableComposable / @ReadOnlyComposable in the changed code has a co-located comment explaining why.
  • Runtime confirmed via @TraceRecomposition (see ../../measurement/tracing-recompositions-at-runtime/SKILL.md) that the composable skips when its inputs are equal.
  • Stability baseline (see ../../stability/enforcing-stability-in-ci/SKILL.md) covers the changed module so a future regression in skip behavior fails CI.

References

For diagnosing why a composable is unstable in the first place, see ../../stability/diagnosing-compose-stability/SKILL.md. For instrumenting a specific composable to see if it actually skips at runtime, see ../debugging-recompositions/SKILL.md and ../../measurement/tracing-recompositions-at-runtime/SKILL.md. For preventing a strong-skipping regression in CI, see ../../stability/enforcing-stability-in-ci/SKILL.md.

© rosuH, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file (references) in .agents/skills/using-strong-skipping-correctly of rosuH/EasyWatermark.

  • SKILL.md
  • references/escape-hatches.md

Open the folder on GitHubat commit 61223db

Used in 1 other repository

We found 1 copy of this SKILL.md (exact, near-identical or edited) in other folders, from 1 other GitHub owner. This page covers the copy in rosuH/EasyWatermark, which our catalogue first saw on October 7, 2026.

Compare with similar skills

Using Strong Skipping Correctly next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Using Strong Skipping Correctly compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Using Strong Skipping Correctly this skillrosuH/EasyWatermark1.9k1 repos~5.5kAutomated safety check: PassApache-2.0
Compose Multiplatform Patternsmonta-app/ocpp-emulator1805 repos~2kAutomated safety check: PassApache-2.0
Android Developmentdpconde/claude-android-skill337—~1.7kAutomated safety check: PassMIT
Claude Android NinjaDrjacky/claude-android-ninja124—~5.2kAutomated safety check: PassApache-2.0
Jetpack Composedarriousliu/PiPixiv263—~1.5kAutomated safety check: PassApache-2.0
Footgun Scanmaxrave-dev/kotlin-footguns1.1k—~518Automated safety check: PassGPL-3.0

Similar skills

  • Compose Multiplatform Patterns

    monta-app/ocpp-emulator

    Compose Multiplatform and Jetpack Compose patterns for KMP projects — state management, navigation, theming, performance, and platform-specific UI.

    180 GitHub starsUsed in 5 repos~2k tokens
    MobileAuto-check passed
  • Android Development

    dpconde/claude-android-skill

    Create production-quality Android applications following Google's official architecture guidance and NowInAndroid best practices.

    337 GitHub stars~1.7k tokensUpdated 10 mo ago
    MobileAuto-check passed
  • Claude Android Ninja

    Drjacky/claude-android-ninja

    Build and migrate Android apps with Kotlin, Jetpack Compose, MVVM, Hilt, Room 3 (KSP, SQLiteDriver, Flow/suspend DAOs), Navigation3, and multi-module Gradle.

    124 GitHub stars~5.2k tokensUpdated 10 days ago
    MobileAuto-check passed
  • Jetpack Compose

    darriousliu/PiPixiv

    Jetpack Compose expert skill for Android UI development. An agent skill from darriousliu/PiPixiv.

    263 GitHub stars~1.5k tokensUpdated yesterday
    MobileAuto-check passed
  • Footgun Scan

    maxrave-dev/kotlin-footguns

    Scan a Kotlin or Compose Multiplatform diff for known footgun shapes and open the matching trap to confirm each hit.

    1.1k GitHub stars~518 tokensUpdated 14 days ago
    MobileAuto-check passed
  • Coding Style

    sk2andy/candy-browser

    Apply Candy Browser's project-specific Kotlin, Jetpack Compose, Android/WebView, testing, and generator conventions.

    508 GitHub stars~548 tokensUpdated yesterday
    MobileAuto-check passed

More from rosuH/EasyWatermark

All 28 skills in this repo
  • Deferring State Reads

    rosuH/EasyWatermark

    A skill your agent uses to push frequently-changing Jetpack Compose state reads (scroll position, animation values, drag offsets) out of the Composition phase and down into Layout or Draw using…

    1.9k GitHub starsUsed in 1 repo~3.8k tokens
    Auto-check passed
  • Diagnosing Compose Stability

    rosuH/EasyWatermark

    A skill your agent uses to diagnose Jetpack Compose stability problems by enabling and reading the Compose Compiler Reports (classes.txt, composables.txt, composables.csv, module.json).

    1.9k GitHub starsUsed in 1 repo~3.3k tokens
    Auto-check passed
  • Generating Baseline Profiles

    rosuH/EasyWatermark

    A skill your agent uses to generate and measure Jetpack Compose Baseline Profiles end-to-end with the AGP 8.2+ Baseline Profile Generator module and the Macrobenchmark harness.

    1.9k GitHub starsUsed in 1 repo~5k tokens
    Auto-check passed
  • Migrating To Modifier Node

    rosuH/EasyWatermark

    A skill your agent uses to author new custom Jetpack Compose modifiers and migrate legacy ones from Modifier.composed { } to Modifier.Node + ModifierNodeElement<T.

    1.9k GitHub starsUsed in 1 repo~5k tokens
    Auto-check passed
  • ML Kit Genai Prompt API

    rosuH/EasyWatermark

    Analyzes Android codebases to implement ML Kit GenAI Prompt API.

    1.9k GitHub starsUsed in 1 repo~1k tokens
    Auto-check passed
  • Stabilizing Compose Types

    rosuH/EasyWatermark

    A skill your agent uses to fix unstable Jetpack Compose types once a stability diagnosis has identified them.

    1.9k GitHub starsUsed in 1 repo~4.4k tokens
    Auto-check passed

Categories

Questions about Using Strong Skipping Correctly

What does Using Strong Skipping Correctly do?

A skill your agent uses 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…. Using Strong Skipping Correctly is an agent skill from rosuH/EasyWatermark.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.

When should I use Using Strong Skipping Correctly?

Using Strong Skipping Correctly fits situations like: reason about Jetpack Composes Strong Skipping Mode — the default since Kotlin 2.0.20 — including what it changes about skippability; it does and does not auto-remember lambdas; which escape hatches (@DontMemoize; @NonSkippableComposable.

How do I install Using Strong Skipping Correctly in Claude Code?

Run `npx skills add rosuH/EasyWatermark --skill using-strong-skipping-correctly -a claude-code`. Or copy the skill folder (.agents/skills/using-strong-skipping-correctly in rosuH/EasyWatermark) into .claude/skills/using-strong-skipping-correctly in your project. Claude Code loads it when a task matches its description.

How do I install Using Strong Skipping Correctly in Codex?

Run `npx skills add rosuH/EasyWatermark --skill using-strong-skipping-correctly -a codex`. Or copy the skill folder (.agents/skills/using-strong-skipping-correctly in rosuH/EasyWatermark) into .agents/skills/using-strong-skipping-correctly in your project. Codex loads it when a task matches its description.

Can I use Using Strong Skipping Correctly in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add rosuH/EasyWatermark --skill using-strong-skipping-correctly -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/using-strong-skipping-correctly, .gemini/skills/using-strong-skipping-correctly, .github/skills/using-strong-skipping-correctly and .opencode/skills/using-strong-skipping-correctly in your project.

What does Using Strong Skipping Correctly need to run?

SKILL.md names no scripts, command-line tools or credentials: Using Strong Skipping Correctly is instructions for the agent only.

Does Using Strong Skipping Correctly access the network?

SKILL.md names 4 domains. As links in the text: developer.android.com, medium.com, chrisbanes.me and github.com. This is read from the text; nothing was executed.

Is Using Strong Skipping Correctly safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Using Strong Skipping Correctly use?

Using Strong Skipping Correctly is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Using Strong Skipping Correctly use?

About 5.5k tokens (SKILL.md is roughly 22k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 3.1k tokens, read only when the agent opens those files.

What are the alternatives to Using Strong Skipping Correctly?

Skills that share tags, products or a category with Using Strong Skipping Correctly: Compose Multiplatform Patterns (monta-app/ocpp-emulator, 180 stars), Android Development (dpconde/claude-android-skill, 337 stars), Claude Android Ninja (Drjacky/claude-android-ninja, 124 stars) and Jetpack Compose (darriousliu/PiPixiv, 263 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Using Strong Skipping Correctly?

rosuH (a GitHub user) maintains it in rosuH/EasyWatermark, which has 1,895 GitHub stars. The repository holds 28 skills in this directory. The repository was last updated on October 6, 2026.

Source: rosuH/EasyWatermark on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.