| name | using-stability-analyzer-ide-plugin |
| description | Use this skill to install and operate the `skydoves/compose-stability-analyzer` IntelliJ / Android Studio plugin so the developer sees Compose stability feedback live in the editor instead of waiting for a Gradle build. Covers installing the plugin from disk, configuring the `Settings → Tools → Compose Stability Analyzer` panel, reading the four gutter colors (green stable, red unstable, yellow runtime, gray no-params), the per-parameter hover documentation, the inline parameter hint badges, and the `UnstableComposable` weak-warning inspection with its `@Suppress("NonSkippableComposable")` and `@Suppress("ParamsComparedByRef")` quick fixes. Use when the user mentions gutter icons, inline hints, the stability inspection, the IDEA plugin, real-time stability feedback while editing, or asks why a composable is flagged as non-skippable in the editor. |
| license | Apache-2.0. See LICENSE for complete terms. |
| metadata | {"author":"Jaewoong Eum (skydoves)","keywords":["jetpack-compose","performance","stability","intellij-plugin","android-studio","gutter-icons","inline-hints","inspection","compose-stability-analyzer","editor-feedback"]} |
Using the Stability Analyzer IDE Plugin — live in-editor stability feedback
The Compose Compiler reports tell the developer about stability after a build completes. The skydoves/compose-stability-analyzer IntelliJ plugin tells them while they edit. Gutter icons mark every @Composable with a color, hover docs render the per-parameter table with reasons, inline hints render colored badges next to each parameter type, and the UnstableComposable weak-warning inspection surfaces actionable problems with quick fixes.
The plugin uses the Kotlin K2 Analysis API to evaluate the same stability rules that drive ../understanding-stability-inference/SKILL.md, so editor feedback agrees with what ../diagnosing-compose-stability/SKILL.md would later show in the compiler reports. This shortens the loop from "ship → build → read reports" to "type → see the gutter".
When to use this skill
- The developer wants real-time stability feedback while editing a Composable file.
- A reviewer is reading a PR locally and wants the inline signal next to each composable.
- A new joiner wants to see at a glance which composables in the file are non-skippable.
- The user asks why the editor flagged a function with a weak warning called
UnstableComposable.
- The user mentions gutter icons, inline hints, the stability inspection, the IDEA plugin, the K2 Analysis API for Compose, or the
Compose Stability Analyzer tool window.
When NOT to use this skill
- CI gating that fails the build on stability regressions. Use
../enforcing-stability-in-ci/SKILL.md.
- Build-time Compose Compiler reports analysis. Use
../diagnosing-compose-stability/SKILL.md.
- Active runtime tracing or visual cascade investigation through the plugin's tool window. Use
../visualizing-recomposition-cascades/SKILL.md.
- Conceptual questions about how the compiler classifies a type. Use
../understanding-stability-inference/SKILL.md.
Prerequisites
- Android Studio 2024.2+ or IntelliJ IDEA 2024.2+ (build range 242 through 261, covering 2024.2 through the 2026.1 EAP).
- Kotlin 2.3.0 in the IDE plugin runtime, required by the K2 Analysis API the plugin relies on.
- The Compose Compiler Gradle plugin already wired in the project (
org.jetbrains.kotlin.plugin.compose). The analyzer evaluates stability against the same compiler model.
- The plugin is currently installed from disk during development; the JetBrains Marketplace listing is pending.
Workflow
1. Build the plugin from source
Clone skydoves/compose-stability-analyzer and build the IDEA module.
git clone https://github.com/skydoves/compose-stability-analyzer
cd compose-stability-analyzer
./gradlew :compose-stability-analyzer-idea:buildPlugin
The packaged plugin lands at compose-stability-analyzer-idea/build/distributions/*.zip.
2. Install from disk
In the IDE, open Settings → Plugins → ⚙ → Install Plugin from Disk… and pick the ZIP produced in step 1. Restart the IDE when prompted. DO NOT look for the plugin in the JetBrains Marketplace yet; the listing is under review at the time of writing.
3. Confirm the settings panel
Open Settings → Tools → Compose Stability Analyzer. Verify isStabilityCheckEnabled is on. The full set of toggles, all read from StabilitySettingsState, is:
| Key | Default | Effect |
|---|
isStabilityCheckEnabled | true | Master switch for all editor features. |
isStrongSkippingEnabled | true | Match Compose Compiler 2.0.20+ runtime: classify with strong skipping on. |
showGutterIcons | true | Render the colored icon in the gutter beside each @Composable. |
showGutterIconsOnlyForUnskippable | false | Hide green/gray icons; only show problems. Use on dense files. |
showGutterIconsInTests | false | Render gutter icons inside test source roots too. |
showWarnings | true | Enable the UnstableComposable inspection. |
showInlineHints | true | Render colored parameter-type badges inline. |
showOnlyUnstableHints | false | Suppress inline badges for stable parameters. |
stableGutterColorRGB | #5FB865 (95, 184, 101) | Gutter / hint color for stable composables. |
unstableGutterColorRGB | #E8684A (232, 104, 74) | Gutter / hint color for unstable composables. |
runtimeGutterColorRGB | #F0C674 (240, 198, 116) | Gutter / hint color for runtime-stability composables. |
stableHintColorRGB / unstableHintColorRGB / runtimeHintColorRGB | per defaults above | Inline hint color overrides. |
ignoredTypePatterns | "" | Newline- or comma-separated glob list of types to treat as stable. |
stabilityConfigurationPath | "" | Optional path to the same stability_config.conf the compiler reads. |
isHeatmapEnabled | true | Allow the live recomposition heatmap (see ../visualizing-recomposition-cascades/SKILL.md). |
Point stabilityConfigurationPath at the project's stability_config.conf so the in-editor classification matches the compiler's classification.
4. Read the gutter colors
Open any Kotlin file containing @Composable functions. Confirm a colored icon appears beside each. The four colors and their meanings:
| Color | Hex | Meaning |
|---|
| Green | #5FB865 | Skippable; every parameter stable. |
| Red | #E8684A | At least one unstable parameter; not skippable. |
| Yellow | #F0C674 | At least one runtime-stability parameter (resolved across separate compilation units). |
| Gray | #808080 | No parameters (still restartable but trivially skippable). |
A gray gutter is fine; the function has nothing to compare. A green gutter means the analyzer believes Compose will skip recomposition when arguments are equal. A red or yellow gutter is a diagnostic: the function will recompose more than necessary when the parent recomposes.
5. Hover for the parameter table
Hover any composable name. The popup, served by StabilityDocumentationProvider, shows the skippability badge, a per-parameter table with the stability classification per parameter, and the suggested fix when the analyzer can name one (e.g. "wrap List<Item> in ImmutableList"). Use this for triage before opening the full compiler reports.
6. Tune inline hints for dense files
StabilityInlayHintsProvider renders a colored badge next to each parameter type in the function signature. On a screen with many composables this can become noisy. In Settings → Tools → Compose Stability Analyzer enable showOnlyUnstableHints so badges disappear for stable parameters and only the actionable ones remain. For an even quieter file, enable showGutterIconsOnlyForUnskippable so the gutter only shows red/yellow.
7. Read the UnstableComposable inspection
StabilityInspection (short name UnstableComposable, group Compose, severity weak warning) flags non-skippable composables with at least one unstable parameter. It runs on the fly and on Code → Inspect Code…. The inspection surfaces in two ways:
- A weak-warning underline in the editor.
- A finding in the Inspection Results tool window grouped under
Compose / Unstable Composable.
It is intentionally a weak warning: skippability is a diagnostic, not a build-blocking error. It will not turn the file red, will not block a commit, and will not fail CI on its own. Treat it as a backlog signal.
8. Apply quick fixes only when justified
The inspection ships two suppression intentions, surfaced via Alt+Enter on the underlined composable:
@Suppress("NonSkippableComposable") — applied by AddSuppressAnnotationFix / AddSuppressIntentionAction. Silences the inspection on a function the developer has actively decided is acceptable (e.g. a debug overlay never on a hot path).
@Suppress("ParamsComparedByRef") — same fix path, narrower scope: silences the warning when the parameter is intentionally compared by reference.
Apply suppressions on the specific function only. DO NOT push them to file scope.
9. Annotate hot paths with @TraceRecomposition
AddTraceRecompositionIntention is available via Alt+Enter on any @Composable. It inserts the @TraceRecomposition annotation, which is the runtime instrumentation entry point used by the live heatmap and by ../../measurement/tracing-recompositions-at-runtime/SKILL.md. Use it on suspected hot composables once the gutter has identified them.
Patterns
Pattern: red gutter inside a hot path is actionable, even when the build is green
// WRONG
PriceTicker has a red gutter icon.
Build is green, the team ships, jank reports come in two days later.
// WRONG because: the inspection is a weak warning by design and does not block the build.
// The gutter is the only signal until the developer opens the compiler reports.
// Treat red gutters on hot-path composables as actionable; confirm with
// `../diagnosing-compose-stability/SKILL.md`, then fix via `../stabilizing-compose-types/SKILL.md`.
// RIGHT
PriceTicker has a red gutter icon.
Hover -> "price: Price unstable (var price)".
Open the compiler reports for confirmation.
Stabilize `Price` (val + immutable fields) per `../stabilizing-compose-types/SKILL.md`.
Gutter turns green; confirm with the live heatmap per `../visualizing-recomposition-cascades/SKILL.md`.
Pattern: suppress on the function, never on the file
@file:Suppress("UnstableComposable")
package com.example.feature.cart
// WRONG because: file-level suppression hides every future regression in that file.
// New unstable composables added to the file will never surface in the inspection.
@Suppress("NonSkippableComposable")
@Composable
fun DebugOverlay(state: MutableState<DebugInfo>) {
}
Pattern: do not chase 100% green gutters
// WRONG
"All composables in :feature-search must show green gutters before merge."
// WRONG because: skippability is a diagnostic, not a KPI. Some composables legitimately
// take unstable parameters (interop with Java POJOs, third-party data classes the team
// does not own). The goal is "no regression in hot-path composables", not "all green".
// Use `../enforcing-stability-in-ci/SKILL.md` to gate against regressions, not absolutes.
// RIGHT
Hot-path composables (list rows, scroll items, animation tickers) are green or yellow.
Cold-path composables (settings screens, debug tools) may be red and that is acceptable.
Pattern: silence noise via settings, not via inspection-disable
// WRONG
Settings -> Editor -> Inspections -> Compose -> Unstable Composable -> off
// WRONG because: turning the inspection off globally silences real regressions
// across the whole codebase. The next unstable parameter slipping into a hot
// composable will not surface anywhere in the editor.
// RIGHT
Settings -> Tools -> Compose Stability Analyzer:
showGutterIconsOnlyForUnskippable = true
showOnlyUnstableHints = true
The inspection stays on; only the visual noise is reduced.
Pattern: align the in-editor classifier with the compiler
isStrongSkippingEnabled = true
stabilityConfigurationPath = "<repo-root>/stability_config.conf"
The compiler runs with strong skipping on by default in Kotlin 2.0.20+ and consults the same stability_config.conf (see ../stabilizing-compose-types/SKILL.md). Matching both settings means the gutter color the developer sees agrees with what the compiler emits in ../diagnosing-compose-stability/SKILL.md.
Mandatory rules
- MUST treat a red or yellow gutter on any composable inside a hot path as actionable. Confirm with the compiler reports per
../diagnosing-compose-stability/SKILL.md, then fix via ../stabilizing-compose-types/SKILL.md.
- MUST point
stabilityConfigurationPath at the same stability_config.conf the Compose compiler reads, so the editor and the compiler agree on classifications.
- MUST NOT apply file-level
@file:Suppress("UnstableComposable"). Suppress on the specific function with @Suppress("NonSkippableComposable") or @Suppress("ParamsComparedByRef"), and document why in a comment.
- MUST NOT disable the inspection globally to silence noise. Tune
showGutterIconsOnlyForUnskippable = true and showOnlyUnstableHints = true in Settings → Tools → Compose Stability Analyzer first.
- MUST NOT chase 100% green gutters. Skippability is a diagnostic, not a KPI. Stability config is a contract, not a magic spell — marking a mutable type stable means the compiler trusts the developer; break the contract and recompositions silently go missing.
- PREFERRED: keep
isStrongSkippingEnabled = true so the analyzer's classification matches the compiler's actual runtime behavior on Kotlin 2.0.20+.
- PREFERRED: apply
@TraceRecomposition via the Add @TraceRecomposition intention on suspected hot composables, then follow ../../measurement/tracing-recompositions-at-runtime/SKILL.md to wire the runtime side.
- PREFERRED: install from disk during development; the JetBrains Marketplace listing is pending and MUST NOT be assumed available yet.
Verification
References
For CI-side gating that turns red gutters into a build failure, see ../enforcing-stability-in-ci/SKILL.md. For the build-time Compose Compiler reports the gutter colors agree with, see ../diagnosing-compose-stability/SKILL.md. For the upstream type fixes that turn red gutters green, see ../stabilizing-compose-types/SKILL.md. For the active investigation tools (cascade visualizer, live heatmap) inside the same plugin, see ../visualizing-recomposition-cascades/SKILL.md. For the runtime instrumentation that the Add @TraceRecomposition intention sets up, see ../../measurement/tracing-recompositions-at-runtime/SKILL.md.