A Kotlin library for driving Compose Desktop UIs from automated tests. Reads the semantics
tree, drives mouse and keyboard input — either real OS-level events via java.awt.Robot or
synthetic AWT events dispatched straight into the window hierarchy (RobotDriver.synthetic(...),
useful when tests run in parallel and can't fight over OS focus) — and records the screen,
against IDE-hosted Compose surfaces (IntelliJ, Jewel) and standalone desktop apps alike.
Important
Spectre is pre-1.0. Stable APIs are covered by the compatibility policy in
docs/STABILITY.md; experimental APIs, especially the HTTP transport,
may change between releases. Read docs/SECURITY.md before enabling
cross-JVM control or recording in environments that handle untrusted input.
macOS, Windows, Linux Xorg, and Linux Wayland. The Wayland path goes through a small
out-of-process Rust helper (recording/native/linux/) that owns the xdg-desktop-portal
handshake, the PipeWire FD lifetime, and the gst-launch-1.0 subprocess; the JVM-side
recorder talks to it over stdin/stdout via a tiny JSON protocol. Same out-of-process
architecture as the macOS Swift helper.
Note
Linux support is best-effort. Routine validation runs on one machine: Ubuntu 22.04,
exercising the Xorg session (input + popup + HiDPI + x11grab) and the GNOME / mutter
Wayland session (the portal-based recording path). Other distros, compositors (KDE /
Plasma, sway, wlroots), window managers, and Ubuntu versions aren't covered. Reports
and PRs widening the coverage are very welcome — open an issue with your distro /
compositor / session combo and we'll work through it.
User guide and API documentation: https://spectre.sebastiano.dev.
Install released versions from Maven Central, or consume the current checkout as a Gradle composite build while working ahead of a release: Installation.
Start at Getting started for the shape of a Spectre test, or The automator for the mental model.
Agent skill:
npx skills add rock3r/spectre --skill spectrecore— semantics tree, selectors, coordinate mapping, Robot-backed input.server— embedded HTTP transport (Ktor) for cross-JVM access. Experimental; seedocs/SECURITY.mdfor the trust model.recording— region capture, window-targeted video capture, and native still window screenshots where available (ScreenCaptureKit on macOS, Windows Graphics Capture on Windows, X11 region fallback on Linux).AutoRecorder/AutoScreenshotterpick per call. Seedocs/RECORDING-LIMITATIONS.md.recording-macos— runtime-only macOS ScreenCaptureKit helper resources for native window/region recording and still screenshots.recording-linux— runtime-only Linux helper resources for native Xorg and Wayland capture.recording-windows— runtime-only Windows Graphics Capture helper resources for native window/region recording and still screenshots. Runtime machines need Windows 10 version 1903+, .NET 8 Desktop Runtime, and Windows App Runtime 1.8; contributors building the helper need the .NET 8 SDK.agent— experimental local attach transport for driving a Spectre-instrumented JVM from a separate process.agent-runtime— loadable Java-agent runtime jar used byagentwhen attaching to a target JVM.testing— JUnit 5 extension and JUnit 4 rule.sample-desktop— Compose Desktop app for manual smokes.sample-intellij-plugin— in-tree IntelliJ plugin hosting a Jewel tool window. Unpublished; serves as the IDE-hosted test bed.
Standalone Compose Desktop app:
./gradlew :sample-desktop:runIntelliJ plugin — then Tools → Run Spectre Against the Sample Tool Window, or pass
-PspectreAutorun=true to fire the action on project open:
./gradlew :sample-intellij-plugin:runIde./gradlew check # tests + Detekt + Compose Rules + ktfmt
./gradlew ktfmtFormat # rewrite Kotlin / .gradle.kts in placeTwo heavier checks live outside :check:
:sample-intellij-plugin:uiTest— boots IntelliJ viaintellij-ide-starter, installs the plugin, firesRunSpectreAction, and asserts every tagged Compose node shows up inidea.log.:recording:checkon macOS — covers the Swift ScreenCaptureKit helper contract.
JBR 21 is the dev-loop default. JBR 25 also gets exercised via the IDE-hosted test (bundled with IntelliJ 2026.1). Any JDK 21+ works for the non-IDE modules. CI runs on Temurin 21.
ci.yml—:checkon Linux, every PR.macos-check.yml—:checkon macOS, broad path filter.windows.yml—:checkon Windows, broad path filter.macos.yml— Swift helper build +:recording:check, gated onrecording/**andrecording-macos/**.ide-uitest.yml— IDE-hosted UI test on macOS + Windows, gated on plugin / core / recording changes.out/ide-tests/{installers,cache}is cached between runs.validation-windows.yml—:sample-desktop:validationTest*on Windows, gated onsample-desktop/**. JUnit-XML-driven verifier so a Gradle/Compose protocol flake on shutdown can't hide a real failure.validation-linux.yml— same validation matrix on Linux underxvfb-run(real Xorg, no compositor in the loop), gated on the samesample-desktop/**filter shape.
For consumer projects, see Running on CI for the required test-JVM flags:
java.awt.headless=false for AWT, skiko.renderApi=SOFTWARE_COMPAT on GPU-less Linux runners,
and the macOS apple.awt.UIElement=true trade-offs for synthetic typing vs. clipboard paste.
The user guide and these reference pages are also published as a single browseable site at https://spectre.sebastiano.dev.
- Architecture
- Testing
- Conventions
- Static analysis
- Recording limitations
- Spike gist — original design notes.
