Repository navigation
Releases: kakao/prevue
Release list
v0.21.0
Name a file in commonMain and its previews come up in the browser and redraw on save, the same way Android ones do — Kotlin Multiplatform and Compose Multiplatform modules work end to end. Prevue also gets going on a Mac without Android Studio, finding an installed JDK by itself and saying what is missing (Java or the Android SDK) before anything is approved, and saving stays under a second even when you pause between edits.
Kotlin Multiplatform
Prevue now draws commonMain previews of Kotlin Multiplatform and Compose Multiplatform modules. Like Android Studio, it draws them from the module's Android compilation, and iOS · web targets alongside are fine. It takes AGP 9's com.android.kotlin.multiplatform.library (variant androidMain) and the older kotlin.multiplatform + com.android.library pair. If you warmed up an app module with an earlier version, warm it up once more to pick all of this up.

PartyAnimationPreview from the commonMain of the KotlinConf app (Apache 2.0), opened in Prevue's interactive mode.
- Warmup. Previews come up from the dump of the Android app that includes the module. Warming up with a file of a KMP module takes that app's dump, even on a fresh clone where nothing is built yet (when several apps include it, it asks which one), and a module with no Android target says why.
- Saving. Prevue watches commonMain · androidMain and the intermediate source sets Android takes part in, so saving redraws without Gradle. That includes KMP modules of an included build under the repository (
includeBuild("components"), as in Thunderbird'scomponents/ui/bolt). expect·actual. Saving or opening a file withexpect·actualdeclarations says it needs a Gradle build. It used to try compiling and fail with "'expect' and 'actual' declarations can be used only in multiplatform projects" plus advice to warm up the module. Now the picture stays as it was, marked stale with "needs a Gradle build", and redraws on its own when the build outputs change. Opening such a file changed since the last Gradle build, or bringing back an empty tab by saving one, draws from the Gradle build with the same mark instead of failing.- Compose Multiplatform resources (
Res). Fonts, images and strings fromcomposeResourcesused to fail with "Missing resource … .cvr" or fall back to the default font. Prevue now takes the app's merged assets from the dump and draws them as the app does. A KMP module'ssrc/androidMain/resand manifest are also watched for resource changes. - The older JetBrains
@Preview(org.jetbrains.compose.ui.tooling.preview.Preview) reads like the androidx one. Multipreview annotations built from it now expand, constants in its arguments (widthDp = WIDE) are read from the compiled class, and an aliased import still counts. Its@PreviewParameterproviders already worked. - Viewer. A KMP module's file names its source set in the subtitle (
feature:pearl · commonMain · debug). In the open-files rail, a shared source set's file icon carries the Kotlin Multiplatform mark and a KMP module's androidMain an Android robot, in the official one-color logo (black, white in dark mode); Android-only files keep the plain file icon, and the icons are 18px. A shared source set's tab tooltip adds "Shared code · rendered with the Android build", and the first time you open such a file in a checkout, a note at the bottom says "commonMain renders with the app's Android build too. expect calls run the Android actual." until you close it (it steps aside while you look at other files).prevue statusgainskmp, andsourceSetfor the shown file and for each tab of a KMP module. - README. The subtitle names Jetpack Compose and Compose Multiplatform, and a Compose Multiplatform badge joins the badge row, now regrouped into plain build, version and license badges and brand-colored ones for Claude Code, Codex, Jetpack Compose, Compose Multiplatform and JDK. Get started says to name a file in commonMain the same way, the board section says commonMain Previews are drawn from the module's Android compilation, and Supported lists which KMP modules work and which stop.
Setup without Android Studio
- Without Android Studio, Prevue finds an installed JDK by itself, and says so when there is none. It used to run only on Android Studio's bundled Java or the JDK in
PREVUE_JDK: a Mac with JDK 25 from Homebrew still stopped at "Java is missing", and with neither,healthreported only the server as missing andstartthen failed with "FileNotFoundError: [Errno 2] No such file or directory". Now, with noPREVUE_JDK, it looks at Android Studio (/Applicationsand~/Applications), thenJAVA_HOME,Library/Java/JavaVirtualMachines, Homebrew'sopenjdk*and SDKMAN, reading each JDK's version itself, and takes 25 first, then 21–24, then 26 or later. When none is 21 or later,healthlistsjdkundermissingfirst, before any download or Gradle run is approved, saying where it looked (jdkSearched) and to runbrew install openjdk@25(no sudo), andstartstops with the same message before it opens the preparation screen or touches a running server; call again after installing and it is found with nothing to set. A Java older than 21 counts as missing too, so aPREVUE_JDKpointing at JDK 17 no longer passeshealthonly for the server to fail after setup and warmup; the response names the version it found injdkVersion. Previews were byte-identical on Android Studio's JBR 25, Temurin 21 and Temurin 25; 25 or later starts about a second faster. Thanks to @Dwite for the fix (#29). - Without an Android SDK,
healthsays so before anything is approved. The preview server draws against the SDK'sandroid.jar, found throughANDROID_HOME, thenANDROID_SDK_ROOT, then~/Library/Android/sdk. With none there, setup and warmup went ahead and the server then failed to start, leaving only "android.jar를 찾지 못했다" in its log. Nowhealthlistssdkundermissingright afterjdk, with the folder it checked and how to install the SDK, andstartstops with the same message before it opens the preparation screen. An SDK folder with no platform downloaded counts as missing, and an emptyANDROID_HOMEis skipped the same way by both.
Performance
- Saving stays under a second when you pause between edits. The preview server used to start the Kotlin compiler's environment over on every save, so with saves half a minute apart, compiling one file could climb from about 0.3 s to 0.6–1 s after a few saves and a save took longer than a second (KotlinConf's
PageTitle.kt, a commonMain file). Now it keeps that environment between saves, as the Kotlin daemon does. On an Apple M4 Max, six to ten saves 30 seconds apart took a median of 0.64–0.79 s across four runs, against 0.63–1.19 s across five runs without it; a jar that Gradle rewrites in the meantime is still read fresh.
Fixes
- Projects whose module directories don't follow their Gradle paths work end to end. When
settings.gradle(or a settings plugin) moves a module withprojectDir—:widgetsliving incore/design/widgets— saving a file failed to compile with "Unresolved reference" because it borrowed the app's classpath, andwait·focus·scroll·touchanswered "No daemon" (#30). The dump now records each module's directory from settings, so warm up once more to pick it up. Thanks to @sergei-lapin for the report and the fix (#31). - A component no longer stretches when you pick a device in interactive mode. A preview that sizes itself to its content, such as a card or a row, used to be drawn only as tall as its content. The viewer then stretched that picture to fill the device screen, so text looked tall and squeezed. It now draws at the device's screen size like a custom size does, with the component at the top left and the rest of the screen empty. The posture pictures drawn ahead and the CLI's PNG change the same way. The renderer takes whole dp only, so on devices whose screen does not divide evenly into dp (Pixel 9, Pixel 9 Pro Fold, Galaxy Z Fold8 and Fold8 Ultra) the picture can be one pixel off the panel size, for example 1079×2423 on a Pixel 9.
- When the renderer or a project's
ui-toolingdoesn't pair with Prevue, the preview fails and names what's missing. If a project'sandroidx.compose.ui:ui-toolinglacked the tree accessor Prevue reads, the picture still came out but pointing at it found nothing, with only the warning "Compose 노드 없음 — 렌더는 성공했지만 Preview가 그린 노드가 없다", which blamed the preview. Now that render fails with "Couldn't read the Compose tree from ComposeViewAdapter — this project's androidx.compose.ui:ui-tooling doesn't pair with Prevue's renderer (ComposeViewAdapter.getViewInfos$ui_tooling is missing)". On the renderer side, the internals Prevue uses to load, preload and swap your classes are now opened when the server starts, and when any is missing it stops there listing all of them ("The renderer doesn't pair with this Prevue — couldn't open renderer internals: …"), instead of failing partway through a later render or save. - When the preview server fails on its first start,
startgives the reason. On the...
v0.20.2
prevue setupworks with only Android Studio's Java installed. It used to stop with "Cannot find a Java installation … matching: {languageVersion=17}" unless JDK 17 was also installed (#22). JDK 21 or later is enough now, as the README says.- Saving redraws projects built for Java 21. When a saved file called an
inlinefunction from a module built for JVM 21, the redraw failed with "cannot inline bytecode built with JVM target 21 into bytecode that is being built with JVM target 17" (#21). Prevue now compiles each saved file for the same JVM target Gradle used for that module.
v0.20.1
- Reporting a problem has a form now. New issues offer a "Not working" form that asks where Prevue stopped, your environment, and the size of your project, and the README links to it. To tell us about a screen you can't see in a Preview, use the pinned discussion instead.
v0.20.0
- The daemon starts faster with JDK 25 or later (Android Studio's bundled runtime is 25). The first daemon after an install or update records a class cache when it stops; later starts load it, which cuts about a second off the first Preview. The cache is about 200MB in
~/.prevue/aotand shows up inprevue paths. SetPREVUE_AOT=0to turn it off. - The first Preview after
startshows sooner when its file changed since your last Gradle build. The daemon compiles that file while the renderer is still starting, instead of waiting behind compiler warmup, and draws the first picture only from the new code. Other files that look newer than the build are compiled with the next change, unless the opened file needs them. - The daemon uses less memory when you switch between large devices. Moving back and forth between Fold8, Fold8 Ultra and a 1600×1600dp custom size for a long time used to peak at about 3.6GB. It now stays under 3GB, because the daemon caps its heap at 2GB and hands unused memory back sooner. Set
PREVUE_HEAPto raise the cap. - The README headline now says it's for Compose. It used to read only "Your agent finally sees the UI it builds."
v0.19.0
- The plugin install is smaller. Claude Code and Codex now download only the plugin itself, not the repository's README media, design prototypes, tests, or test fixtures. Update the marketplace before the plugin this time — a marketplace entry from before this release can no longer find the plugin.
- A running daemon no longer breaks when the plugin's files are rebuilt or replaced under it. It runs from its own copy, so drawing keeps working instead of failing with
NoClassDefFoundError. prevue stopreports only daemons that actually stopped. A daemon that can't handle the stop request is now shut down with a signal instead of being counted as stopped while it kept its port. If one still won't stop,stopanswersok:falseand lists it underfailed.
v0.18.3
- The README intro video is redrawn. Hot swap now changes a whole board of Previews twice, layout then theme, and the every-screen part follows the same drink screen into its two-pane layout from 673 wide and onto a folding iPhone Duo.
v0.18.2
- The README now opens with a 20-second intro video and reads more naturally in English and Korean. Install and update share one section.
v0.18.1
- Fixed blurry interactive frames when the same Preview is open in more than one window. The daemon shrank the moving picture to the width of whichever window reported last and sent it to every window, so one small window (or a leftover headless browser) made a large window's animation a stretched thumbnail (945px drawn at 139px). Now each window's width is kept separately, frames go out at the widest window still attached, and closed windows drop out. Still frames were always full size.
v0.18.0
First public release.
- Jetpack Compose
@Previews in the browser, without Android Studio. Prevue renders them with headless layoutlib, and saving a file redraws them in about a second without Gradle. Gradle runs once, to read the build setup, and never touches your build files. - Your agent sees what it builds. The Claude Code and Codex plugins let the agent open a Preview, wait for the redraw, and look at the picture itself, so it can check its own work.
- Point instead of explaining. Click anything in a Preview and the agent reads it as a file and line.
- Every Preview on one board, with an interactive mode that runs clicks and animations, a workspace that resizes the screen or switches devices (phones, foldables, tablets, iPhones), and quick open (
/·⌘K). - One worktree, one daemon. Each checkout draws with its own code, so several agents can work side by side.
- The viewer speaks English and Korean (
?lang=ko,prevue --lang ko). The CLI and agent skills are English, and the agent relays them in your language. - Licensed under Apache-2.0.
