Quickstart
From zero to a module on screen
Two routes: download the released JAR, or build it yourself. The download needs no credentials; building does, because Gradle resolves mirror-api from GitHub Packages.
Route A — use the released JAR
Every v* tag publishes the built JAR as a release asset. Downloading an asset does not go through GitHub Packages, so no token is involved:
curl -LO https://github.com/pierrejochem/SpeculumExampleModule/releases/latest/download/SpeculumExampleModule.jar
cp SpeculumExampleModule.jar /path/to/Speculum/plugins/
Restart the mirror and the module appears at top_center. The current release is v1.1.0, which needs mirror-api 1.3.0 — that is Speculum v1.3.0 or newer.
Route B — requirements
- JDK 17–21. The bundled Gradle wrapper runs on these; a newer default
javaneedsJAVA_HOMEororg.gradle.java.homepointed at one. - A GitHub personal access token with the
read:packagesscope.
org.speculum:mirror-api is public, but GitHub's Maven registry still requires authentication for every download. This is a registry policy, not a permission on the package.Credentials for GitHub Packages
Keep them out of the repository. Either put them in your user Gradle properties:
# ~/.gradle/gradle.properties
gpr.user=<your-github-username>
gpr.token=<a-PAT-with-read:packages>
…or export them instead:
export GITHUB_ACTOR=<your-github-username>
export GITHUB_TOKEN=<a-PAT-with-read:packages>
gradle.properties deliberately contains no credentials — only a comment pointing here.Build
git clone https://github.com/pierrejochem/SpeculumExampleModule.git
cd SpeculumExampleModule
./gradlew jar
The JAR lands in build/libs/SpeculumExampleModule.jar. Check the thin-JAR contract — it should hold only the example classes and the service file, with no Compose or mirror-api classes inside:
unzip -l build/libs/SpeculumExampleModule.jar
./gradlew build additionally runs ktlint, detekt and the test suite.
Deploy and run
Point the deployToMirror task at a Speculum checkout or install:
./gradlew deployToMirror -Pspeculum.pluginsDir=/path/to/Speculum/plugins
The SPECULUM_PLUGINS_DIR environment variable does the same. With neither set the JAR is copied to build/plugins/ for you to move yourself.
Then start the mirror the usual way (see Speculum's Getting Started). The module is discovered on startup — nothing to register.
Choosing a mirror-api version
mirror-api is published on every v* tag of the Speculum project; the artifact version is the tag without its leading v. Set it in gradle/libs.versions.toml:
[versions]
mirrorApi = "1.3.0"
Pin the oldest version whose API you actually use — a module compiled against an older mirror-api still loads in a newer host, because added SPI methods carry default implementations. settingsSchema() is the reason this project needs 1.3.0.