Plugin System
Plugins are the primary extension model for Pipe Bomb. Music sources, metadata providers, search backends, and automation steps are provided by plugins - nothing is hardcoded into the server.
What is a plugin?
A plugin is a Node.js package installed into the server's plugin directory. It exports a single default class that extends the base Plugin interface from the SDK:
import { Plugin, PluginApiContext } from "@pipe-bomb/plugin-sdk";
export default class MyPlugin extends Plugin {
async enable(ctx: PluginApiContext): Promise<void> { ... }
async disable(): Promise<void> { ... }
}
The server loads all subdirectories of the plugin directory at startup (except for directories that start with .), calls enable() on each, and passes a PluginApiContext that the plugin uses to register its capabilities.
What plugins can register
| Registration call | What it does |
|---|---|
registerLibraryHandler(handler) |
Exposes a music source that can be scanned and streamed |
registerAttributeSource(source) |
Enriches tracks/artists/albums with metadata |
registerTrackIdentifier(id) |
Assigns canonical identities to tracks |
registerArtistIdentifier(id) |
Assigns canonical identities to artists |
registerAlbumIdentifier(id) |
Assigns canonical identities to albums |
registerEphemeralSource(source) |
Integrates an external catalog (search without indexing) |
registerSearchSource(source) |
Provides a search backend for the local library |
registerTask(task) |
Adds a background task runnable from the Tasks UI |
registerConfigManager(mgr) |
Adds a global plugin settings page |
registerUserConfigManager(id, mgr) |
Adds per-user plugin settings |
registerLanguageDirectory(path) |
Provides i18n strings for the frontend |
registerIconDirectory(path) |
Provides icons used by the frontend |
registerExternalUrlSource(source) |
Adds external links to entities (e.g. "Open in Spotify") |
getWorkflowClient() |
Register custom workflow triggers and steps |
getPlaylistClient() |
Manage playlists programmatically |
Plugin lifecycle
- Server starts → scans the plugin directory
- Each plugin directory is loaded:
package.jsonis validated, the entry file is imported, the class is instantiated enable(ctx)is called - the plugin registers its capabilities- On uninstall: the plugin directory is deleted; the plugin is not hot-unloaded (restart required)
Installing plugins
Plugins are installed from a git URL via the Settings → Installed Plugins UI or the API. The server clones the repo, runs npm ci and (if configured) npm run build, then moves the result into the plugin directory and calls enable() on it.
See users/Marketplace for installing from a curated registry.
Plugin inter-communication
Plugins can retrieve other loaded plugins via ctx.getPlugin(pluginId). This returns the raw plugin instance, so the calling plugin must know the API the target plugin exposes. This is the mechanism for plugin dependency chains.
Related pages
- development/Plugin-Development — how to write a plugin
- development/Library-Handler — exposing a music source
- development/Attribute-Source — enriching metadata
- users/Identifiers — canonical identity system
- users/Ephemeral-Sources — external catalog integration
- development/Workflow-Steps — custom automation
- users/Marketplace — plugin registries