Skip to main content

Mixlar SDK

PyPI Python

The official SDK and CLI for building Mixlar Control plugins and M1X device widgets. Write a plugin once, against typed, importable classes — the same classes the desktop app itself uses — and test it end-to-end without a device plugged in: lint the manifest, run it against a headless mock device, render its widget to a PNG, sign it, and package it, all from the command line.

Off-app, from mixlar import MixlarPlugin gives you a faithful standalone implementation with autocomplete and type checking. Inside the running Mixlar Control app, that same import transparently becomes the app's own live class — so a plugin authored against this SDK loads completely unmodified. See How this maps onto the app below.

Install

pip install mixlar-sdk

Or, to hack on the SDK itself, from a checkout of this folder:

pip install -e .

Optional extras, added as needed:

extra adds needed for
[render] Pillow mixlar-sdk emulate --render (widget PNG previews)
[publish] requests mixlar-sdk publish (nicer HTTP errors; stdlib fallback works without it)
[dev] pytest, Pillow, requests running this SDK's own test suite
[all] everything above "just give me all of it"
pip install -e ".[all]"

This installs the mixlar-sdk console script. You can also run it in place with python -m mixlar_cli (handy before pip install -e ., or in CI).

Quickstart

mixlar-sdk create "My Plugin" --template full   # scaffold into ./my_plugin/
cd my_plugin
mixlar-sdk validate                             # lint plugin.json + widgets/
mixlar-sdk emulate --render preview.png         # render the widget, no hardware
mixlar-sdk emulate --interactive                # press/toggle/slide it from a REPL
mixlar-sdk keygen --key-id my-key               # once, if you plan to sign
mixlar-sdk pack --sign my-key                   # build a signed .mixplugin
mixlar-sdk link                                 # copy it into the app's plugins dir

create names the output folder after the plugin id (a slug derived from the display name, or --id), not the display name itself — "My Plugin" becomes ./my_plugin/.

Commands

command what it does
create scaffold a new plugin package from a template (macro, slider, widget, full)
validate lint plugin.json and every bundled widgets/<id>/widget.json
link copy (or symlink) a package into the app's plugins directory
dev validate + link once, then watch the folder and re-sync on save
emulate run a package against a headless mock device — render a PNG or drive it interactively
pack zip a validated package into a .mixplugin, optionally signing it first
sign sign a package in place with a publisher key
verify check a package's signature against the pinned publisher keyset
keygen generate an ed25519 publisher keypair
publish upload a .mixplugin to the marketplace (stub until the endpoint ships)

Full reference with flags and example output: docs/cli.md.

The SDK in a nutshell

from mixlar import MixlarPlugin
from mixlar.macros import MacroActions, action
from mixlar.colors import ACCENT

class MyPlugin(MacroActions, MixlarPlugin):
    plugin_id = "my_plugin"
    plugin_name = "My Plugin"
    plugin_icon_color = ACCENT

    #: Pairs this plugin with widgets/my_widget/widget.json.
    widget_id = "my_widget"

    @action("ping", "Ping", icon="fa5s.satellite-dish")
    def _ping(self, step):
        self.push_widget_data("status", "pong!")   # → WDATA,my_widget.status,pong!

    def on_widget_shown(self, widget_id):
        self.push_widget_data("status", "idle")

    def on_widget_event(self, widget_id, element_id, action):
        if element_id == "ping_btn" and action == "press":
            self._ping({})

That's a complete plugin: a macro action, a bundled device widget pairing, and a button handler. No boilerplate quartet of empty methods to override — MacroActions derives get_macro_actions() / get_macro_action_groups() / get_macro_action_icons() / execute_macro_step() from the @action decorators for you (see docs/plugin-api.md).

How this maps onto the app

Everything in this SDK is a faithful, importable port of code that already lives inline in PC Software/mixlar_mini.pyMixlarPlugin, PluginRegistry, the color palette, the ed25519 package signing, the widget/manifest linters. Off-app you get standalone reimplementations (so imports resolve in your editor and this SDK has no dependency on the app). Inside the running app, mixlar.plugin.MixlarPlugin, mixlar.registry.PluginRegistry, and mixlar.colors.* detect that mixlar_mini is already imported and transparently re-export the app's own live objects instead — same class, same registry, same palette — so a plugin written against this SDK needs zero changes to run for real, and push_widget_data reaches the actual serial link. This "single source of truth" seam is documented in each module's docstring and in docs/migration.md.

Package trust works the same way both places: mixlar.signing.package_digest computes the exact SHA-256 the app's _plugin_package_digest computes, so a package signed with this SDK verifies in the real app. See docs/signing-and-packaging.md.

Documentation

Start at docs/index.md. Highlights:

A complete worked example — a Pomodoro timer plugin with macros, a settings schema, and a bundled countdown widget — lives in examples/pomodoro/.

For the underlying specs this SDK implements, see the repo root's PLUGINS.md (package format, install/trust flow) and WIDGETS.md (widget spec, serial protocol).

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mixlar_sdk-0.2.0.tar.gz (109.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mixlar_sdk-0.2.0-py3-none-any.whl (93.3 kB view details)

Uploaded Python 3

File details

Details for the file mixlar_sdk-0.2.0.tar.gz.

File metadata

  • Download URL: mixlar_sdk-0.2.0.tar.gz
  • Upload date:
  • Size: 109.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for mixlar_sdk-0.2.0.tar.gz
Algorithm Hash digest
SHA256 8ec2dac9978bd41bdd5b47ad73d778ea0e2481e8ea1bba1142f6becbaf063dcf
MD5 bfeeb1fc700ce8a29c94769e3f41f46a
BLAKE2b-256 259471f7125bec874da6bb7df7c8dae89a099abc1f403b970879bd0dc556265f

See more details on using hashes here.

Provenance

The following attestation bundles were made for mixlar_sdk-0.2.0.tar.gz:

Publisher: publish.yml on MixlarLabs/mixlar-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mixlar_sdk-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: mixlar_sdk-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 93.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for mixlar_sdk-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5ad7819328dcc68ad175e50de679ef671e03572d96db6fa9e105e8825bdbfe62
MD5 62b3106cf753416df410b63febf9bdf2
BLAKE2b-256 02b4157f49ab3e8f9adcf6178364ac8cd9599dbc9516bff9de4a734077c5053e

See more details on using hashes here.

Provenance

The following attestation bundles were made for mixlar_sdk-0.2.0-py3-none-any.whl:

Publisher: publish.yml on MixlarLabs/mixlar-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.3.7

2 files

0.3.6

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

This release

0.2.0 This release

2 files

0.1.9

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page