Creating a plugin
sh
pnpm genThis runs the plugin generator (a Turborepo generator, defined in turbo/generators/). It asks for three things:
| Prompt | Example | Used for |
|---|---|---|
| Folder name | my-plugin | packages/my-plugin/, the npm package name, the release tag prefix and the .wasm file name. Kebab-case, and the folder must not exist yet. |
| Plugin name | MyPlugin | The name Pumpkin shows and the data folder name (plugins/data/MyPlugin/). PascalCase. Defaults to the folder name converted. |
| Description | Does a thing | The plugin's metadata, its README, its package.json and the package table in the root README. At most 70 characters, since it is also the package description; src/info.ts can say more later. |
To skip the prompts, pass the answers in that order:
sh
pnpm gen --args my-plugin MyPlugin "Does a thing"What it does
- Creates
packages/<folder>/with a working plugin:package.json,tsconfig.json,vitest.config.ts,src/name.ts,src/info.ts,src/commands/spec.ts,src/plugin.ts, a barebonesREADME.md(a title and generated blocks, including the component reference marker) and an integration test that loads the built plugin and checks its starter/plugincommand on a real Pumpkin server. The name and command permission are declared once in their respective source modules. - Registers the plugin for releases: an entry in
release-please-config.json(with"release-as": "0.0.1") and one in.release-please-manifest.json, with the plugin starting at version0.0.0, so that its first release is0.0.1. Thepackage.jsoncomes with the license, author, repository and funding metadata every package has. CI fails if a plugin isn't registered or its metadata is incomplete (pnpm check). See Registering a plugin for releases. - Runs
pnpm install, fills in the plugin's README from itsinfo.ts, generates its docs-site reference links from repository metadata, and adds the plugin to the root README. - Formats the new files with Biome.
It doesn't commit anything. A CI job (🧬 Generator) generates a throwaway plugin on every run and typechecks, builds and integration-tests it, so the templates can't silently rot.
Next steps
- Describe what the plugin needs in
src/info.ts(permissions, commands, config), editing or replacing the starter command insrc/commands/spec.tswithdefineCommands. Keep its permission under theCOMMAND_PERMISSIONconstant. See Plugin info and READMEs. - Add plugin-specific behavior in
src/plugin.ts'sonPluginLoadhook. The generated plugin extendsPluginBaseand callsregisterPlugin, which provide shared metadata, lifecycle logging and the automatic update check. Read Building first: plugins run on QuickJS and a few API calls need workarounds. Follow Code style: public code needs JSDoc descriptions andpnpm lintchecks it. - If the plugin needs settings, declare them as a schema with
@pumpkin-plugins/configand add it as a dev dependency. See Plugin config. - Run
pnpm exec turbo run build test:integration --filter=@pumpkin-plugins/<folder>to build the plugin and load it on a real server.
Files and network access
A plugin can't read files or open sockets unless its WIT world imports the WASI interfaces. Opt in per plugin in package.json:
json
"pumpkinPlugin": { "entry": "src/plugin.ts", "output": "build/my-plugin.wasm", "wasi": ["filesystem", "sockets", "http"] }The server also has to grant the matching permissions. PluginBase metadata includes the automatic updater permission; list other permissions in info.permissions:
| Capability | Permissions the plugin will typically request |
|---|---|
filesystem | fs.read.data, fs.write.data (access is limited to the plugin's own data folder, preopened as data) |
sockets | network.tcp.bind to listen, network.tcp.connect to connect out |
udp | network.udp.bind to receive, network.udp.outgoingdatagram to send to any address, network.udp.connect to talk to one |
http | http.outbound to make HTTP or HTTPS requests; the automatic updater adds this permission |
Without the generator
Copy packages/bedrock-addon-manager or generate a plugin and delete what you don't need. Three things are easy to forget:
- The plugin has to be registered for releases: an entry in
release-please-config.jsonand one in.release-please-manifest.json, with the plugin at version0.0.0. The exact entries are in Registering a plugin for releases, andnode scripts/check-release-config.mjstells you what is missing. pnpm installhas to run so the workspace links are created.pnpm readmehas to run so the package table lists it and its docs-site reference links are generated.