What are managers?
plugins and themes are the two addon managers. They govern every addon of their kind through one shared lifecycle: loading a bundle, running it, persisting whether it’s on, and tearing it down.
Both extend a single base addon manager and behave identically. They differ in just one place: how a raw bundle becomes a running instance. They’re exposed as unbound.plugins and unbound.themes (and importable from @unbound-app/api).
The addon lifecycle
Every addon moves through the same stages. The key distinction is runtime vs intent: starting and stopping control whether the addon is executing right now; enabling and disabling control whether it should, a persisted preference restored on the next launch.Load
The bundle and manifest enter the manager. If the addon’s persisted state is enabled, it starts immediately.
Start / Stop
Runtime.
start turns the bundle into an instance and runs it; stop tears that instance down. Not persisted, purely “is it running this session?”.Enable / Disable / Toggle
Intent.
enable persists the addon as on (and starts it); disable persists it as off (and stops it); toggle flips between them. This is what survives a reload.Because enabled-state is persisted, the manager restores it on launch: an enabled addon auto-starts during Load. That’s the whole point of separating intent from runtime.
Manifests & validation
Every addon ships a manifest describing itself, and the manager validates it before loading. A missing or undefined required field rejects the addon. The shared schema (id, name, description, authors, version, main, plus the optional icon, updates, and url) is documented once:
The manifest
The shared addon manifest schema and validation rules.
Events & state
Managers are event emitters. Subscribe to lifecycle events to react when addons change:loaded, unloaded, started, stopped, enabled, disabled, toggled, reloaded. Enabled-state is persisted through storage, which is how it’s restored next launch.
Plugins vs themes
Same lifecycle, one difference: whathandleBundle does with a bundle. Plugins eval their bundle into a running instance with start/stop hooks. Themes parse their bundle as JSON and drive the theme store, applying the selected theme’s colors. Everything else (loading, validation, enable/disable, persistence, events) is shared.