Installation
ModuleKit is published under the group id gg.cubix at version 1.2.0. It
targets Java 25. This page covers adding it to a Gradle build for the three
common setups: a plain Java app, a feature module, and a shaded Minecraft plugin.
:::info Artifacts
| Artifact | When you need it |
|---|---|
gg.cubix:modulekit-api:1.2.0 | Always. Your module classes compile against this. |
gg.cubix:modulekit-core:1.2.0 | In the application/host that runs discovery and the lifecycle. |
gg.cubix:modulekit-paper:1.2.0 | Paper plugins. Pulls in api + core transitively. |
gg.cubix:modulekit-folia:1.2.0 | Folia servers (and Paper). Pulls in paper + core + api transitively. |
gg.cubix:modulekit-minestom:1.2.0 | Minestom servers. Pulls in api transitively. |
| ::: |
A feature module
A feature module is a self-contained unit (reporting, economy, chat, …).
It only needs the API to compile. If it references core types (like
InjectionResolver) keep them compileOnly, because the host already brings core.
plugins { `java-library` }
dependencies {
api("gg.cubix:modulekit-api:1.2.0")
// Only if this module touches core types directly; usually not needed:
compileOnly("gg.cubix:modulekit-core:1.2.0")
// Type references to services provided by OTHER modules:
compileOnly(project(":database")) // for the DatabaseService interface
compileOnly(project(":auth")) // for the AuthService interface
}
:::tip Why compileOnly for other modules?
A module needs the interface of a service it consumes at compile time, but it
must not bundle another module's implementation. ModuleKit supplies the real
instance at runtime through injection. compileOnly gives you the type without
the coupling.
:::
The host application (plain Java)
The host is the program that owns the main() method (or the plugin entry
point). It brings core — which contains the engine — plus every feature module
it wants to run.
plugins {
java
id("com.gradleup.shadow") version "9.4.1" // if you ship a single fat jar
}
dependencies {
implementation("gg.cubix:modulekit-api:1.2.0")
implementation("gg.cubix:modulekit-core:1.2.0")
// Every feature module you want available at runtime:
implementation(project(":database"))
implementation(project(":auth"))
implementation(project(":reporting"))
}
Bundling into a single jar — the one mandatory step
Modules are discovered through service files on the classpath (see Discovery). Every module contributes a file at the same path:
META-INF/services/gg.cubix.modulekit.api.module.Module
When you shade many modules into one jar, those files collide — they all have the same name. Without merging, only one survives and every other module becomes invisible. You must tell the shadow plugin to merge them:
tasks.shadowJar {
mergeServiceFiles {
include("META-INF/services/**")
}
}
:::danger This is the #1 setup mistake
If modules "disappear" — discovery finds one and silently ignores the rest — you
almost certainly forgot mergeServiceFiles. It is required for any fat jar that
bundles more than one module.
:::
Paper plugin
Paper plugins use the modulekit-paper adapter. Paper itself is compileOnly
(the server provides it at runtime).
plugins {
java
id("com.gradleup.shadow") version "9.4.1"
}
dependencies {
implementation("gg.cubix:modulekit-paper:1.2.0") // brings api + core
compileOnly("io.papermc.paper:paper-api:26.2.build.119-stable")
implementation(project(":gamemode"))
implementation(project(":economy"))
}
tasks.shadowJar {
mergeServiceFiles { include("META-INF/services/**") }
}
Continue with the Paper adapter guide.
Folia plugin
Folia plugins use modulekit-folia, which layers region-aware scheduling on top of
the Paper adapter. You still compile against paper-api — it ships the regionised
scheduler contracts, so no folia-api dependency is needed, and the resulting jar
runs on Paper as well.
plugins {
java
id("com.gradleup.shadow") version "9.4.1"
}
dependencies {
implementation("gg.cubix:modulekit-folia:1.2.0") // brings paper + core + api
compileOnly("io.papermc.paper:paper-api:26.2.build.119-stable")
implementation(project(":beacon"))
}
tasks.shadowJar {
mergeServiceFiles { include("META-INF/services/**") }
}
Your plugin must also declare folia-supported: true in its paper-plugin.yml, or
Folia will refuse to load it. Continue with the
Folia adapter guide.
Minestom server
Minestom servers use modulekit-minestom and are typically launched from your
own main().
dependencies {
implementation("gg.cubix:modulekit-minestom:1.2.0")
implementation("net.minestom:minestom:2026.08.16-26.2")
implementation(project(":world"))
implementation(project(":lobby"))
}
Continue with the Minestom adapter guide.
Verify your toolchain
ModuleKit is compiled for Java 25. Set your toolchain accordingly:
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(25))
}