macrodeck-plugin run
Launches a plugin as a child process with the environment the supervisor would give it, and streams its output live.
Examples
Section titled “Examples”macrodeck-plugin run --project src/HelloDeck --stub-hostStarted a disposable stub host at http://127.0.0.1:49789.Started process 18593 (mode: SelfRegistering, host: http://127.0.0.1:49789). Press Ctrl-C to stop.[plugin] info: Microsoft.Hosting.Lifetime[14][plugin] Now listening on: "http://127.0.0.1:49790"...[plugin] info: MacroDeck.Plugin.Hosting.Transport.PluginConnectionHostedService[0][plugin] Registered with the host as '"com.example.hello-deck"'.Session established (negotiated plugin protocol v3).[plugin] info: HelloDeck.PluginIntegration[0][plugin] Initialized.[log:information] HelloDeck.PluginIntegration: Initialized....^CStopping the plugin...The plugin did not exit within its 10s grace period; killing it.An isolated loop with no Macro Deck installed. The stub is a real in-process MacroDeckTestHost, not a
mock.
macrodeck-plugin run --project src/HelloDeckAgainst the running Macro Deck. Approve the pairing prompt that appears in Macro Deck - see Pairing with a real host.
macrodeck-plugin run --project src/HelloDeck --watchAgainst the running Macro Deck, rebuilt on every save. Leave a developer preview open and it follows along - see Watching for changes.
macrodeck-plugin run --artifact ./artifacts/com.example.hello-deck-1.0.0-osx-arm64.macroDeckPlugin --stub-hostRun exactly what you packed, rather than the Debug build.
macrodeck-plugin run --project src/HelloDeck --stub-host --mode managedReproduce a managed (supervisor-launched) plugin. Managed mode works only against the stub.
macrodeck-plugin run --executable ./bin/Debug/net10.0/HelloDeck.dll --host-url http://127.0.0.1:5000An already-built executable or framework-dependent .dll, against a host you name explicitly.
For breakpoints, child-process attach and the direct-project launch against a desktop host, see Debugging plugins.
Options
Section titled “Options”Exactly one of --project, --executable or --artifact is required.
| Option | Default | Description |
|---|---|---|
--project <path> |
- | A plugin’s .csproj, or its directory. |
--executable <path> |
- | An already-built executable or framework-dependent .dll. |
--artifact <path> |
- | A packed .macroDeckPlugin artifact. |
--host-url <url> |
the running host | A real host’s URL; cannot be combined with --stub-host. |
--stub-host |
off | Run against a disposable in-process stub host. |
--mode <managed|self-registering> |
self-registering |
Registration mode; managed needs --stub-host. |
--pairing <true|false> |
true |
Self-registering only: let interactive pairing supply the credential when no token is given. |
--enrollment-token <token> |
placeholder on the stub | Self-registering only: required against a real host when --pairing false. |
--plugin-id <id> |
the manifest’s id |
Managed only: the injected plugin id. |
--secret <secret> |
generated on the stub | Managed only. |
--state-directory <dir> |
temp dir | Self-registering only: where the persisted credential is stored. |
--data-directory <dir> |
temp dir | Managed only. |
--instance-id <id> |
fresh id | Both modes. |
--launch-id <id> |
fresh id | Managed only, diagnostic; never asserted on the wire. |
--listen-url <url> |
http://127.0.0.1:0 |
Where the plugin listens; port 0 lets the OS pick. |
--watch |
off | With --project against a real host: run the plugin under dotnet watch. See Watching for changes. |
Temp directories run created itself are deleted when it exits.
Which host run uses
Section titled “Which host run uses”macrodeck-plugin run --project src/HelloDeck --host-url http://127.0.0.1:5000 # this hostmacrodeck-plugin run --project src/HelloDeck --stub-host # no discovery at all- The running Macro Deck host is the default. While it runs, the host writes the loopback port it
bound to
macro-deck-host.port(ormacro-deck-host-development.portfor a Development build) in the system temp directory, and deletes it on exit.runreads it and points the plugin athttp://127.0.0.1:<port>- the same URL the supervisor injects asMACRO_DECK_PLUGIN_HOST_URL. - Both names are probed. If a Development and a Production host run side by side, the most recently written port file wins - the host you started last.
- No readable port file fails with
host-not-found(exit 3).runnever falls back to the stub silently.
Watching for changes
Section titled “Watching for changes”macrodeck-plugin run --project src/HelloDeck --watch--watch runs the project with dotnet watch run, using the environment run composes:
- A saved change that .NET Hot Reload supports - a new text, a changed layout, a different mock value in a preview scenario - is applied to the running plugin. Open developer previews are rebuilt in place, without a restart, and the plugin’s other open views, such as widgets and configuration editors, are opened again with the new code. See Real views.
- Any other change rebuilds the project and restarts the plugin. Macro Deck keeps the open preview on screen, marked as waiting, and reopens it when the plugin is back.
The plugin runs from the project directory, like dotnet run, and ignores launchSettings.json so a profile
cannot point it at another host or state directory. The state directory is kept for the whole command, so you
pair once per run --watch; pass --state-directory to keep the credential across runs.
--watch needs --project (watch-needs-project, exit 2) and a real host (watch-needs-real-host, exit 2):
the stub host has no previews to follow the plugin.
Bundled icon packs
Section titled “Bundled icon packs”A self-registered session against a real host brings the host’s copy of the plugin’s
bundled icon packs in line with manifest.json when the session
starts: packs are added, replaced or removed by key, so the icons are in the icon picker and on buttons
without installing the plugin.
With --watch, run also watches icon-packs/ and the manifest’s bundledIconPacks. An
icon-pack add or remove, or a replaced pack file, is synced right away without
restarting the plugin, buttons re-render with the new icons, and open plugin views reload.
- Only self-registered sessions sync. Nothing is synced against
--stub-hostor in managed mode. - A pack larger than 8 MiB cannot be synced live. Build and install the plugin to try it.
runasks the plugin to sync throughMACRO_DECK_PLUGIN_BUNDLED_ICON_PACKS(sync, orwatchwith--watch). A host that predates bundled icon packs answers that it does not support them, and the plugin runs on without them.- With
--project,runalso setsMACRO_DECK_PLUGIN_BUNDLED_ICON_PACKS_ROOTto the project directory, so the packs are read from the project even though the plugin runs from its build output.
Pairing with a real host
Section titled “Pairing with a real host”self-registering is the default, and the only mode a real host accepts. A managed launch needs a
launch bootstrap token that only a real supervisor can mint, so --mode managed without --stub-host
fails with managed-needs-stub-host (exit 2).
With pairing on (the default) and no token, run asks the host whether pairing is available and reports:
| Diagnostic | Meaning |
|---|---|
developer-mode-disabled |
Developer Mode is off, so no prompt can appear. run keeps going; the plugin pairs as soon as you turn it on, with no restart. |
pairing-prompt-expected |
The host could not be asked (unreachable or too old). A prompt is expected but not guaranteed. |
| (neither) | Developer Mode is on; a prompt will appear. |
Once a request is pending, the plugin writes Waiting for pairing approval in Macro Deck... to stderr,
and reports the outcome the same way after you approve or reject it.
Using an enrollment token instead
Section titled “Using an enrollment token instead”macrodeck-plugin run --project src/HelloDeck --pairing false --enrollment-token <token>$ macrodeck-plugin run --project src/HelloDeck --pairing falseerror enrollment-token-required: --mode self-registering against a real host needs --enrollment-token when --pairing is off.The environment run composes
Section titled “The environment run composes”Every inherited MACRO_DECK_PLUGIN_* variable and ASPNETCORE_URLS is scrubbed, then set fresh for the
resolved mode, mirroring
what the supervisor injects.
Against a real host in self-registering mode run also sets MACRO_DECK_PLUGIN_BUNDLED_ICON_PACKS (see
Bundled icon packs), which the supervisor never sets.
In managed mode, MACRO_DECK_PLUGIN_ID comes from the manifest.json next to the launch target, because
the host rejects an injected id that disagrees with the manifest. --plugin-id overrides it. Only when
neither exists does run generate a development id, and it warns:
warning plugin-id-generated: No manifest.json next to the launch target, so a development id was generated. ...Output
Section titled “Output”[plugin]lines are the plugin’s stdout and go torun’s stdout;[plugin:stderr]lines go to stderr.[log:...]lines are the stub host’s forwarded logs.--verbosity quiethides[log:...]lines and progress narration. The plugin’s own output always prints.
Stopping
Section titled “Stopping”Ctrl-C runs the supervisor’s shutdown sequence against the stub host:
session.goodbye.- Close with code
4004(SupervisorShutdown). - Wait for the manifest’s
shutdown.gracefulTimeoutSeconds(clamped to 1-60s; 10s if absent). - Kill the process tree if it is still running.
Against a real host, run owns no session to say goodbye on, so only steps 3 and 4 apply.
Exit codes
Section titled “Exit codes”| Code | When |
|---|---|
| the plugin’s own | The plugin exited on its own. |
| 2 | Usage error: wrong number of launch targets, --host-url with --stub-host, managed-needs-stub-host, enrollment-token-required, watch-needs-project, watch-needs-real-host. |
| 3 | host-not-found, a project that fails to build, an unreadable artifact, or a process that fails to start. |
| 4 | Ctrl-C, whether the plugin exited gracefully or had to be killed. |
See the shared exit codes.
See also
Section titled “See also”- Debugging plugins - breakpoints, IDE profiles, enrollment tokens.
- Plugin hosting - registration modes and every
MACRO_DECK_PLUGIN_*variable. macrodeck-plugin test- the conformance suite, against the same stub host.