Skip to content

Plugin CLI

macrodeck-plugin scaffolds, builds, checks, runs and packages a Macro Deck plugin without Macro Deck installed.

Terminal window
dotnet tool install --global MacroDeck.Plugin.Cli --prerelease
  • --prerelease is required until a stable 3.0 build ships: only -preview versions are published, and dotnet tool install skips prereleases unless asked.
  • The tool needs the ASP.NET Core shared framework, not just the .NET runtime, because run and test start a real Kestrel loopback host (via MacroDeck.Plugin.Testing). If they report that Microsoft.AspNetCore.App is missing, install the ASP.NET Core runtime or SDK.
Terminal window
macrodeck-plugin new --name "Spotify Controller" --publisher "Example Publisher" --yes
cd SpotifyController/src/SpotifyController
macrodeck-plugin run --project SpotifyController.csproj --stub-host
macrodeck-plugin build --output ../../artifacts
macrodeck-plugin validate --artifact ../../artifacts/com.example.spotify-controller-1.0.0.macroDeckPlugin

The artifact build (or pack) produces is what your publishing workflow submits to the Creator Portal, which signs it - see Publishing to the Store. There is no keygen or sign step on the way to the Store: those commands are for artifacts distributed outside the Store and for Macro Deck’s own infrastructure.

Command What it does
new Scaffold a plugin project from the official template.
build Build every runtime identifier the manifest declares and package the result.
validate Validate a manifest, a version directory or a packed artifact.
inspect Report what installing an artifact would find, without a running host.
pack Pack an existing payload directory into a .macroDeckPlugin artifact.
run Run a plugin against the running host or a disposable stub host.
test Run the conformance suite and write a text, JSON or Markdown report.
keygen / sign / verify Creator key pairs and package signatures, for artifacts distributed outside the Store.

Run macrodeck-plugin <command> --help for a command’s options.

These work on every command, before or after the command name:

Option Default Description
--verbosity <quiet|normal|diagnostic> normal How much a command narrates while it works.
--no-color off Disable ANSI colour in text output.

quiet hides progress lines only. A command’s result - a validation report, a conformance report, a plugin’s own console output, any error or warning line - always prints.

--output is not global. validate and inspect use it for a render format (text/json), pack and test for a destination file, and new, build and keygen for a destination directory.

$ macrodeck-plugin build
error manifest-not-found: No manifest at '~/src/SpotifyController/manifest.json'.
  • Failures print one line on stderr: error <kebab-case-code>: <sentence>, red unless --no-color is given.
  • Non-fatal observations (a missing foreign-RID entrypoint, a Debug-looking source tree, missing publication metadata) print the same way as warning <code>: <sentence>, also on stderr. A warning never changes the exit code.
  • validate is the exception: its error/warning lines are its result, so they go to stdout and validate ... > report.txt captures them.
  • Paths in messages are always resolved and absolute.

Running with no arguments prints the command list (exit 2). A mistyped command gets a suggestion when one command name is close, otherwise a pointer to --help:

$ macrodeck-plugin pakc --source .
error unknown-command: 'pakc' is not a macrodeck-plugin command. Did you mean 'pack'?
Code Meaning
0 Success, or conformant.
1 The subject is wrong: validation failed, or a required conformance check failed.
2 Usage error: bad arguments, an unknown --check/--category token, or an output file that already exists without --force.
3 The input could not be read: a missing file, something that is not a ZIP, or a permissions failure.
4 Cancelled (Ctrl-C).
70 An error the command did not anticipate.

1 and 3 are kept apart so CI can tell a broken plugin from a broken environment. run is the one exception on a normal exit: it returns the launched plugin’s own exit code.