Skip to main content
Compose Hot Reload can be configured using various system properties that control its behavior at build time and runtime. These properties allow you to fine-tune the hot reload experience for your specific needs.

Overview

System properties are set using the -D flag when running your application or as Gradle properties. They control aspects like:
  • Hot reload activation and behavior
  • Dev tools window appearance
  • Build optimizations
  • Debugging and logging
  • Advanced configuration

Build-Time vs Runtime Properties

Build-Time Properties

These properties are read during the Gradle build process and affect how hot reload tasks are configured:
  • Used in build.gradle.kts files
  • Affect task configuration and dependencies
  • Set using gradle.properties or -D flags during build

Runtime Properties

These properties are read when the application is running:
  • Control application behavior
  • Configure dev tools and orchestration
  • Set using -D flags when launching the app

Shared Properties

Many properties are available in both build and runtime contexts, allowing consistent configuration across your development workflow.

Commonly Used Properties

Hot Reload Activation

compose.reload.isActive

compose.reload.isActive
boolean
default:"false"
Indicates whether Hot Reload is active. Set to true when the application is launched with hot reload.
Target: Application
Usage: This property is automatically set by the hot reload tasks. You can check it programmatically:
import org.jetbrains.compose.reload.isHotReloadActive

if (isHotReloadActive) {
    println("Running with Hot Reload")
}

Dev Tools Configuration

compose.reload.devToolsEnabled

compose.reload.devToolsEnabled
boolean
default:"true"
Controls whether the dev tools window is launched.
Target: Application, DevTools, Build
# Disable dev tools entirely
./gradlew :app:hotRunJvm -Dcompose.reload.devToolsEnabled=false

compose.reload.devToolsHeadless

compose.reload.devToolsHeadless
boolean
default:"false"
Run dev tools in headless mode without showing the UI window.
Target: Application, DevTools, Build
# Run dev tools without UI
./gradlew :app:hotRunJvm -Dcompose.reload.devToolsHeadless=true

compose.reload.devToolsDetached

compose.reload.devToolsDetached
boolean
default:"false"
Launch the dev tools window as a detached, regular window instead of snapping it to the main application.
Target: Application, Build, DevTools
# Detach dev tools window
./gradlew :app:hotRunJvm -Dcompose.reload.devToolsDetached=true
When to use: Useful when experiencing window flickering, working with virtual desktops, or preferring a separate window.

Build Optimization

compose.reload.isHotReloadBuild

compose.reload.isHotReloadBuild
boolean
default:"false"
Indicates whether the current build is a hot reload recompilation. Used to disable unnecessary tasks and improve build speed.
Target: Build
build.gradle.kts
tasks.named("someExpensiveTask") {
    onlyIf {
        !System.getProperty("compose.reload.isHotReloadBuild").toBoolean()
    }
}

compose.reload.gradle.build.optimize

compose.reload.gradle.build.optimize
boolean
default:"true"
Enable build optimizations during hot reload, such as Gradle’s configuration cache.
Target: Application, DevTools, Build
# Disable build optimizations
./gradlew :app:hotRunJvm -Dcompose.reload.gradle.build.optimize=false

Logging and Debugging

compose.reload.logLevel

compose.reload.logLevel
enum
default:"Info"
Set the minimum logging level for hot reload components.
Target: Application, DevTools, Build
Values: Trace, Debug, Info, Warning, Error
# Enable debug logging
./gradlew :app:hotRunJvm -Dcompose.reload.logLevel=Debug

compose.reload.logStdout

compose.reload.logStdout
boolean
default:"false"
Output all hot reload logs to standard output.
Target: Application, Build, DevTools
# Log to stdout
./gradlew :app:hotRunJvm -Dcompose.reload.logStdout=true

UI Effects

compose.reload.effectsEnabled

compose.reload.effectsEnabled
boolean
default:"true"
Enable visual reload effects shown in the UI when a reload is triggered.
Target: Application, Build
# Disable reload effects
./gradlew :app:hotRunJvm -Dcompose.reload.effectsEnabled=false

JetBrains Runtime Configuration

compose.reload.jbr.version

compose.reload.jbr.version
int
default:"21"
Specifies the default JetBrains Runtime version to use (e.g., 21 or 25).
Target: Build
# Use JBR 25
./gradlew :app:hotRunJvm -Dcompose.reload.jbr.version=25

