Use this skill to diagnose Jetpack Compose stability problems by enabling and reading the Compose Compiler Reports (classes.txt, composables.txt, composables.csv, module.json). Covers the Gradle DSL, the release-only build requirement, and how to interpret per-class and per-composable stability annotations including stable, unstable, runtime, restartable, skippable, readonly, @static, and @dynamic markers. Use when the developer asks "why does this recompose", reports jank, dropped frames, slow scroll, high recomposition count, suspects an unstable parameter, mentions Compose Compiler Reports, classes.txt, composables.txt, module.json, or wants to know which composables are non-skippable. The fix lives in a sibling skill — this one only diagnoses.
npx skills add https://github.com/skydoves/compose-performance-skills --skill diagnosing-compose-stability
Compose skips recomposition by comparing parameters. When a parameter is unstable, skipping is disabled — this skill tells Claude how to find out which parameters are unstable and why. The output is a prioritized list of unstable types and non-skippable composables; the fix lives in ../stabilizing-compose-types/SKILL.md.
@TraceRecomposition log shows recomposition counts that exceed the number of meaningful state changes.classes.txt, composables.txt, composables.csv, module.json, or "non-skippable".List<Foo>, LocalDateTime, or a domain type is stable.../stabilizing-compose-types/SKILL.md.Modifier.alpha(state.value)); use ../../recomposition/deferring-state-reads/SKILL.md.derivedStateOf misuse; use ../../recomposition/choosing-derivedstateof/SKILL.md.../enforcing-stability-in-ci/SKILL.md.id("org.jetbrains.kotlin.plugin.compose"). The pre-2.0 kotlinCompilerExtensionVersion flow is obsolete.org.jetbrains.kotlin.plugin.compose Gradle plugin (Kotlin 2.0+). The composeCompiler { … } extension is owned by that plugin; AGP version is incidental.build.gradle.kts. Scope to release only — debug builds emit misleading data.// app/build.gradle.kts (or any compose module)
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose")
}
composeCompiler {
// Only emit reports for release to avoid Live Literals noise.
val isReleaseBuild = providers.gradleProperty("composeCompilerReports").orNull == "true"
if (isReleaseBuild) {
reportsDestination = layout.buildDirectory.dir("compose_compiler")
metricsDestination = layout.buildDirectory.dir("compose_compiler")
}
}
Or the always-on form:
composeCompiler {
reportsDestination = layout.buildDirectory.dir("compose_compiler")
metricsDestination = layout.buildDirectory.dir("compose_compiler")
// Optional — opt mutable third-party types into stability:
stabilityConfigurationFiles.add(
rootProject.layout.projectDirectory.file("stability_config.conf")
)
}
./gradlew :app:assembleRelease -PcomposeCompilerReports=true
For a library module: ./gradlew :feature-feed:assembleRelease. The release flavor is required — see RIGHT/WRONG below.
<module>/build/compose_compiler/:app/build/compose_compiler/
├── app_release-classes.txt # per-class stability
├── app_release-composables.txt # per-composable signatures
├── app_release-composables.csv # CSV mirror of the above (CI-friendly)
└── app_release-module.json # aggregate counts
If any file is missing, the plugin did not run for that variant — re-check that composeCompiler { reportsDestination = ... } is on the right module and that the build was release.
composables.txt first. This is the highest-signal file. Search for restartable lines that are not followed by skippable. Each one is a recomposition entry point that cannot be skipped. Inside each block, read the per-parameter prefix: stable, unstable, @static, @dynamic. Any unstable parameter blocks skipping. See references/reading-composables-txt.md for the full grammar.classes.txt to learn _why_ a class is unstable. For every type flagged unstable in composables.txt, find its declaration in classes.txt. The line tells you whether a var field, a generic parameter, or an unstable nested type is the cause. The runtime stable class Box { stable val value: T } shape means "this class is stable iff the runtime $stable: Int field of the substituted T says so" — see references/reading-classes-txt.md.module.json for triage numbers. Counts of skippable composables, restartable composables, stable classes, etc. Use this to compare before/after a fix or to decide which module to attack first. DO NOT treat these counts as a target — they exist to spot regressions, not to chase 100 percent.LazyColumn item is critical. Cross-reference with measurement (@TraceRecomposition from skydoves/compose-stability-analyzer, or Macrobenchmark FrameTimingMetric) before fixing — see ../../measurement/tracing-recompositions-at-runtime/SKILL.md.../stabilizing-compose-types/SKILL.md.The compiler reports surface the cause directly inside the function signature. Walk the developer through this real shape.
restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
stable index: Int,
unstable snacks: List<Snack>, // <-- blocks skipping
stable onSnackClick: Function1<Long, Unit>,
)
Diagnosis script:
restartable but NOT prefixed with skippable. Therefore it always recomposes when its parent does.unstable snacks: List<Snack> parameter. kotlin.collections.List is an interface; the compiler cannot prove its implementations are immutable.classes.txt and find Snack. If Snack itself is unstable, fix the data class first; if it is stable then only the List wrapper is the problem.List<Snack> with kotlinx.collections.immutable.ImmutableList<Snack>, or add kotlin.collections.* to stability_config.conf if the developer is comfortable with that contract.runtime meansruntime stable class Box {
stable val value: T
}
This is not unstable. The compiler emits a synthetic $stable: Int field at runtime and queries it during composition. The class is stable iff the substituted T reports stable. DO NOT annotate runtime classes with @Stable to "promote" them — the runtime check is the correct mechanism.
# WRONG
./gradlew :app:assembleDebug
# WRONG because: debug enables Live Literals; constant 0 dp becomes a getter, every literal looks dynamic, and counts in module.json drift versus what ships to users.
# RIGHT
./gradlew :app:assembleRelease -PcomposeCompilerReports=true
// WRONG — reading composables.txt without checking the leading flags
fun MyScreen(...)
// WRONG because: skipping the `restartable`/`skippable` prefix discards the only data point that determines whether unstable params actually cost anything.
// RIGHT — every diagnosis quotes the full prefix and per-param annotations
restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun MyScreen(
stable user: User,
stable onClick: Function0<Unit>,
)
If build/compose_compiler/ is missing or empty after a release build:
org.jetbrains.kotlin.plugin.compose plugin is applied to this module — the extension is per-module../gradlew :app:clean :app:assembleRelease.reportsDestination is set inside a composeCompiler { } block, not the legacy kotlinOptions freeCompilerArgs flow.composables.txt per-parameter annotations (stable/unstable/@static/@dynamic), not just the function name. The flag prefix is the diagnosis.classes.txt to identify the root cause (a var, a generic, an unstable field type, or an interface).@Stable based on a report alone — that decision belongs to the fix skill, which evaluates the contract.composables.csv line counts and call it done. The counts are a regression sentinel; the per-line annotations are the actual diagnosis.../enforcing-stability-in-ci/SKILL.md (skydoves compose-stability-analyzer plugin or the community ComposeGuard plugin) so regressions surface on PR review.module.json per release so future regressions are visible by diff../gradlew :app:assembleRelease (or module-specific) completes successfully with the org.jetbrains.kotlin.plugin.compose plugin applied.<module>_release-classes.txt, <module>_release-composables.txt, <module>_release-composables.csv, <module>_release-module.json.composables.txt, OR a confirmed-zero count from module.json justifying that no fix is needed.classes.txt so the fix skill receives a concrete root cause (a var, a List, a LocalDateTime, etc.).runtime stable class … is not a problem — it is the compiler's correct lazy-stability emission.references/reading-classes-txt.md — full grammar for classes.txt with worked examples (stable / unstable / runtime / generic).references/reading-composables-txt.md — full grammar for composables.txt including restartable, skippable, readonly, scheme, and per-parameter stable / unstable / @static / @dynamic.Creating interactive data visualisations using d3.js. This skill should be used when creating custom charts, graphs, network diagrams, geographic visualisations, or any complex SVG-based data visualisation that requires fine-grained control over visual elements, transitions, or interactions. Use this for bespoke visualisations beyond standard charting libraries, whether in React, Vue, Svelte, vanilla JavaScript, or any other environment.
Comprehensive Python library for astronomy and astrophysics. This skill should be used when working with astronomical data including celestial coordinates, physical units, FITS files, cosmological calculations, time systems, tables, world coordinate systems (WCS), and astronomical data analysis. Use when tasks involve coordinate transformations, unit conversions, FITS file manipulation, cosmological distance calculations, time scale conversions, or astronomical data processing.
Convert laboratory instrument output files (PDF, CSV, Excel, TXT) to Allotrope Simple Model (ASM) JSON format or flattened 2D CSV. Use this skill when scientists need to standardize instrument data for LIMS systems, data lakes, or downstream analysis. Supports auto-detection of instrument types. Outputs include full ASM JSON, flattened CSV for easy import, and exportable Python code for data engineers. Common triggers include converting instrument files, standardizing lab data, preparing data for upload to LIMS/ELN systems, or generating parser code for production pipelines.
Quantum mechanics simulations and analysis using QuTiP (Quantum Toolbox in Python). Use when working with quantum systems including: (1) quantum states (kets, bras, density matrices), (2) quantum operators and gates, (3) time evolution and dynamics (Schrödinger, master equations, Monte Carlo), (4) open quantum systems with dissipation, (5) quantum measurements and entanglement, (6) visualization (Bloch sphere, Wigner functions), (7) steady states and correlation functions, or (8) advanced methods (Floquet theory, HEOM, stochastic solvers). Handles both closed and open quantum systems across various domains including quantum optics, quantum computing, and condensed matter physics.
Retrieve and display GitHub Copilot usage metrics for organizations and enterprises using the GitHub CLI and REST API.
Socratic mentoring for junior developers and AI newcomers. Guides through questions, never answers. Triggers: "help me understand", "explain this code", "I''m stuck", "Im stuck", "I''m confused", "Im confused", "I don''t understand", "I dont understand", "can you teach me", "teach me", "mentor me", "guide me", "what does this error mean", "why doesn''t this work", "why does not this work", "I''m a beginner", "Im a beginner", "I''m learning", "Im learning", "I''m new to this", "Im new to this", "walk me through", "how does this work", "what''s wrong with my code", "what''s wrong", "can you break this down", "ELI5", "step by step", "where do I start", "what am I missing", "newbie here", "junior dev", "first time using", "how do I", "what is", "is this right", "not sure", "need help", "struggling", "show me", "help me debug", "best practice", "too complex", "overwhelmed", "lost", "debug this", "/socratic", "/hint", "/concept", "/pseudocode". Progressive clue systems, teaching techniques, and success metrics.
Core Python library for astronomy and astrophysics workflows that need Astropy APIs, including units/quantities, coordinates, FITS I/O, tables, time systems, WCS, and cosmology. Use when implementing or debugging astronomical data analysis code with Astropy.
High-performance DataFrame library for Python ETL, analytics, and pandas migration. Use for expression-based data manipulation with lazy query optimization, parallel execution, streaming out-of-core processing, Arrow interoperability, and optional GPU execution.
Take skydoves/diagnosing-compose-stability from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.