How Nexus sees a plugin
Read this first if you have never seen a Nexus plugin: it shows what runs where and which files a plugin has.
Nexus never imports your code into its own process. It starts a worker thread for each configured instance of a plugin and talks to it with messages. Three consequences follow:
- A plugin that crashes, hangs or leaks takes nothing else down. Nexus restarts it.
- Everything the plugin knows about Nexus arrives through the SDK objects (
this.config,this.store, theparamsof a sensor). You never see the bus, the database or other plugins. - Values you send and receive are plain data (see Values) that survives being copied between threads.
Your plugin offers two kinds of signals, which are named values on Nexus' internal bus:
| Kind | Direction | Is for | You write |
|---|---|---|---|
| Sensor | device to Nexus | a reading, a state, an event | a class that calls emit(value) |
| Actuator | Nexus to device | a command, a setting, a switch | a class whose run(value) talks to the device |
The user then connects signals with wires (for example a sensor of yours to a Miniserver input). Wires, topics and the Bus Inspector are the user's business; you only decide what exists and what it does.
The user adds an instance of your plugin (with its settings) and then adds signals to the instance, either by hand or by picking them from your catalog. One plugin can have many instances, for example one per inverter, and each runs separately.
Shape of a plugin
my-plugin/
package.json "loxNexus": { "apiVersion": 1, "id": "myplugin", "entry": "dist/plugin.js", "name": "…", "icon": "…" }
src/
index.ts export default PluginEntry.define(MyPlugin)
MyPlugin.ts class MyPlugin extends Plugin<MyConfig>
MyConfig.ts zod schema; secret fields wrapped in secret()
sensors/*.ts one Sensor class per kind of value (device to Loxone)
actuators/*.ts one Actuator class per kind of command (Loxone to device)
MyCatalog.ts optional browsable tree of ready-to-add sensors and actuators
*.test.ts PluginTestHost tests, next to the code they test
test/fixtures/ recorded (or documented) API responses the tests serve
The manifest is explained in Publishing a plugin. id is the
plugin's topic segment and stable reference: myplugin/<instance>/sensor/<signal>.
Keep files short and give each class one job. The first-party plugins are a good model.
PluginEntry.define(MyPlugin) in src/index.ts is the only line that connects your class to the
runtime. Loaded by Nexus it starts the runtime; imported anywhere else (tests, tools) it just
returns the class.