Plugin packages (plugin.json)
Every Mixlar plugin ships as a folder, not a single script. The app reads
the folder’s plugin.json manifest before it runs a single line of your
code — that’s what makes drop-in installs, hot-loading, and the trust gate
possible.
Package layout
Section titled “Package layout”Drop your plugin’s folder into %APPDATA%\Mixlar\config\plugins\:
<PlugName>/ plugin.json ← manifest (required, read before any code runs) <entry>.py ← the MixlarPlugin subclass(es) widgets/<id>/ ← device widget bundles (widget.json + assets) screen/ ← full-screen device page (BETA — reserved, not yet implemented) icons/ ← PNGs: PC-app UI icons AND device widget image assetsThe device widget bundle format (widget.json, elements, the WDATA/WEVENT
protocol) is covered separately in
Widget spec.
plugin.json (manifest v1)
Section titled “plugin.json (manifest v1)”Here’s a complete example, taken from a real single-widget plugin:
{ "manifest": 1, "id": "mouse_battery", "name": "Mouse Battery", "version": "1.2.0", "author": "Mixlar Labs", "description": "Shows your wireless mouse battery on the device.", "entry": "mouse_battery.py", "icon": "fa5s.mouse", "icon_color": "#1DB954", "icons_dir": "icons", "min_app_version": "1.4.1", "widgets": [ { "id": "mouse_batt", "name": "Mouse Battery", "version": "1.2.0" } ], "screen": { "id": "mouse_screen", "name": "Battery Screen", "beta": true }, "publisher": "", "sig": ""}Field reference
Section titled “Field reference”| Field | Required | Meaning |
|---|---|---|
manifest |
Yes | Manifest format version — must be 1 |
id |
Yes | Plugin id (should match the .py’s plugin_id) |
name |
Yes | Display name |
version |
Yes | Semver. The manifest wins over the .py class attributes |
entry |
Yes | The plugin .py filename inside the folder — no paths, no .. |
author |
No | Shown on the plugin card |
description |
No | Shown on the plugin card |
icon |
No | Icon shown on the plugin card (e.g. a fa5s.* icon name) |
icon_color |
No | Accent color for the icon, as a hex string |
icons_dir |
No | Folder of PNGs installed into the app’s icon set (also usable as widget assets) |
min_app_version |
No | Reject the package on app versions older than this |
widgets[] |
No | Device widgets this plugin ships — see below |
screen |
No | BETA placeholder for a future full-screen device page — parsed and shown in the install popup, not yet rendered |
publisher |
No | Reserved: signing key id |
sig |
No | Reserved: base64 ed25519 signature of the package digest — see Verification & signing |
Unknown fields are ignored, so the format is forward-compatible.
The widgets[] array
Section titled “The widgets[] array”Each entry declares a device widget bundle the plugin ships:
{ "id": "mouse_batt", "name": "Mouse Battery", "version": "1.2.0" }idmust match awidgets/<id>/folder, and must be 2–24 characters matchinga-z0-9_-.versionshould equal the"version"field inside that widget’swidget.json. The manifest’s version is authoritative — if the two disagree,mixlar-sdk validatewarns but the manifest value wins.- Give each widget a real
"version": "x.y.z"and bump it on changes — that’s what drives the app’s update prompts on connect.
Validation rules
Section titled “Validation rules”These are the exact checks the app (and mixlar-sdk validate) run against
plugin.json, in order — the first failure blocks the load:
plugin.jsonmust parse as valid JSON and be a JSON object.manifestmust equal1.id,name,version, andentrymust all be present as non-empty strings.versionmust be a valid semver string.entrymust end in.pyand must not contain/,\, or...- The file named by
entrymust exist inside the package folder. - If
min_app_versionis set and the running app is older, the package is rejected with a version-mismatch error. - Every entry in
widgets[]must have anidmatching^[a-z0-9_-]{2,24}$, andwidgets/<id>/widget.jsonmust exist on disk.
mixlar-sdk validate additionally reports (as warnings, not hard failures):
idhas surrounding whitespaceicons_diris set but the folder doesn’t existauthorordescriptionis missing (both are shown on the plugin card)- a widget’s manifest
versiondoesn’t match itswidget.jsonversion sigis present but fails signature verification (reported as an error, not a warning)
Install & update flow
Section titled “Install & update flow”- Drop-in while the app is running: the folder watcher waits for the copy to finish, runs the trust gate, hot-loads the plugin, and pops up “This plugin supports N widget(s)… Install to device?” — Install streams the widget bundle(s) to the device immediately (or on next connect if disconnected); Not now defers, and the widget stays available from the plugin’s Send to Device button.
- On every connect: the app asks the device for its installed-widget
inventory (
WLIST→WLIST,<id>,<version>lines). Widgets absent from the device auto-install; widgets whose bundled version is newer than the device’s are collected into one Update All / Skip prompt. Skipping is remembered per version, so you’re only asked again when the version increases. - Manual: every plugin with widget bundles has a Send to Device button (on the plugin card and in the settings header) that force-pushes its bundles.
- Old firmware without
WLISTfalls back to content-hash change detection — everything still installs and updates, just without the version prompt.
Verification & signing
Section titled “Verification & signing”Each package gets a deterministic SHA-256 package digest, computed over
the manifest (with sig blanked out), the entry file, and the contents of
widgets/, screen/, and icons/. The digest is checked against the local
trust cache and the Mixlar marketplace API; unknown packages prompt the user
before any plugin code runs — the same gate applies to startup loads and
to live drop-ins.
publisher and sig are reserved for package signing (ed25519 over the
digest). A package with an invalid signature is never auto-trusted. Full key
infrastructure is future work — unsigned packages currently use the hash flow
above. Details in Signing.
Reference examples
Section titled “Reference examples”The SDK ships example packages under PC Software/Plugin Examples/:
| Example | What it shows |
|---|---|
HttpTrigger/ |
Minimal template — macro actions + slider mode, no widget |
Mouse Battery/ |
Single-widget bundle with live data pushes |
Custom Widget Demo/ |
Multi-widget showcase — 5 widgets including interactive elements, pages, and QR codes |
Next steps
Section titled “Next steps”- Write the plugin class itself: Plugin API
- Scaffold a new package with the CLI: mixlar-sdk create
- Learn the device widget bundle format: Widget spec