Skip to content

JetBrains/compose-hot-reload

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,737 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

drawing Compose Hot Reload

JetBrains official project Kotlin Beta Maven Central GitHub license docs Slack channel

Build Compose UIs faster and let your creativity flow when designing multiplatform user interfaces.

Text changing depending on mode. Light: 'So light!' Dark: 'So dark!'

With Compose Hot Reload, you can make UI code changes in a Compose Multiplatform app and see the results instantly, without needing to restart. The JetBrains Runtime intelligently reloads your code whenever it changes.

Important

Compose Hot Reload needs a JVM target in your multiplatform project. We're exploring adding support for other targets in the future.

Prerequisites

Ensure that your project meets the minimum version requirements:

  • Kotlin 2.1.20 or higher.
  • Compose compiler 2.1.20 or higher.
  • Compose Multiplatform 1.8.2 or higher.
    • CHR 1.2.0-alpha02 and later requires Compose Multiplatform 1.10.0+.
  • JetBrains Runtime: To be compatible with JetBrains Runtime, your project must target Java 21 or earlier.

For the best development experience, we recommend using an IDE with the Kotlin Multiplatform plugin:

Set up your project

There are two ways to add Compose Hot Reload to your project:

Create a project from scratch

Follow the Kotlin Multiplatform quickstart guide to set up your environment and create a project. Be sure to select the desktop target when you create the project.

Apply the Gradle plugin to your project

  1. In your project, update the version catalog. In gradle/libs.versions.toml, add the following code:

    composeHotReload = { id = "org.jetbrains.compose.hot-reload", version.ref = "composeHotReload"}
    
  2. In the build.gradle.kts of your parent project, add the following code to your plugins {} block:

    plugins {
        alias(libs.plugins.composeHotReload) apply false
    }
    

    This prevents the Compose Hot Reload plugin from being loaded multiple times in each of your subprojects.

  3. In the build.gradle.kts of the subproject containing your multiplatform application, add the following code to your plugins {} block:

    plugins { 
        alias(libs.plugins.composeHotReload)
    }
    
  4. An installation of the JetBrains Runtime is required: Launching Compose Hot Reload with the Kotlin Multiplatform IDE plugin will re-use IntelliJ's installation of the JetBrains Runtime. If you want Gradle to automatically download the JetBrains Runtime, add the following code to your settings.gradle.kts file

    plugins {
        id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
    }
    

    Alternatively, you can use automatic JetBrains Runtime provisioning for the hot reload tasks by enabling the compose.reload.jbr.autoProvisioningEnabled property.

Important

Automatic JetBrains Runtime provisioning is an experimental feature. Please report any issues you encounter.

  1. Click the Sync Gradle Changes button to synchronize Gradle files:

    Synchronize Gradle files

Use Compose Hot Reload

You can run your application with Compose Hot Reload using your IDE or the CLI via Gradle tasks. Compose Hot Reload supports two modes: Explicit mode and Auto mode.

  • In Explicit mode, you manually trigger the reload to apply changes.
  • In Auto mode, Compose Hot Reload uses Gradle’s file-watching and continuous build system to automatically reload when file changes are detected. To enable this mode, specify the --autoReload or --auto arguments in CLI or in the run configuration settings.

In the IDE

In IntelliJ IDEA or Android Studio, you can run Compose Hot Reload directly from the IDE gutter.

  1. Click the Run icon Run main function in the gutter of your main function and select Run 'shared [jvm]' with Compose Hot Reload.

  2. When you save code changes, the reload is triggered automatically.

    Alternatively, you can trigger the reload explicitly by pressing the assigned shortcut key or clicking the Reload UI button:

    Reload UI in the IDE

You can modify the trigger behavior on the Settings | Tools | Compose Hot Reload page in your IDE.

Important

If you don't have the Kotlin Multiplatform IDE plugin installed, you can manually create Gradle run configurations with hot reload tasks (see Run tasks). In this case, you can trigger the reload by clicking the Reload UI button or running the reload Gradle task.

From the CLI

Run tasks

The Compose Hot Reload plugin automatically creates the following tasks to launch the application:

  • :hotRunJvm: For multiplatform projects. The async alternative is :hotRunJvmAsync.
  • :hotRun: For Kotlin/JVM projects. The async alternative is :hotRunAsync.

You can run these Gradle tasks from the command line:

./gradlew :app:hotRunJvm
# or
./gradlew :composeApp:hotRunJvm

After making changes, save all files to automatically update your app's UI.

Custom target name

If you define a custom JVM target name, Gradle uses a different task name. For example, if your target name is desktop:

kotlin {
    jvm("desktop")
}

The task name is :hotRunDesktop.

Command-line arguments

Here's a list of all the possible arguments that you can use with the Gradle run tasks:

Argument Description Example
--mainClass <Main class FQN> The main class to run. ./gradlew :app:hotRunJvm --mainClass com.example.MainKt
--autoReload
--auto
Enable automatic reloading. Default: false. ./gradlew :app:hotRunJvm --autoReload
./gradlew :app:hotRunJvm --auto
--no-autoReload
--no-auto
Disable automatic reloading. ./gradlew :myApp:hotRunJvm --no-auto
./gradlew :myApp:hotRunJvm --auto
Configure the main class

