Installation¶
Spectre publishes these library modules to Maven Central:
| Module | Maven coordinate |
|---|---|
core |
dev.sebastiano.spectre:spectre-core:<version> |
testing |
dev.sebastiano.spectre:spectre-testing:<version> |
recording |
dev.sebastiano.spectre:spectre-recording:<version> |
recording-macos |
dev.sebastiano.spectre:spectre-recording-macos:<version> |
recording-linux |
dev.sebastiano.spectre:spectre-recording-linux:<version> |
recording-windows |
dev.sebastiano.spectre:spectre-recording-windows:<version> |
server |
dev.sebastiano.spectre:spectre-server:<version> |
agent |
dev.sebastiano.spectre:spectre-agent:<version> |
agent-runtime |
dev.sebastiano.spectre:spectre-agent-runtime:<version> |
Before a release tag is published
The main branch declares 0.1.0-SNAPSHOT. Until a tagged release has been published
to Maven Central, consume the checkout as a Gradle composite build (includeBuild) or
publish locally with ./gradlew publishToMavenLocal.
Requirements¶
- JDK 21 or newer. JBR 21 is the project's dev-loop default; JBR 25 is exercised via the IDE-hosted UI test. Any JDK 21+ works for the non-IDE modules.
- Windows 10 version 1903 or newer, .NET 8 Desktop Runtime, and Windows App Runtime 1.8 for native window/region recording and still-window screenshots through Windows Graphics Capture. Contributors and CI that build the helper from source need the .NET 8 SDK.
- A Compose Desktop or Compose Multiplatform (desktop target) application. Spectre reads Compose's semantics tree, so the UI under test must be a real Compose surface.
- Platform-specific recording dependencies if you plan to use the recording module — see Recording for the per-OS prerequisites.
Consume from Maven Central¶
Add the modules you need to the consuming project's build.gradle.kts:
dependencies {
testImplementation("dev.sebastiano.spectre:spectre-core:<version>")
testImplementation("dev.sebastiano.spectre:spectre-testing:<version>")
// Optional, depending on what you need:
testImplementation("dev.sebastiano.spectre:spectre-recording:<version>")
testRuntimeOnly("dev.sebastiano.spectre:spectre-recording-macos:<version>") // macOS SCK helper
testRuntimeOnly("dev.sebastiano.spectre:spectre-recording-linux:<version>") // Linux capture helper
testRuntimeOnly("dev.sebastiano.spectre:spectre-recording-windows:<version>") // Windows WGC helper
testImplementation("dev.sebastiano.spectre:spectre-server:<version>")
testImplementation("dev.sebastiano.spectre:spectre-agent:<version>")
testRuntimeOnly("dev.sebastiano.spectre:spectre-agent-runtime:<version>") // Java-agent runtime
}
spectre-recording contains the public recording API and common JVM implementation.
The macOS, Linux, and Windows helper artifacts are runtime-only resources: add the one(s)
your tests can run on with testRuntimeOnly(...), or with runtimeOnly(...) for
production application code.
If you depend on server, you also need to add a Ktor server engine yourself — Spectre
intentionally doesn't bundle one. See Cross-JVM access for the choice.
If you depend on agent, keep the artifact roles separate:
- Add
spectre-agentto the attacher's compile/test classpath. This is the API containingAgentAttach,AttachedAutomator, andAttachOptions. - Add
spectre-agent-runtimeto the attacher's runtime/test-runtime classpath.AgentAttachlocates that physical jar and passes it toVirtualMachine.loadAgent(...). - Add
spectre-coreto the target app. The target does not needspectre-agentorspectre-agent-runtimedeclared as dependencies.
Custom launchers that do not expose the runtime jar on java.class.path can pass an explicit
AttachOptions.agentJarPath or set -Ddev.sebastiano.spectre.agent.runtimeJar=<path>. See
Agent attach for the full attach flow and custom path examples.
You also need the JUnit version that matches the wrapper you'll use:
The testing module declares both JUnit dependencies as compileOnly, so consumers
pick whichever they're already using.
Consume the current checkout¶
Clone Spectre next to the project that wants to use it:
In the consuming project's settings.gradle.kts, include Spectre's checkout as a
composite build and map the published module coordinates to the included projects:
includeBuild("../spectre") {
dependencySubstitution {
substitute(module("dev.sebastiano.spectre:spectre-core"))
.using(project(":core"))
substitute(module("dev.sebastiano.spectre:spectre-testing"))
.using(project(":testing"))
substitute(module("dev.sebastiano.spectre:spectre-recording"))
.using(project(":recording"))
substitute(module("dev.sebastiano.spectre:spectre-recording-macos"))
.using(project(":recording-macos"))
substitute(module("dev.sebastiano.spectre:spectre-recording-linux"))
.using(project(":recording-linux"))
substitute(module("dev.sebastiano.spectre:spectre-recording-windows"))
.using(project(":recording-windows"))
substitute(module("dev.sebastiano.spectre:spectre-server"))
.using(project(":server"))
substitute(module("dev.sebastiano.spectre:spectre-agent"))
.using(project(":agent"))
substitute(module("dev.sebastiano.spectre:spectre-agent-runtime"))
.using(project(":agent-runtime"))
}
}
In the consuming project's build.gradle.kts, use the same coordinates as the Maven
Central path — Gradle resolves them against the included build:
dependencies {
testImplementation("dev.sebastiano.spectre:spectre-core")
testImplementation("dev.sebastiano.spectre:spectre-testing")
// Optional, depending on what you need:
testImplementation("dev.sebastiano.spectre:spectre-recording")
testRuntimeOnly("dev.sebastiano.spectre:spectre-recording-macos")
testRuntimeOnly("dev.sebastiano.spectre:spectre-recording-linux")
testRuntimeOnly("dev.sebastiano.spectre:spectre-recording-windows")
testImplementation("dev.sebastiano.spectre:spectre-server")
testImplementation("dev.sebastiano.spectre:spectre-agent")
testRuntimeOnly("dev.sebastiano.spectre:spectre-agent-runtime")
}
Versions are intentionally omitted: includeBuild substitutes the project dependency
into the consumer's classpath using whatever version the included build declares, so
the 0.1.0-SNAPSHOT declared by Spectre's root Gradle build is implicit.
For local Maven-style testing without a composite build, publish the current checkout to Maven Local:
Modules at a glance¶
| Module | What it gives you |
|---|---|
core |
ComposeAutomator, semantics tree reader, selectors, RobotDriver for input. |
testing |
ComposeAutomatorExtension (JUnit 5), ComposeAutomatorRule (JUnit 4). |
recording |
Region and window-targeted screen capture API (AutoRecorder, native helpers, deprecated ffmpeg escape hatches, …). |
recording-macos |
Runtime-only macOS ScreenCaptureKit helper resources for recording. |
recording-linux |
Runtime-only Linux capture helper resources for recording. |
recording-windows |
Runtime-only Windows Graphics Capture helper resources for recording. |
server |
Embedded HTTP transport (Ktor) and HttpComposeAutomator for cross-JVM access. Experimental; see Security notes. |
agent |
Local attach transport API. Experimental; see Agent attach. |
agent-runtime |
Loadable Java-agent runtime for agent; add as runtime-only beside the API jar. |
Most projects only need core + testing. Add recording if you want video output for
test runs, add the platform helper artifact(s) for the OSes you run recording tests on, and
add server or agent if your test process needs to reach a UI in a different JVM.
Next¶
Continue to Getting started for a worked example.