The shape of a plugin
A plugin is an object with optional lifecycle hooks. Unbound callsstart when the plugin is enabled and stop when it’s disabled, so everything a plugin does (its patches, listeners, subscriptions) is set up in start and torn back down in stop.
Whatever you create in
start, undo in stop. A plugin that’s toggled off should leave no trace running. Dangling patches and listeners are the most common source of bugs after a disable.How plugins are loaded
Here’s the part that shapes how you should write one: every installed plugin’s bundle is loaded and evaluated at startup, whether or not it’s enabled. Being disabled means Unbound never calls yourstart; it does not mean your bundle’s top-level code is skipped.
So anything you do at the top level of your bundle runs for every user on every launch, even with your plugin turned off.
Writing a fast plugin
Two techniques keep a plugin’s startup cost near zero until it’s actually enabled and used.Defer module lookups with lazy
Wrap top-level Metro handles in
lazy (from unbound.utils) or use the { lazy: true } search option. The search then runs the first time you touch the result (inside start, or even later inside a handler) instead of at import.Where to go next
Manifest
The metadata every addon ships and how it’s validated.
Function Patching
Intercept and modify any function with the patcher.
Patching Components
Change what Discord’s components render.
Flux Stores
React to Discord’s internal events and stores.
Debugging
Tools for developing and inspecting your plugin.