Skip to content

macrodeck-plugin build

build builds every runtime identifier your manifest declares and packages the result into one .macroDeckPlugin, using the same packer as pack.

Terminal window
cd ~/src/SpotifyController/src/SpotifyController
macrodeck-plugin build --output ../../artifacts
Building linux-x64...
Building osx-arm64...
Building win-x64...
Built linux-x64, osx-arm64, win-x64.
Packed com.example.spotify-controller 1.0.0 -> ../../artifacts/com.example.spotify-controller-1.0.0.macroDeckPlugin (1041 entries, 342566393 bytes uncompressed).

A full multi-platform package. Run it from the directory holding manifest.json.

Terminal window
macrodeck-plugin build --rid osx-arm64 --output ../../artifacts
Building osx-arm64...
Built osx-arm64.
Packed com.example.spotify-controller 1.0.0 -> ../../artifacts/com.example.spotify-controller-1.0.0-osx-arm64.macroDeckPlugin (...).

One platform only. Use it in a CI matrix job.

Terminal window
macrodeck-plugin build --source src/SpotifyController --output artifacts --force

Build from the repository root and overwrite the previous artifact.

Option Default Description
--source <dir> . The plugin project directory.
--manifest <path> <source>/manifest.json The manifest that decides which runtime identifiers to build.
--build-config <path> macrodeck-build.json beside the manifest The build recipe.
--rid <rid> all declared Build only this runtime identifier, which the manifest must declare.
--output <dir> . Directory for the artifact, unlike pack --output, which is a file path.
--force off Overwrite an existing artifact.

The artifact is named <id>-<version>.macroDeckPlugin, or <id>-<version>-<rid>.macroDeckPlugin with --rid.

manifest.entrypoints decides what to build; macrodeck-build.json decides how.

  • A runtime identifier declared in the manifest without a matching target fails with target-not-configured - a declared platform is never skipped.
  • Each target runs in turn: its executable with its arguments as a vector, never through a shell, so spaces, quotes or $HOME reach the tool exactly as written.
  • The CLI does not know which platforms a machine can build. Every requested target is attempted, and a missing or failing toolchain is reported with the runtime identifier and the tool’s stdout and stderr.
  • Whether the output is Release or Debug is up to the recipe; the generated one publishes Release. (pack’s source-looks-like-debug-build warning cannot fire here, because build packs a temporary directory.)
manifest.json
runtimes/win-x64/MyPlugin.exe
runtimes/osx-arm64/MyPlugin
runtimes/linux-x64/MyPlugin
assets/icon.png
{
"version": 1,
"include": ["assets", "data/defaults.json"],
"targets": { "...": {} }
}
  • Each target’s output is staged under the directory its entrypoint declares, so identically named macOS and Linux executables do not overwrite each other.
  • Besides that output and manifest.json, the package holds only the file the manifest’s icon names and whatever the recipe’s include lists, each at its project-relative path.
  • An include entry is a file or directory relative to the project root and must stay inside it; one that does not exist fails with build-config-invalid.
  • Never packaged, not even inside an included directory: project and source files (*.csproj, *.sln, *.cs, *.resx, Properties/, dotfiles and the like), macrodeck-build.json, each target’s output directory, the --output directory, bin/, obj/, node_modules/ and any .macroDeckPlugin file.
  • A declared path one of these rules drops is named in an include-not-packaged warning, and every other file beside the manifest that was left out in a file-not-packaged warning, so a forgotten asset never disappears silently.
  • An --output directory inside the project, such as . or ./artifacts, is safe to build into repeatedly.
  • Staging happens in a temporary directory outside your project, removed when the command finishes.

Every requested runtime identifier must produce its declared entrypoint, or the build fails with entrypoint-missing (where pack only warns). This catches a manifest declaring a Windows .exe while the recipe produces a framework-dependent .dll.

A full build checks every declared runtime identifier; --rid win-x64 checks only win-x64, so a matrix job is not failed by platforms it never built.

A --rid artifact’s manifest declares only that runtime identifier, so it never claims platforms the job did not produce. The CLI does not merge per-runner artifacts; for one package covering every platform, run a full build on a machine that can build them all.

  • Never signs. The package is unsigned, needs no key, and any signature and files[] in the project manifest are dropped. files[] is recomputed from the staged bytes. Signing is sign or the Creator Portal.
  • Fills in languages. languages is derived from Localization/*.resx: an unsuffixed Strings.resx counts as en, and each culture-suffixed sibling adds its BCP-47 tag. pack cannot do this, because its payload no longer contains the project tree. See the localization guide.
  • Warns about publication readiness. Every unsatisfied field at the publication requirement level (for example a missing description or publisher) is a publication-metadata-missing warning. It never fails the build, and there is no --level flag to turn it off.
$ macrodeck-plugin build --rid win-arm64
error rid-not-declared: The manifest does not declare 'win-arm64'. Declared runtime identifiers: linux-x64, osx-arm64, win-x64.
Code When
0 The artifact was written.
1 A build failed, or the manifest, build configuration or result does not match what the manifest declares.
2 A --rid the manifest does not declare, or an artifact that already exists without --force.
3 The source, the manifest, the build configuration or the build tool could not be found.
4 Cancelled (Ctrl-C).
70 Staging failed.
  • new - scaffold a project with a ready macrodeck-build.json.
  • pack - package output you built yourself.
  • validate - check the artifact build produced.
  • Manifest reference.