The Maru bundle format
How .maru carries a release's processing, interface, assets and host requirements in one file.
A .maru file is a Maru bundle: one release in one portable file. It keeps
the processing, interface, presets and resources of a musical tool together,
so a compatible host can verify and load the same version wherever you use it.
Maru is consolidating processors of different types and sampler content around this shared format. Instruments, audio effects and MIDI tools bring their processing; sampler banks bring their recordings and mappings for a sampler host. The common envelope describes what is inside and what it needs to run.
Project, release and bundle
These are three forms of the work you build:
| Form | What it gives you |
|---|---|
| Project | Editable source, configuration and assets. This is where you develop the tool. |
| Release | A fixed version with its built artifacts, file digests and verification records. A published reference such as @handle/my-effect@3 names a particular release. |
| Bundle | That release's file tree transported as one .maru file. Extracting or repacking it preserves the release's identity. |
You can keep developing a project while an earlier release remains available. Sharing its bundle carries that specific result. See Publishing for the full workflow.
What is inside
The container is a ZIP archive with release.json at its root. That manifest
uses the maru-audio-release/v1 contract and describes the release's artifacts,
their files and digests, and its requirements. The payload depends on the tool:
- Programs contain built processing for the runtimes the release supports, such as JavaScript or WebAssembly.
- Faces contain the tool's interface and supporting files.
- Assets contain resources such as samples, impulse responses and sampler bank documents. Bank documents describe how recordings are mapped and played.
- Qualification records retain the checks associated with the built result.
- Source, when shared by the author, can accompany the release separately from the files used at runtime.
A representative layout looks like this; optional directories appear only when the release includes those artifacts:
release.json module.json browser-source.json ui/ programs/ adapters/ assets/module-v1/ artifacts/native/ qualification/ source/ # optional shared source
Presets remain settings for the module or bank they belong to. A rack composes references to musical tools and their connections. The shared envelope lets different kinds of content retain their own behavior and data contracts.
How a host knows it can play the release
The manifest's requires block declares the engine ABI, runtime line, optional
face API version and any required host capabilities. The host checks these
against what it provides. A tool that uses generation, for example, needs a
host that offers the declared generation service.
The engine, worklet runtime and FaceShell come from the host's runtime line. The release carries its own processing and resources while declaring the platform services it expects. A compatible envelope does not add a missing service or another processing target: the host must also support the included artifacts and the tool's needs.
Identity and verification
releaseSha256 is the SHA-256 digest of the exact release.json bytes. The
archive's own digest identifies the downloaded file; the release digest
identifies the release inside it. Repacking the same tree preserves the release
digest, and Maru's writer produces deterministic archive bytes for the same tree.
The reader validates declared file sizes and digests, artifact digests and manifest structure before exposing a read-only view of the runtime files. It refuses malformed paths, duplicate or case-colliding names, links, unsafe file modes, undeclared payload files and missing declared files. A failed check refuses the bundle as a whole.
These checks detect damaged or changed content. Publisher signature verification is separate work; the current bundle digests alone do not authenticate who created an archive. The ZIP container also does not encrypt the content.
Source and ownership
A bundle can include source/ when the release's sharing settings allow source
for the included parts. Runtime loading ignores that directory. A product-only
release carries the built product without an editable source subtree.
Your own project remains your editable working copy whether or not you include source in a distributed bundle. For someone else's release, the author's sharing settings and license determine access and permitted reuse. See Project structure and Licensing.
Building and using bundles today
To define the source project that builds into a bundle, follow Define a Processor module. It covers the authoring contracts and what to prepare for publication.
The qualified maru module build <project> workflow produces a release
directory and a deterministic <slug>@<version>.maru file, verifies the archive
and reports its identity. It needs the local toolchain and qualification inputs
described in Check, build and export. A prebuilt bundle can
be published with maru publish <file.maru> --no-source, preserving its release
bytes and recorded checks.
For an existing release directory, maru pack writes and verifies a bundle.
The CLI also accepts a local bundle for installation into the Maru plug-ins'
library:
maru pack ./my-release --out ./my-tool.maru maru install ./my-tool.maru
Use the release directory produced by the build for ./my-release. Installation
retains the release identity; playback still depends on the installed host's
requirements and supported artifacts.
Sampler banks already use the shared release model for asset delivery. Their
Studio import/export controls and host support are still being consolidated
around .maru; use Sampler banks for the
available workflow. The bundle reader and writer exist today; file opening,
installation and playback availability depend on the particular host.
Start by building the tool or bank you want to make. Use its release's listed formats and the destination host's capabilities to choose where to take it.