Gradle Configuration

After installing the Gradle plugin, you can customize how the compiler plugin instruments your code.

You will not need most of this. Every option below already defaults to the value that makes hot reload work, which is why applying the plugin is the whole setup. The block exists for the cases where you want to narrow what HotSwan touches.

Configuration options

Configure the plugin in your module's build.gradle.kts using the hotSwanCompiler block:

hotSwanCompiler {
    debugOnly = true
    dispatchRewriteEnabled = true
    literalPatching = true
    instrumentObjects = true
    desktopEnabled = true
    strictManifestLint = false
}

debugOnly

Instrument debug variants only. Release builds compile normally with no HotSwan transformation and no runtime dependency. HotSwan is a development tool, so there is rarely a reason to change this. Default: true.

dispatchRewriteEnabled

The master switch. When false, the module compiles without the dispatch rewrite that makes its code reloadable, so nothing in it hot reloads. Reach for it only when a module has a reason to keep its bytecode untouched. Default: true.

literalPatching

The fast path. Literal values are wrapped so that changing one can be pushed to the running app without compiling anything. Turning it off does not break hot reload, it just makes literal edits take the normal compile path. Default: true. See Fast Pathing.

instrumentObjects

Admit top level Kotlin object declarations into instrumentation, so a screen written as object HomeScreen : Screen() reloads like any other. Default: true.

desktopEnabled

Instrument JVM desktop compilations in a Compose Multiplatform project, which is what lets a desktop window reload from the same save as your device. Default: true.

strictManifestLint

Fail the build on any manifest rule violation instead of warning. Default: false, which warns and carries on.

iosBundleId

A fallback bundle id for the iOS simulator delivery task, for projects where it cannot be derived. Leave it unset unless HotSwan asks you for it.

Excluding classes

To keep specific classes out of instrumentation without turning the module off, list them by fully qualified name:

hotSwanCompiler {
    exclude("com.example.HotPath**")
    exclude("com.example.legacy.*")
    exclude("com.example.exact.OneClass")
}

The pattern grammar is small:

  • A trailing ** matches the prefix and everything below it, so com.foo.** matches both com.foo.Bar and com.foo.bar.Baz
  • A trailing * matches one segment, so com.foo.* matches com.foo.Bar but not com.foo.bar.Baz
  • No wildcard is an exact match

An excluded class compiles exactly as it would without HotSwan, and edits to it need a rebuild. Use this for a class with strict bytecode requirements rather than as a general tuning knob, since anything you exclude is something you can no longer hot reload.

Setting options on the command line

Every boolean option above also reads a Gradle property, so you can flip one for a single run without editing a build file:

./gradlew assembleDebug -Photswan.literalPatching=false

The property name is hotswan. followed by the option name, so hotswan.debugOnly, hotswan.dispatchRewriteEnabled, hotswan.instrumentObjects and hotswan.desktopEnabled all work the same way. A value set in the build file wins over the property.

This is mostly useful for bisecting. If a reload behaves oddly, turning one option off for a run tells you whether that part of the pipeline is involved, without committing anything.