Migrating from a Maven or Gradle plugin project
If you already have a plugin project built with Maven or Gradle, pluggy can take over without a full rewrite. This recipe walks through the translation: what maps to what, what goes away, and what you’ll still do by hand. It assumes you already understand how Maven or Gradle work; for first-time plugin authors, start with Getting started instead.
What pluggy replaces
| Old world | pluggy equivalent |
|---|---|
pom.xml or build.gradle | project.json |
<dependencies> or implementation(...) | project.json:dependencies |
<repositories> or repositories { } | project.json:registries (Maven only) |
maven-shade-plugin config | project.json:shading |
mvn package or ./gradlew shadowJar | pluggy build |
mvn test or ./gradlew test | pluggy test (JUnit Platform via testDependencies) |
plugin.yml (hand-written) | pluggy-generated, or staged via resources |
src/main/java/ | src/ |
src/main/resources/ | project.json:resources mapping |
| IntelliJ/Eclipse import | Automatic. pluggy init writes the IntelliJ stub, pluggy build writes .classpath. See IDE integration. |
What pluggy does not do
- Parent POMs. pluggy’s Maven resolver doesn’t traverse parent POMs. If an upstream library uses one, property expansion can fail. Declare the missing transitives explicitly in
project.json. - Class relocation in shading. Moving
com.google.guava.*toyour.plugin.guava.*to avoid conflicts is not supported by pluggy’s shading. Keepmaven-shade-pluginor the Gradle shadow plugin, or open an issue. - Custom Gradle plugins. Anything that mutates the build graph in unusual ways (custom source sets, AOT annotation processors beyond standard javac flags) isn’t representable in
project.json. Keep Gradle for those projects.
Starting the migration
1. Stop Gradle/Maven
Move or rename the existing build files temporarily so pluggy doesn’t get confused and so you don’t trip over two build systems while migrating:
mv pom.xml pom.xml.old # Mavenmv build.gradle build.gradle.oldmv build.gradle.kts build.gradle.kts.old2. Scaffold a project.json
pluggy init --yes --name <your_name> --main com.your.Main --platform paperIf your project has a non-src/main/java source directory, you’ll fix that in step 4.
3. Port dependencies
In your old pom.xml:
<dependency> <groupId>net.kyori</groupId> <artifactId>adventure-api</artifactId> <version>4.17.0</version></dependency>Becomes:
pluggy install maven:net.kyori:adventure-api@4.17.0Or edit project.json directly:
"dependencies": { "adventure-api": { "source": "maven:net.kyori:adventure-api", "version": "4.17.0" }}Don’t port the platform API dep (Paper’s paper-api, Spigot’s spigot-api, Velocity’s velocity-api, Sponge’s spongeapi). pluggy adds it automatically based on compatibility.platforms[0].
Port Modrinth-sourced deps as well. If your Gradle build used the Modrinth Gradle plugin or a direct URL, switch to pluggy’s Modrinth source kind:
pluggy install worldedit@7.3.154. Move sources
pluggy expects <workspace>/src/<package>/<Class>.java. Move from Maven’s src/main/java/com/example/ to src/com/example/:
mv src/main/java/com ./src/Resources move too. If your Maven project had src/main/resources/config.yml,
declare it in resources:
"resources": { "config.yml": "src/main/resources/config.yml"}Or move the file and update the path:
mv src/main/resources/config.yml src/config.yml"resources": { "config.yml": "src/config.yml"}5. Port shading
maven-shade-plugin:
<configuration> <artifactSet> <includes> <include>net.kyori:adventure-api</include> </includes> </artifactSet> <filters> <filter> <artifact>net.kyori:adventure-api</artifact> <includes> <include>net/kyori/adventure/api/**</include> </includes> </filter> </filters></configuration>Becomes:
"shading": { "adventure-api": { "include": ["net/kyori/adventure/api/**"] }}pluggy’s shading is keyed by the dep name (the dependencies key), not the Maven coordinate. For Maven-sourced deps, the key is the artifactId, so net.kyori:adventure-api becomes adventure-api.
6. Port plugin.yml
pluggy generates a minimal plugin.yml from project.name, project.version, project.main, project.description, and derives api-version from compatibility.versions[0]. That’s usually enough.
If your existing plugin.yml has commands:, permissions:, or softdepend: blocks pluggy doesn’t model, stage it as a resource:
"resources": { "plugin.yml": "src/plugin.yml"}The resource-staging code sees that you’ve claimed plugin.yml and skips the auto-generation step. Your hand-written file wins.
7. Port tests
If your old project ran tests with mvn test or ./gradlew test, port them to pluggy test. Move sources from src/test/java/ to test/, and declare every test-only dependency under testDependencies in project.json:
"testDependencies": { "junit-jupiter": { "source": "maven:org.junit.jupiter:junit-jupiter", "version": "5.11.4" }, "mockbukkit": { "source": "maven:org.mockbukkit.mockbukkit:mockbukkit-v1.21", "version": "4.90.0" }}JUnit Platform Console Standalone is auto-injected, so you never declare it. See pluggy test for the full command, and the MockBukkit recipe for a worked example.
8. Port project.compatibility
Maven’s <properties> with <maven.compiler.target>21</maven.compiler.target> is implicit in pluggy. The JDK pluggy provisions for your project is what javac targets, and compatibility.versions[0] drives the Minecraft version. The api-version line in plugin.yml is derived, not configured.
A minimal before / after
Before: Maven pom.xml
<project> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>myplugin</artifactId> <version>1.0.0</version> <packaging>jar</packaging>
<repositories> <repository> <id>papermc</id> <url>https://repo.papermc.io/repository/maven-public/</url> </repository> </repositories>
<dependencies> <dependency> <groupId>io.papermc.paper</groupId> <artifactId>paper-api</artifactId> <version>1.21.8-R0.1-SNAPSHOT</version> <scope>provided</scope> </dependency> <dependency> <groupId>net.kyori</groupId> <artifactId>adventure-api</artifactId> <version>4.17.0</version> </dependency> </dependencies></project>After: pluggy project.json
{ "name": "myplugin", "version": "1.0.0", "main": "com.example.myplugin.Main", "compatibility": { "versions": ["1.21.8"], "platforms": ["paper"] }, "registries": ["https://repo1.maven.org/maven2/"], "dependencies": { "adventure-api": { "source": "maven:net.kyori:adventure-api", "version": "4.17.0" } }}Note what went away:
paper-api: inferred fromcompatibility.platforms[0].- PaperMC Maven repo: added automatically during resolve for Paper projects.
packaging,scope, andmodelVersion: pluggy has one output kind (plugin jar) and one scope model. Everything is compile-time on the classpath; shading decides what’s bundled.
Verify the translation
pluggy doctor # config validationpluggy build # full compile, descriptor, shade, and zippluggy test # if you ported testsCompare the output jar contents with your old shaded jar:
unzip -l bin/myplugin-1.0.0.jarplugin.yml should be present, config.yml should be present (if declared in resources), and any shaded classes should be under the expected paths.
What your team needs to change
- README. Replace
mvn packageand./gradlew buildwithpluggy build. Replacemvn cleanwithpluggy build --clean. Replacemvn testwithpluggy test. - CI. See CI without global pluggy.
- IDE import. Just open the repo in your editor.
pluggy initalready wrote the IntelliJ stub andpluggy buildwrites.classpathfor Eclipse and VS Code. No Maven or Gradle import flow.
See also
- project.json reference: every field in detail.
- Dependencies: the four source kinds.
- Build pipeline: what pluggy actually does.
pluggy test: the test runner reference.