Guide

How to make a Minecraft plugin in Kotlin

Updated October 18, 2026

Kotlin runs on the JVM, so a Kotlin plugin uses the same Paper or Spigot API, the same plugin.yml and the same plugins/ folder as a Java one. The code is shorter and null-safe. The one thing Java plugins do not have to worry about is the Kotlin standard library: the server does not ship it, so the plugin has to bring it.

Start from this example.

Generate this with Codexe

Step by step

  1. 1.Create a Gradle project with Kotlin DSL

    A build.gradle.kts with the kotlin("jvm") plugin, a Java toolchain that matches your Minecraft version (17, 21 or 25) and the PaperMC repository.

  2. 2.Add the server API

    compileOnly("io.papermc.paper:paper-api:<version>"). Like in Java, the server provides it at runtime, so it is never bundled.

  3. 3.Write the main class

    class MyPlugin : JavaPlugin() with override fun onEnable(). Register commands and listeners exactly as in Java.

  4. 4.Bring the Kotlin standard library

    Bundle it into the .jar with the Shadow plugin, or let the server download it at startup through the libraries list in plugin.yml. Without one of them the plugin fails with NoClassDefFoundError: kotlin/....

  5. 5.Write plugin.yml

    The same file as a Java plugin: name, version, main (the Kotlin class), api-version, commands and permissions.

  6. 6.Build and test

    ./gradlew shadowJar (or build), copy the .jar from build/libs/ to a test server and read the console on startup.

Getting Kotlin onto the server

  • Shade it: the Shadow Gradle plugin copies the Kotlin standard library and other runtime libraries into your .jar. It works on every version and is the most common choice.
  • libraries in plugin.yml: from Spigot 1.16.5, a plugin can list Maven Central libraries that the server downloads and loads for it. The .jar stays small, but the server needs internet access on first start.
  • Libraries you add: kotlinx-coroutines is a separate library, not part of the standard library, and must be bundled too. Relocating it into your own package avoids clashes with other plugins that bundle another version.

Coroutines and the main thread

Coroutines are a clean way to load data from a database without freezing the server, but the Bukkit API (worlds, entities, inventories) must still be used from the main thread. Do the slow work on a background dispatcher, then switch back to the server thread with the scheduler before touching the game. Tie the coroutine scope to the plugin, so it is cancelled in onDisable().

Java or Kotlin?

FeatureJavaKotlin
APIPaper / SpigotThe same Paper / Spigot API
BuildMaven or GradleGradle with build.gradle.kts
Runtime extrasNoneKotlin standard library, bundled or loaded
Tutorials and examplesMost of themFewer, but Java examples translate directly

With Codexe

Choose Bukkit/Spigot/Paper (Kotlin). Codexe generates a Gradle project with build.gradle.kts, the Paper API, the Shadow plugin to bundle what the server does not provide, and coroutines bundled and relocated when the code uses them. It compiles the plugin before it is Ready, and Kotlin plugins can be tried on a test server and checked by test players like Java ones. See the Kotlin plugin generator.

"A Paper 1.21.4 plugin in Kotlin called Bounties: /bounty set <player> <amount> through Vault, the killer gets the reward, /bounty top shows the 10 highest, stored in SQLite with coroutines for database access. Use data classes and extension functions, keep the Bukkit API calls on the main thread."

Questions

Is a Kotlin plugin slower than a Java plugin?

No meaningful difference: both compile to JVM bytecode. The .jar is larger when the standard library is bundled.

Can I mix Java and Kotlin in one plugin?

Yes, Gradle compiles both in the same project, and Kotlin code calls Java classes directly.

Why NoClassDefFoundError for kotlin classes?

The Kotlin standard library is not in the .jar or not loaded. Build with shadowJar and install that .jar, or add the library to libraries in plugin.yml.

Make a Kotlin plugin

This prompt opens ready to send:

“A Paper 1.21.4 plugin in Kotlin called Bounties: /bounty set <player> <amount> using the Vault economy, the killer gets the reward, /bounty top shows the 10 highest, bounties stored in SQLite with coroutines for database access, Bukkit API calls on the main thread, messages in config.yml.”

Generate this with Codexe
How to make a Minecraft plugin in Kotlin (Paper) | Codexe