No NMS. No reflection. No version-specific hacks.

Build plugins without the pain.

Just clean, type-safe APIs. Write in the language you already use, and Pumpkin loads the result as a WebAssembly plugin.

Pick your language

rustup target add wasm32-wasip2

First step of 4 in the Rust guide. Open the guide

Same feature, two APIs

Send a welcome message, then ask for confirmation with a Java dialog or a Bedrock form. On Spigot that means reflection into NMS and a second plugin. On Pumpkin it's one branch.

Spigot + Reflection NMS + Geyser API (Java)
  • 18 reflection calls
  • Needs the Geyser API
  • Breaks on version bumps
WelcomeListener.java
// Send chat messageplayer.sendMessage("Welcome!"); // Handling Java vs Bedrock with Reflection NMS & GeyserGeyserApi geyser = GeyserApi.api();if (!geyser.isBedrockPlayer(player.getUniqueId())) {    try {        // Multi-version NMS Packet via Reflection        Object nmsPlayer = player.getClass().getMethod("getHandle").invoke(player);        Object connection = nmsPlayer.getClass().getField("playerConnection").get(nmsPlayer);        Class<?> pingClass = Class.forName("net.minecraft.network.protocol.game.ClientboundPingPacket");        Object packet = pingClass.getConstructor(int.class).newInstance(id);        connection.getClass().getMethod("send", Class.forName("net.minecraft.network.protocol.Packet")).invoke(connection, packet);         openCustomJavaDialog(player, "Confirm Action");    } catch (Exception e) { e.printStackTrace(); }} else {    // Bedrock-exclusive Geyser form API    GeyserConnection conn = geyser.connectionByUuid(player.getUniqueId());    CustomForm form = SimpleForm.builder().title("Confirm Action").content("Are you sure?").button("Yes").build();    conn.sendForm(form);} void openCustomJavaDialog(Player player, String title) throws Exception {    Object nmsPlayer = player.getClass().getMethod("getHandle").invoke(player);    Object conn = nmsPlayer.getClass().getField("playerConnection").get(nmsPlayer);    Class<?> dialogPacket = Class.forName("net.minecraft.network.protocol.game.ClientboundShowDialogPacket");    Object packet = dialogPacket.getConstructor(String.class).newInstance(title);    conn.getClass().getMethod("send", Class.forName("net.minecraft.network.protocol.Packet")).invoke(conn, packet);}// Nightmarish reflection boilerplate & fragile third-party dependencies

What the API gives you

Every player, one plugin

Native Java + Bedrock support. Multi-version built in. Write once, reach everyone.

Typed commands and events

Register commands and hook typed plugin events without reflection, NMS, or version-specific hacks.

Async by default

Built on Tokio. No main thread bottleneck. Heavy tasks don't freeze the server.

Memory safe

Rust guarantees. No null pointers, no memory leaks, no data races.

Quick start

Pick a language. Each guide goes from an empty folder to a plugin file Pumpkin can load.

  1. 1

    Creating a new project

    Pumpkin plugins use the Cargo build system.

    The complete code for this plugin can be found as a template on GitHub.

  2. 2

    Installing the toolchain

    Before we can compile a plugin, we have to have the wasm32-wasip2 target installed. You can install the target by running:

    Terminal
    rustup target add wasm32-wasip2
  3. 3

    Initializing a new crate

    First we need to create a new project folder. You can do this by running this command in the folder you created:

    Terminal
    cargo new <project-name> --lib

    After adding this, we want to create a new directory called .cargo and add in a config.toml file with the following contents:

    .cargo/config.toml
    [build]target = "wasm32-wasip2"

    Altogether your new folder structure should look like this:

    Project layout
    ├── .cargo/│   └── config.toml├── src/│   └── lib.rs├── Cargo.toml└── Cargo.lock
  4. 4

    Configuring the crate

    Since Pumpkin plugins are loaded at runtime as dynamic libraries, we need to tell Cargo to build this crate as one.

    Cargo.toml
    [package]name = "hello-pumpkin-wasm"version = "0.1.0"edition = "2024" [lib] crate-type = ["cdylib"] [dependencies]

    Next we need to add some basic dependencies. Since Pumpkin is still in early development, the internal crates aren't published to crates.io, so we need to tell Cargo to download the dependencies directly from GitHub.

    Cargo.toml
    [package]name = "hello-pumpkin"version = "0.1.0"edition = "2024" [lib]crate-type = ["cdylib"] [dependencies]# This is the api crate that makes creating plugins easier, and has wit definitionspumpkin-plugin-api = { version = "0.1.0", git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-plugin-api" }tracing = "0.1"

The full walkthrough is in the Rust documentation.

Ready to build?

The docs cover events, commands and the rest of the API. Discord is where to ask when they don't.