Install
Most people don’t need this page — the home page covers the one-step paths for agents, VS Code, and the CLI. This page is the full reference: every install surface, requirements, and CI recipes.
CLI
The compose-preview binary works against any Compose project with no
build edits — it injects the preview plugin at runtime via a bundled
Gradle init script.
curl -fsSL https://raw.githubusercontent.com/yschimke/skills/main/scripts/install.sh | bash
The installer drops the CLI on your $PATH and (unless you pass
--cli-only) the compose-preview / compose-preview-review agent skills
into the Claude / Codex / Gemini skill directories. Useful flags:
| Flag | Effect |
|---|---|
--cli-only |
Install the CLI only, skip the skill bundles. |
--android-sdk |
Also install the Android cmdline-tools + platform + build-tools. |
--jdk 17,21 |
Install the listed JDK majors. |
VERSION |
Install a specific release instead of latest. |
Then:
compose-preview doctor # check Java + project compatibility
compose-preview list # scan @Preview annotations
compose-preview render # render every @Preview to PNG
compose-preview render-matrix --id com.example.MyPreview \
--ui-mode light,dark --font-scale 1.0,2.0 # one preview across a grid
Because the CLI auto-injects, projects that already apply
com.android.application / com.android.library / org.jetbrains.compose
work without touching build.gradle.kts. Projects that already declare the
plugin are detected and left alone, so mixed setups don’t conflict.
Builds that apply AGP via a convention plugin
If your build supplies the Android Gradle Plugin through an included build’s
convention plugin — the build-logic / gradle/conventions pattern used by
Now in Android, AndroidX, and
similar repos — auto-inject cannot apply the preview plugin, and discovery
will report 0 modules with failures like:
NoClassDefFoundError: com/android/build/api/variant/AndroidComponentsExtension
This is a classloader limitation, not a bug. With the convention-plugin layout
AGP is applied by the included build, so AGP’s classes live on the convention
plugin’s classloader. Auto-inject can only add the preview plugin to each
project’s own buildscript classpath — a sibling classloader that can’t see
AGP — so the plugin throws the moment it touches AndroidComponentsExtension.
There is no Gradle init-script API to contribute a dependency to an included
build’s classpath, so auto-inject genuinely can’t reach AGP here.
Apply the plugin from your convention plugin instead. That puts it on the
same classloader as AGP, where it renders correctly. The CLI then detects the
included-build apply and skips auto-inject automatically (no
--no-auto-inject needed).
-
Add the preview plugin’s marker artifact to your
build-logicbuild’s dependencies. This is the key step: it puts the plugin on the convention build’s runtime classpath, so the compiled convention plugin can apply it by id. (Declaring it inbuild-logic’splugins {}block withapply falseonly resolves it for that build script — not for the convention plugin applied to your app modules, which fails withPlugin with id … not found.) The marker coordinate is<id>:<id>.gradle.plugin:<version>:// build-logic/.../build.gradle.kts (the convention build) plugins { `kotlin-dsl` } dependencies { implementation( "ee.schimke.composeai.preview:ee.schimke.composeai.preview.gradle.plugin:<latest>" ) }Make sure
build-logic’s repositories include where the plugin is published (mavenCentral()/gradlePluginPortal()). -
Apply it from your convention plugin alongside AGP:
// build-logic/.../YourAndroidConventionPlugin.kt override fun apply(target: Project) = with(target) { pluginManager.apply("com.android.library") // or the AGP plugin you use pluginManager.apply("ee.schimke.composeai.preview") // …rest of your convention… } -
Run the CLI as usual — it sees the included build provides the plugin and leaves your build alone:
compose-preview render
This is the explicit “apply manually via your convention plugin” integration
mode: auto-inject is the zero-config convenience for the common
plugins { id("com.android.application") } layout; the convention-plugin
layout opts out of it by design.
Gradle plugin (version-pinned)
If you’d rather wire it into your build explicitly, the plugin is published to Maven Central — no auth, no PAT.
// <module>/build.gradle.kts
plugins {
id("ee.schimke.composeai.preview") version "<latest>"
}
Pin the version shown on Maven Central. (The in-repo samples/ apply it
without a version because they resolve it from this repository’s own
included build — that’s not drop-in for an external project.)
./gradlew :app:composePreviewDiscover # scan @Preview annotations
./gradlew :app:composePreviewRenderAll # render every @Preview to PNG
For direct ./gradlew use with the auto-inject script (e.g. a CI step that
needs extra Gradle flags), materialise the init script once and thread its
path through each invocation:
INIT_SCRIPT="$(compose-preview init-script --path)"
./gradlew --init-script "$INIT_SCRIPT" :app:composePreviewRenderAll
VS Code extension
Published to the VS Code Marketplace and Open VSX (VSCodium / Cursor / Windsurf). Open the Extensions view (⇧⌘X / Ctrl+Shift+X), search Compose Preview, click Install. It auto-injects on every Gradle invocation it makes — no project changes needed.
Agent skill
Point any agent that can fetch a URL at the
compose-preview skill
— a complete install-and-iterate playbook. The skill checks whether the CLI
is present and bootstraps it (via the installer above) if not, so “point the
agent at the skill” and “run the installer” converge on the same place. See
Agents & MCP for the agent loop the skill drives.
CI / GitHub Actions
Composite actions for pipelines:
install— pin the CLI on$PATH, with version-catalog + Renovate recipes.apply— unified pipeline: baselines on push, before/after PR comments, a11y + notification surfaces.
There’s also a reusable, preview-gated AI PR-review workflow (Codex / Claude / Gemini): see PR review workflow.
Requirements
Java 17+, Gradle 8.13+, AGP 8.13.0+ (Android), Kotlin 2.0.21+, Compose
Multiplatform 1.10.3+ (Desktop). The bottom edge of this envelope is
exercised on every push by the
agp8-min job.
Running an agent in a cloud sandbox (Claude Code on the web, etc.)? See the
cloud sandbox setup
for the network allowlist and install.sh --android-sdk Setup recipe.
</content>