Plugins · 01

Plugin developers

This guide is for plugin authors targeting Silk. It covers the metadata Silk understands, the compatibility behaviors it provides, and the patterns that travel best across Paper, Folia, and Silk.

Recommended metadata

Add this to plugin.yml:

silk-supported: true

Silk also honors the legacy upstream key:

folia-supported: true

Either flag is sufficient. Marking your plugin tells Silk you have at least reviewed the regional threading model and consider your plugin compatibility-aware.

Practical guidance

What Silk tries to help with

What Silk will not do

Patterns that travel well

// Schedule on the entity's owning region
entity.getScheduler().run(plugin, task -> {
    entity.setHealth(20);
}, null);

// Schedule global tick work
Bukkit.getGlobalRegionScheduler().run(plugin, task -> { /* ... */ });

// Async teleport (works on Paper, Folia, Silk)
player.teleportAsync(target).thenAccept(success -> { /* ... */ });

Patterns to avoid on Silk

// Legacy sync schedule with no region context.
// Silk bridges this through the Global Region Scheduler, but plugins should
// migrate to the region/entity/global schedulers explicitly.
Bukkit.getScheduler().runTaskTimer(plugin, () -> { /* ... */ }, 0L, 20L);

// Synchronous cross-world teleport in a tick callback.
// Silk will warn and return optimistically; the actual teleport runs async.
entity.teleport(somewhereInAnotherWorld);

Detection

Plugins that want to identify the server platform can check Bukkit.getServer().getName() or ServerBuildInfo. Silk reports brand SilkMC with key gg.tame:silkmc. The upstream Folia classes still exist under their original packages for binary compatibility, so feature-detection (rather than name-detection) remains the most reliable approach.