Catch Jetpack Compose mistakes as you type β 37 best-practice rules from the Compose Rules guidelines, surfaced live in Android Studio & IntelliJ IDEA with inline highlights, gutter icons, and one-click fixes.
The Compose Rules catch the subtle mistakes that hurt
Compose code β missing Modifier parameters, un-remembered state, unstable collections, reused
modifiers, and dozens more. ComposeGuard brings those checks into the editor, so you fix them
while the code is still fresh instead of discovering them in a build log or a code review.
- β‘ Instant β analysis runs as you type; no build, no Gradle task, no CI round-trip.
- π― Accurate β rules are PSI-based and tuned to avoid false positives on valid patterns (overrides, scoped slots, mutually-exclusive branches, run-once effects, β¦).
- π Actionable β most violations come with a quick fix (Alt+Enter) and a detailed explanation of why it matters.
- π Configurable β enable/disable any rule or whole category, or suppress per declaration.
- Features
- Installation
- Quick Start
- Suppressing Rules
- Rule Reference
- Statistics Dashboard
- Configuration
- Requirements & Compatibility
- Contributing
- Credits
- License
- Real-time highlighting β violations appear as colored underlines while you edit.
- Gutter icons β a color-coded dot per
@Composablesummarizes its status at a glance:- π΄ Error Β Β π Warning Β Β βͺ Weak warning Β Β π΅ Info
- Inline hints β compact badges next to function names show rule violations.
- Hover tooltips β every violation explains the problem, the reasoning, and the fix.
- Quick fixes β rename, add a
modifierparameter, wrap inremember, switch to a type-specific state, make a preview private, swap to an immutable collection, and more. - 37 rules across 6 categories β see the full Rule Reference.
- Open Android Studio or IntelliJ IDEA.
- Go to Settings β Plugins β Marketplace.
- Search for ComposeGuard.
- Click Install and restart when prompted.
Or install directly from the JetBrains Marketplace.
Once installed, ComposeGuard automatically analyzes any Kotlin file containing @Composable
functions β no configuration required. Here are a few things it catches:
// π Naming: Unit-returning composables should be PascalCase
@Composable
fun userCard(user: User) { } // β rename to "UserCard"
// π Modifier: public UI composables should expose a Modifier
@Composable
fun ProductCard(product: Product) { // β add `modifier: Modifier = Modifier`
Column { Text(product.name) }
}
// π΄ State: state must be remembered
@Composable
fun Counter() {
val count = mutableStateOf(0) // β wrap in remember { }
}
// π Stricter: prefer stable collections
@Composable
fun ItemList(items: List<Item>) { } // β use ImmutableList<Item>Hover any highlight for the full explanation, or press Alt+Enter to apply a fix.
To intentionally allow a violation, annotate the declaration with @Suppress using the rule id
(the same id shown in the warning, e.g. ModifierRequired). The quick fix can insert this for you:
@Suppress("ModifierRequired")
@Composable
fun SplashLogo() {
Image(painterResource(R.drawable.logo), contentDescription = null)
}
// Multiple rules at once:
@Suppress("ModifierRequired", "ComposableNaming")
@Composable
fun splash() { /* ... */ }Suppression works at the function, property, or class level. To turn rules off project-wide instead, use Configuration.
ComposeGuard ships 37 rules based on the Compose Rules guidelines. Severity legend: π΄ Error Β· π Warning Β· βͺ Weak warning Β· π΅ Info.
| Rule id | Checks | Severity |
|---|---|---|
ComposableNaming |
Unit-returning composables use PascalCase; value-returning use camelCase | π |
CompositionLocalNaming |
CompositionLocal properties are prefixed with Local |
π |
PreviewNaming |
@Preview functions reference Preview in their name |
βͺ |
MultipreviewNaming |
Multipreview annotation classes reference Preview |
βͺ |
ComposableAnnotationNaming |
@ComposableTargetMarker annotations end with Composable |
βͺ |
EventParameterNaming |
Event lambdas use present tense (onClick, not onClicked) |
βͺ |
| Rule id | Checks | Severity |
|---|---|---|
ModifierRequired |
Public, UI-emitting composables expose a Modifier parameter |
π |
ModifierDefaultValue |
modifier parameters default to Modifier |
π |
ModifierNaming |
The main modifier is named modifier; others follow xModifier |
βͺ |
ModifierTopMost |
The modifier is applied to the root-most layout | π |
ModifierReuse |
The same modifier isn't applied to multiple live nodes | π |
ModifierOrder |
Modifier chain order is intentional (e.g. padding before clickable) |
π |
AvoidComposed |
Prefer Modifier.Node over the deprecated composed { } factory |
π |
| Rule id | Checks | Severity |
|---|---|---|
RememberState |
mutableStateOf and friends are wrapped in remember { } |
π΄ |
TypeSpecificState |
Primitives use mutableIntStateOf / mutableFloatStateOf / β¦ |
π |
DerivedStateOfCandidate |
Values computed from state use derivedStateOf |
π |
FrequentRecomposition |
Hot observable sources use lifecycle-aware collection | π |
DeferStateReads |
Fast-changing state reads are deferred to lambda modifiers | π |
HoistState |
State is hoisted to the appropriate level | π΅ |
MutableStateParameter |
Pass value + callback instead of a MutableState parameter |
π |
| Rule id | Checks | Severity |
|---|---|---|
ParameterOrdering |
Order is required β modifier β optional β trailing content |
βͺ |
TrailingLambda |
The content slot is the trailing lambda; event handlers are not | βͺ |
MutableParameter |
Avoid inherently mutable types (MutableList, ArrayList, β¦) as parameters |
π |
ExplicitDependencies |
Make injected ViewModels explicit parameters | βͺ |
ViewModelForwarding |
Don't forward a ViewModel into another composable | π |
| Rule id | Checks | Severity |
|---|---|---|
ContentEmission |
A composable emits content or returns a value, not both | π |
MultipleContentEmitters |
A composable emits a single piece of content | π |
ContentSlotReused |
A content slot isn't invoked more than once on the same pass | π |
EffectKeys |
Changing captured values are passed as effect keys | π |
LambdaParameterInEffect |
Lambda parameters used in effects are wrapped in rememberUpdatedState |
π |
MovableContent |
movableContentOf is remembered |
π΄ |
PreviewVisibility |
@Preview composables are private |
π |
ComponentDefaultsVisibility |
A <Component>Defaults object matches its composable's visibility |
π |
LazyListMissingKey |
Lazy list items provide a stable key |
π |
LazyListContentType |
Heterogeneous lazy lists set a contentType |
π΅ |
| Rule id | Checks | Severity |
|---|---|---|
UnstableCollections |
Prefer ImmutableList / PersistentList over List, Set, Map |
π |
Material2Usage |
Migrate androidx.compose.material (M2) imports to Material 3 |
π΅ |
Suppress any rule with
@Suppress("<RuleId>"), or toggle it in Settings β Tools β ComposeGuard.
ComposeGuard includes a tool window that tracks rule violations across your project.
- Real-time statistics β violation counts update as you code.
- Category breakdown β see violations grouped by rule category.
- Rule-level details β drill into specific rules.
- Project overview β track overall code-quality trends.
Open it from View β Tool Windows β ComposeGuard Statistics.
Configure ComposeGuard at Settings β Tools β ComposeGuard.
- Enable ComposeGuard β master toggle for the whole plugin.
- Display options β toggle gutter icons and inlay hints.
- Rule configuration β enable/disable individual rules or entire categories.
Adding the plugin to a large legacy project? Roll it out gradually instead of facing every warning at once:
- Start with the Stricter category off (
Material2Usage,UnstableCollections). - Enable categories one at a time as you refactor β the category checkbox toggles the whole group.
- Use
@Suppress("<RuleId>")for individual, intentional exceptions.
- IntelliJ IDEA 2024.2+ or Android Studio Ladybug (2024.2)+
- The bundled Kotlin plugin (enabled by default)
| ComposeGuard | Supported IDE builds |
|---|---|
| 1.2.x | 2024.2 β 2026.2 |
Contributions are welcome β issues and pull requests both.
- Fork the repository.
- Create a feature branch:
git checkout -b feature/amazing-feature. - Make your change and add tests (
./gradlew :compose-guard:test). - Commit and push, then open a Pull Request.
Built on the excellent Compose Rules guidelines by Nacho Lopez (mrmans0n).
Designed and developed by 2025 androidpoet (Ranbir Singh)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Made with β€οΈ by androidpoet