compose.reload.jbr.autoProvisioningEnabled

compose.reload.jbr.autoProvisioningEnabled
boolean
default:"false"
Automatically provision a compatible JetBrains Runtime for hot reload tasks.
Target: Build
This is an experimental feature. Please report any issues you encounter.
gradle.properties
compose.reload.jbr.autoProvisioningEnabled=true

Gradle Build System

gradle.build.project

gradle.build.project
string
The Gradle project path that needs recompiling (e.g., :app:, :, or :someModule:composeApp).
Target: Application, DevTools

gradle.build.task

gradle.build.task
string
The name of the task to recompile for hot reload, typically a ComposeReloadHotClasspathTask.
Target: Application, DevTools

gradle.offline.mode

gradle.offline.mode
boolean
default:"false"
The offline mode setting for Gradle. The recompiler uses the same setting to avoid cache misses.
Target: Application, DevTools

Advanced Properties

compose.reload.virtualMethodResolveEnabled

compose.reload.virtualMethodResolveEnabled
boolean
default:"true"
Enable dependency analysis for virtual calls (interfaces and their implementations).
Target: Application, Build
# Disable virtual method resolution
./gradlew :app:hotRunJvm -Dcompose.reload.virtualMethodResolveEnabled=false

compose.reload.dirtyResolveDepthLimit

compose.reload.dirtyResolveDepthLimit
int
default:"5"
Limit how deep the dependency graph is traversed when marking scopes as dirty.
Target: Application, Build
# Increase depth limit
./gradlew :app:hotRunJvm -Dcompose.reload.dirtyResolveDepthLimit=10

compose.reload.staticsReinitializeMode

compose.reload.staticsReinitializeMode
enum
default:"AllDirty"
Controls how static fields are re-initialized after reload.
Target: Application, Build
Values:
  • AllDirty: Re-invoke all static initializers recognized as dirty
  • ChangedOnly: Only re-initialize statics of changed classes
This is an experimental feature.
./gradlew :app:hotRunJvm -Dcompose.reload.staticsReinitializeMode=ChangedOnly

Setting Properties

Via Command Line

Use the -D flag when running Gradle tasks:
./gradlew :app:hotRunJvm -Dcompose.reload.devToolsDetached=true -Dcompose.reload.logLevel=Debug

Via gradle.properties

Add properties to your gradle.properties file:
gradle.properties
compose.reload.devToolsDetached=true
compose.reload.logLevel=Debug
compose.reload.jbr.autoProvisioningEnabled=true

Via IDE Run Configuration

In IntelliJ IDEA or Android Studio:
  1. Open Run | Edit Configurations
  2. Select your hot reload run configuration
  3. Add VM options: -Dcompose.reload.devToolsDetached=true

Programmatically

Check properties in your code:
fun main() {
    val isHotReload = System.getProperty("compose.reload.isActive") == "true"
    
    if (isHotReload) {
        println("Running with Hot Reload")
    }
}

Common Configurations

Headless Development

For CI or automated testing:
./gradlew :app:hotRunJvm \
  -Dcompose.reload.headless=true \
  -Dcompose.reload.devToolsHeadless=true

Debugging Hot Reload

./gradlew :app:hotRunJvm \
  -Dcompose.reload.logLevel=Debug \
  -Dcompose.reload.logStdout=true

Detached Dev Tools (Virtual Desktops)

./gradlew :app:hotRunJvm \
  -Dcompose.reload.devToolsDetached=true

Minimal Dev Tools

./gradlew :app:hotRunJvm \
  -Dcompose.reload.effectsEnabled=false \
  -Dcompose.reload.devToolsHeadless=true

Property Reference

For a complete list of all available properties, see the properties.yaml file in the Compose Hot Reload repository. The properties are documented with:
  • key: The property name
  • type: Data type (boolean, int, string, enum, file, etc.)
  • target: Where the property is used (build, application, devtools)
  • default: Default value
  • visibility: public, delicate, experimental, internal, or deprecated
  • documentation: Detailed description

Property Visibility

  • public: Stable properties for general use
  • delicate: Use with caution; behavior may change
  • experimental: Early-stage features; subject to change
  • internal: For internal use only; not recommended for users
  • deprecated: Will be removed in future versions

Build docs developers (and LLMs) love