You can configure the main class directly in your build script instead of passing it as a command-line argument.

You can configure it in the Compose Hot Reload task:

tasks.withType<ComposeHotRun>().configureEach {
    mainClass.set("com.example.MainKt")
}

Or if you use Compose Multiplatform, in the application {} block:

compose.desktop {
    application {
        mainClass = "com.example.MainKt"
    }
}

Reload tasks (Explicit mode)

Warning

You can't run reload tasks with the --autoReload or --auto command-line argument.

The Compose Hot Reload plugin also provides Gradle tasks to recompile and reload your application:

  • reload: Reload all, currently running, applications.
  • hotReloadJvmMain: Reload all applications that use the jvmMain source set.

For example:

./gradlew :app:reload

Use developer builds

If you want to try the latest changes in Compose Hot Reload, you can use dev builds. To use the latest 'dev' builds of Compose Hot Reload, add the firework Maven repository in your settings.gradle.kts file:

pluginManagement {
    repositories {
        maven("https://packages.jetbrains.team/maven/p/firework/dev")
    }
}

dependencyResolutionManagement {
    repositories {
        maven("https://packages.jetbrains.team/maven/p/firework/dev")
    }
}

MCP server for AI agents

Note: the MCP server is in experimental status and available since the 1.2.0-alpha01 version of Compose Hot Reload.

Compose Hot Reload includes a Model Context Protocol (MCP) server that allows AI agents to interact with a running Compose application. The MCP server connects to the application's orchestration layer and exposes the following tools:

Tool Description
status Checks whether a Compose application is currently connected
reload Recompiles the project and hot-reloads the changed classes into the running application. Reports whether classes were reloaded, or {"status": "reloading"} when it does not finish within the optional timeout_seconds (default 60) — in that case, poll status until reloadState is no longer reloading
list_windows Lists registered application windows as a JSON array (id, title, x, y, width, height)
take_screenshot Captures a screenshot of the application window
get_semantic_tree Returns the Compose semantic/accessibility tree of the application as JSON (component roles, names, descriptions, states, and bounds)
click Clicks the UI element with the given nodeId. The node must expose onClick in get_semantic_tree
long_click Long-presses the UI element with the given nodeId. The node must expose onLongClick
type_text Replaces the content of an editable text field (nodeId) with the given text. The node must expose editableText
scroll Scrolls a scrollable container (nodeId) by deltaX / deltaY logical pixels. The node must support the ScrollBy semantic action
scroll_to_index Scrolls a container (e.g. LazyColumn / LazyRow, nodeId) so the item at zero-based index becomes visible. The node must support the ScrollToIndex semantic action
resize_window Resizes the window to the given width × height in pixels (both must be positive)

Targeting a specific window

Every tool except status, reload, and list_windows accepts an optional window_id parameter and follows the same window-selection rules. An agent may use list_windows to discover the available IDs.

  • window_id provided — the tool operates on that specific window.
  • window_id omitted — the tool operates on the first registered window, that is, the first window the running application has added to its window state. Concretely, this is the first window that is composed and shown during startup (the first Window { ... }, singleWindowApplication { ... }, or DialogWindow { ... } reached). Windows opened later in the session are appended in registration order; closing a window removes it from that list, so the "first registered" entry can change at runtime if the original first window is closed.
  • window_id does not match any currently registered window — the tool returns Window '<id>' not found.

When the MCP server starts, it waits for the app to launch, detects shutdown, and reconnects automatically on restart.

Run the MCP server

Start the MCP server alongside your application using the Gradle task:

./gradlew :app:hotMcpServerJvm
# or
./gradlew :composeApp:hotMcpServerJvm

The task name follows the same naming convention as the run tasks. For a custom JVM target named desktop, the task would be :app:hotMcpServerDesktop.

Configure an AI agent

To configure an AI agent, point your AI agent's MCP client configuration to the Gradle task. For example, in a .mcp.json:

{
  "mcpServers": {
    "compose-hot-reload": {
      "command": "./gradlew",
      "args": [
        "--no-daemon",
        "--quiet",
        "--console=plain",
        "hotMcpServer"
      ]
    }
  }
}

FAQ

I'm developing an Android-only app without Kotlin Mutliplatform. Can I use Compose Hot Reload?

Compose Hot Reload is designed to work with Compose Multiplatform. To use Compose Hot Reload with an Android-only project, you need to:

  • Switch from the Jetpack Compose plugin to the Compose Multiplatform plugin.
  • Add a separate Gradle module and configure the JVM target according to the instructions.

My project is a desktop-only app with Compose Multiplatform. Can I use Compose Hot Reload?

Yes! However, be aware that you can't start the application via the run button in the gutter (CMP-3123). Instead, use Gradle tasks.

Feedback and issues

Feel free to submit any feedback to the CMP issue tracker. If you encounter an issue, please check the known issues and limitations for potential workarounds.

About

Compose Hot Reload: Make changes to your UI code in a Compose Multiplatform application, and see the results in real time. No restarts required. Compose Hot Reload runs your application on the JetBrains Runtime and intelligently reloads your code whenever it is changed.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Contributors

Languages