Agent skill · Audited from source
Choosing Derivedstateof
skill · skydoves/compose-performance-skillsApache-2.0 licenceAudited 16 Oct 2026 · source 87cfb886f00d
Is it safe? Yes — SAFE, grade B (89/100). We read this skill's source at commit 87cfb886f00d and found no filesystem, network or shell access and no hard-coded secrets. What it does: Use this skill to decide when Jetpack Compose derivedStateOf is the right tool and when it is pure overhead. Covers the "input frequency must exceed output frequency" rule, the mandatory remember { derivedStateOf { } }…
Cite
Cite this page
ModelsAtlas. “Choosing Derivedstateof (skydoves/compose-performance-skills)”. Retrieved 16 Oct 2026. https://modelsatlas.com/skills/skydoves/choosing-derivedstateof
Trust audit
Audit 0.4.1 · source read 16 Oct 2026
SAFE means nothing in the source contradicts what the skill says it does. Grade B is shared by 16,667 of 17,602 audited skills.
What the source does
- FilesystemNone observedNo reads or writes in the source
- NetworkNone observedNo outbound calls in the source
- ShellNone observedNo commands run in the source
- DependenciesPinnedNothing floats
- SecretsNone foundNo keys in source
Five audit layers
| Layer | What we check | Result | Findings |
|---|---|---|---|
L0 Provenance | Repo owner, licence, archive status, activity | PASS | 0 |
L1 Static source | Secrets, path traversal, supply chain, hidden code | NA | 0 |
L2 Instructions | Prompt injection, authority framing, hidden directives | PASS | 0 |
L3 Inventory | The files and declarations match the source | PASS | 0 |
L4 Sandbox | Run in isolation and watch behaviour | SKIPPED why | 0 |
Gates applied: no behavioural pass.
Findings (0)
No findings at any severity. We re-audit when the source changes.
Audit 0.4.1 · source sha 87cfb886f00d · 16 Oct 2026Report an issue or request a re-scan
Provenance
Who published it, and what the verdict is pinned to
- Publisherskydoves GitHub userOwner of the repository this skill is read from
- Source folderskydoves/compose-performance-skills/recomposition/choosing-derivedstateofThe exact folder we audited
- LicenceApache-2.0As the repository states it
- Commit pinned for this verdict87cfb886f00dA new audit runs when the source changes
- Repository statusNot archivedLast push 121 days ago
- Sandboxed runNot runSkills are read, not executed; layer L4 is skipped
What it tells the agent
Full source on GitHub ↗Its description: Use this skill to decide when Jetpack Compose derivedStateOf is the right tool and when it is pure overhead. Covers the "input frequency must exceed output frequency" rule, the mandatory remember { derivedStateOf { } }…
---
name: choosing-derivedstateof
description: Use this skill to decide when Jetpack Compose derivedStateOf is the right tool and when it is pure overhead. Covers the "input frequency must exceed output frequency" rule, the mandatory remember { derivedStateOf { } } wrapper, the canonical pitfall of capturing non-state variables by initial value (and the remember(key) fix), and the snapshotFlow alternative for fire-and-forget side effects on derived values. Use when the developer mentions derivedStateOf, scroll-position-driven booleans, threshold checks, firstVisibleItemIndex, "show FAB on scroll", recomposition counts that don't drop after wrapping a value, or asks whether a computed string concatenation should use derivedStateOf.
license: Apache-2.0. See LICENSE for complete terms.
metadata:
author: Jaewoong Eum (skydoves)
keywords:
- jetpack-compose
- performance
- recomposition
- derivedstateof
- snapshotflow
- lazylist
- scroll-perf
- state
---
# Choosing derivedStateOf — Filter Hot Inputs into Cold Outputs
`derivedStateOf` produces a `State` whose readers only invalidate when the **derived result** changes, even if the input states change far more often. Use it when input frequency exceeds output frequency. Use it for any other shape and it is pure overhead — an extra snapshot subscription with no filtering benefit. This skill teaches Claude when to reach for it, when to refuse, and how to avoid the canonical capture-by-initial-value pitfall.
## When to use this skill
- The developer asks whether a value should be wrapped in `derivedStateOf`.
- A scroll position drives a boolean (`firstVisibleItemIndex == 0`, `scrollState.value > threshold`, "show FAB on scroll").
- A high-frequency input (drag delta, animation progress) feeds a low-frequency output (boolean threshold, bucketed integer).
- A `derivedStateOf` exists in the code but recomposition counts didn't drop, or the value never updates after the first composition (the capture-by-initial-value bug).
- The developer wants a one-shot side effect (analytics, logging, snackbar) when a derived value flips.
## When NOT to use this skill
- The state read is in the wrong phase (e.g. `Modifier.alpha(state.value)`). Fix that with `../deferring-state-reads/SKILL.md` first — `derivedStateOf` does not address phase issues.
- Diagnosing whether a parameter is unstable. That is `../../stability/diagnosing-compose-stability/SKILL.md`.
- Input frequency equals output frequency (e.g. `"$first $last"` from two name states). `derivedStateOf` is pure overhead in that case — use a direct read or a plain `remember`.
## Prerequisites
- Familiarity with state-read-driven recomposition: a snapshot read inside a restartable composable subscribes that composable's restart scope to the state.
- Compose runtime ≥ 1.0 (the API is foundational; behavior described here is stable).
- Ability to confirm recomposition counts via Layout Inspector or `@TraceRecomposition` from skydoves/compose-stability-analyzer.
## Workflow
- [ ] **1. Identify the input state(s) and the value the UI actually consumes.** Write down both update frequencies. Example: `listState.firstVisibleItemIndex` (changes every list item scrolled past) → `Boolean` (changes once when the user crosses index 0).
- [ ] **2. Compare frequencies.** Apply the rule:
- Input updates **much more often** than output → `derivedStateOf` is the right tool.
- Input and output update at roughly the same rate → `derivedStateOf` adds an extra snapshot subscription for nothing. Use a direct read or a plain `remember(input1, input2)`.
- [ ] **3. Wrap the derivation in `remember { derivedStateOf { ... } }`.** A bare `derivedStateOf { }` would be re-created on every composition, defeating the cache. The `remember` is mandatory.
- [ ] **4. If the lambda captures non-state variables (function parameters, locals, props), pass them as `remember` keys.** A captured non-state variable is read once at first composition and frozen forever — the derivation will silently use the stale value. The fix is `remember(threshold) { derivedStateOf { ... > threshold } }`.
- [ ] **5. For one-shot side effects on a derived value (logging, analytics, snackbar), prefer `snapshotFlow { ... }.collect { ... }` inside `LaunchedEffect`.** That avoids subscribing the composable's restart scope to the derived state; the side effect runs in a coroutine, off the composition path.
- [ ] **6. Verify in Layout Inspector / `@TraceRecomposition`.** The consuming composable's recomposition count MUST only increment when the derived result changes — not on every input tick. If it still climbs per input tick, either (a) the `derivedStateOf` is missing, (b) the `remember` is missing, or (c) something else (a sibling state read, a wrong-phase modifier) is invalidating the same scope.
## Patterns
### Pattern: scroll-to-top FAB — input >> output
```kotlin
// WRONG
val showFab = listState.firstVisibleItemIndex > 0
// WRONG because: this reads firstVisibleItemIndex on every recomposition; the consuming composable invalidates per scrolled item, not just when the boolean flips.
```
```kotlin
// RIGHT
val showFab by remember {
derivedStateOf { listState.firstVisibleItemIndex > 0 }
}
```
`firstVisibleItemIndex` updates on every list item scrolled past; `showFab` only flips when the user crosses index 0. The `remember` keeps the derived state alive across compositions; the `derivedStateOf` filters out every input change that does not flip the boolean.
### Pattern: pure overhead — input ≈ output
```kotlin
// WRONG
val first by remember { mutableStateOf("Ada") }
val last by remember { mutableStateOf("Lovelace") }
val fullName by remember { derivedStateOf { "$first $last" } }
// WRONG because: first and last change at the same rate as fullName; derivedStateOf adds a snapshot subscription with zero filtering benefit.
```
```kotlin
// RIGHT — direct read, no derivedStateOf needed
val first by remember { mutableStateOf("Excerpt, first 6,000 characters of SKILL.md, verbatim from the audited commit. It is text from someone else’s repository, quoted so you can judge it before your agent reads it.
Install
Pinned to the audited commit 87cfb88
git clone https://github.com/skydoves/compose-performance-skills git -C compose-performance-skills checkout 87cfb886f00d
The author documents no install command, so this uses the repository directly. Our verdict covers commit 87cfb886f00d only.
Works in
The author has not said which agents this skill supports, and we have not tested it in any.
Audit history
Every audit, every source change
- ✓SAFE B 89 / 100
first audit · source
87cfb886f00d
Similar skills
All coding & review skills →skydoves/compose-performance-skills
Use this skill to run an end-to-end Jetpack Compose performance audit when the symptom is broad ("the app feels sluggish", "scroll is rough everywhere", "we're starting a perf sprint", "what should we fix first?").…
skydoves/compose-performance-skills
Use this skill when a Compose tree uses SubcomposeLayout, BoxWithConstraints, or Scaffold and the developer reports extra measure passes, slow first frame, or layout passes running content composition repeatedly. Covers…
skydoves/compose-performance-skills
Use this skill to migrate Compose UI from `collectAsState()` to `collectAsStateWithLifecycle()`, hoist `Flow<T>` parameters out of composables, and apply `.conflate()` / `.distinctUntilChanged()` / `snapshotFlow` so…
skydoves/compose-performance-skills
Use this skill to tune Jetpack Compose lazy-layout prefetch with LazyLayoutCacheWindow (Compose Foundation 1.9+, @ExperimentalFoundationApi) and pausable composition in prefetch (Compose Foundation 1.10+, default on).…
skydoves/compose-performance-skills
Use this skill to configure R8 correctly for a Jetpack Compose application — full mode by default, `proguard-android-optimize.txt`, resource shrinking on, and minimal keep rules because Compose ships consumer ProGuard…
skydoves/compose-performance-skills
Use this skill to find which Jetpack Compose composables are recomposing and why, using Android Studio Layout Inspector recomposition counts and skip counts, the per-parameter Argument Change Reasons (Changed /…
Questions about Choosing Derivedstateof
What does the Choosing Derivedstateof skill do?
Is Choosing Derivedstateof safe to install?
What can Choosing Derivedstateof access on my machine?
How current is this page?
Sources
- github.com/skydoves/compose-performance-skills/tree/main/recompo — the audited source at commit 87cfb886f00d and every finding aboveObserved · 16 Oct 2026
Spotted something wrong? Report a correction · Methodology
Keep going in your AI
Opens with this page as the source. We add nothing else to the prompt.
- What does the Choosing Derivedstateof skill do?
- Is Choosing Derivedstateof safe to install?
- What can Choosing Derivedstateof access on my machine?