# List your repository on Maru

> Add one file, .maru/listing.json, to a plugin or firmware repository so Maru lists it under your name, with your README, screenshots and release downloads. What the file does, every field, how to publish it yourself, and how Maru Desktop installs a plugin built with another framework.

Canonical: https://maru.audio/docs/repository-listing
Documentation index: https://maru.audio/llms.txt

Add one file to your repository, `.maru/listing.json`, and Maru lists your plugin or firmware under your GitHub name, with your README and screenshots. You keep your code, releases and downloads where they are. Maru reads the file, links to your releases, and keeps stars and versions current.

You don't need to build anything with Maru. The file works for any plugin (VST3, CLAP, AU, LV2 and others), whether you publish its source or only its release files, and for firmware for a music device. Maru can list a repository without you having a Maru account, for example after it proposes the file to your project. To publish the listing yourself and manage it, you sign in to Maru with the GitHub account that owns the repository.

> **In the Help Center:** [List a plugin built with another framework](https://maru.audio/help/list-a-plugin-built-elsewhere.md) for deciding between a listing and rebuilding your plugin with Maru.

## What the file does, and doesn't

The file does three things:

- **It asks for a name.** Your listing lives at `@your-login/slug`, for example `/plugins/@asb2m10/dexed`. The `@your-login` part always comes from the account that owns the repository, never from the file.
- **It lets Maru show your README and images.** Without it, Maru shows only facts GitHub publishes, such as the description, licence, stars and latest release, and links to the README on GitHub.
- **It tells Maru what you ship.** Plugin formats, platforms and the compatibility you declare, or the devices your firmware runs on, mapped to your release files.

The file can't set an owner, a verified badge, tested compatibility or a price, and it can't make Maru build or sign your downloads. It adds no build step, dependency, telemetry or licence change.

## Create the file

With the Maru CLI (a version that includes `maru listing`), from your repository's root folder:

```bash
maru listing init --family plugins --kind effect
maru listing check
```

For firmware, add the exact device ID from the [hardware directory](https://maru.audio/hardware):

```bash
maru listing init --family firmwares --device fm-1
```

`init` fills in only what your checkout shows: the name, your GitHub login from the `origin` remote, a licence it can recognise for certain, README images, and the CPU architectures a plug-in bundle or a file name shows (`arm64`, `x64` or `universal`). It never replaces an existing file. Read the draft, change what's wrong, then commit it.

You can also write the file by hand. Point `$schema` at the published schema and your editor completes keys and flags mistakes:

```json
{
  "$schema": "https://maru.audio/schema/repository/listing/alpha.json",
  "format": "maru-listing/v1",
  "listings": [
    {
      "family": "plugins",
      "slug": "tape-echo",
      "name": "Tape Echo",
      "summary": "A warm tape delay with wow, flutter and saturation.",
      "kind": "effect",
      "license": "GPL-3.0-or-later",
      "readme": { "path": "README.md" },
      "media": [{ "path": "docs/screenshot.png", "alt": "The main panel", "role": "cover" }],
      "plugin": {
        "formats": ["vst3", "clap", "au"],
        "releaseAssets": [
          { "match": "TapeEcho-*-macOS.zip", "platforms": ["macos"], "formats": ["vst3", "clap", "au"] },
          { "match": "TapeEcho-*-Windows.zip", "platforms": ["windows"], "formats": ["vst3", "clap"] }
        ]
      }
    }
  ],
  "display": { "readme": true, "media": true }
}
```

## Fields

Only `format`, `family` and `slug` are required. Anything you leave out comes from GitHub, or stays unknown.

| Field | What to put |
| --- | --- |
| `format` | Always `"maru-listing/v1"` |
| `listings` | One entry per plugin or firmware, up to 20. A repository with several plugins, or firmware and an editor, has several entries |
| `family` | `plugins` or `firmwares` |
| `slug` | The name in your address: 2 to 80 lowercase letters, digits and single hyphens |
| `path` | The subfolder for this entry, when the repository holds several |
| `name`, `summary` | Up to 80 and 200 characters, on one line |
| `kind` | Plugins: `instrument`, `effect`, `midi-tool`, `app` or `game`. Firmwares: `firmware`, `on-device-app`, `controller-app`, `editor`, `daw-integration`, `source-release` or `sound-content` |
| `tags` | Up to 12 lowercase words, such as `delay` |
| `license` | An SPDX expression, such as `MIT` or `GPL-3.0-or-later`, or `LicenseRef-` and a name for your own licence. Shown beside the licence GitHub detects |
| `readme` | `path` of the README to show, and optionally `"section": "maru"` |
| `media` | Up to 12 images, as repository paths or HTTPS links, each with `alt` text and a `role` of `cover`, `screenshot` or `demo` |
| `video` | One HTTPS link to a demo |
| `links` | HTTPS links: `homepage`, `documentation`, `support`, `donate` |
| `credits` | People to credit, by GitHub login, with a role: `owner`, `maintainer`, `author`, `contributor`, `porter` or `designer` |
| `basedOn` | Projects this one forks, ports or was inspired by: `{ "repository": "github:owner/repo", "relation": "fork" }` |
| `plugin` | `formats` and `platforms` you ship, and the `plugin` fields below |
| `plugin.framework` | What the plugin is built with: `juce`, `iplug2`, `dpf`, `cmajor`, `faust`, `rust` or `other`. Shown as a credit, such as "Built with JUCE" |
| `plugin.compatibility` | Per platform, such as `macos` or `windows`: `minVersion` (`11`, `11.0` or `10.15.7`), `architectures` (`arm64`, `x64`, `universal`) and `signing` (`unsigned` or `signed`, or `notarized` on macOS) |
| `plugin.hosts` | Up to 12 DAWs: `name`, optional `version`, a `status` of `tested`, `reported` or `known-issue`, and an optional one-line `note` |
| `plugin.install` | `method`: `archive` (unzip and copy the bundles), `installer` (your pkg, dmg, exe or msi), `download` (a plain file) or `build-from-source`. Optional HTTPS `url`, and `notes` in one paragraph of up to 400 characters |
| `plugin.releaseAssets` | Maps release file names to what they hold: `match` (`*` matches any text, such as a version), `platforms`, `formats`, and optionally `architectures` (left out means unknown, not universal), a `minVersion` for that file and a `kind` |
| `plugin.releaseAssets[].kind` | `bundle-archive` (an archive of plug-in bundles, the only kind Maru Desktop installs, as a `.zip`), `installer`, `source` or `other`. Left out, `.zip` and `.tar.gz` files count as bundle archives, and `.pkg`, `.dmg`, `.exe` and `.msi` files as installers |
| `plugin.releases` | Which GitHub releases count: `channel` `stable` (the default) or `all`, and a `tagPattern` such as `v*`. A GitHub prerelease is always a beta |
| `firmware` | `devices` (device ID, optional board revision and release file pattern) and `install` (`author-installer`, `download`, `build-from-source` or `maru-browser`, with an optional HTTPS link) |
| `display` | `readme`, `media` and `mirror`, each `true` or `false`. Leave out what you don't allow |

## Choose what Maru shows

`display` is your permission, and it defaults to nothing:

- `"readme": true` lets Maru show your README on your listing. Raw HTML in it doesn't run, and images in it aren't shown unless you list them in `media`.
- `"media": true` lets Maru show the images in `media`.
- `"mirror": true` lets Maru keep its own copy of those images, so your page doesn't depend on GitHub's image hosting. Leave it out and Maru links to your copies.

To show only part of your README, wrap it in markers and add `"section": "maru"`:

```markdown
<!-- maru:start -->
Tape Echo is a warm tape delay with wow, flutter and saturation.
<!-- maru:end -->
```

Maru reads the README and images at the exact commit it checked, so a later push doesn't change your page until Maru reads the repository again. Showing your README isn't permission to redistribute your release files: download links go to your releases.

## If something in the file is wrong

Maru keeps what it can use. An unknown field, or a field with a bad value, is ignored and the rest of the entry still counts. Only a file that isn't valid JSON, or has no valid entry, is ignored entirely, and the listing then shows GitHub facts only. `maru listing check` reports the same problems Maru would.

If your slug is already taken under your name, Maru doesn't overwrite the other entry. Choose another slug.

## Plugins built with other frameworks

A plugin you build with JUCE, iPlug2, DPF or your own code can be listed with its binaries, from a repository that holds only release files. Its page shows a download for each platform, the compatibility you declare and how to install it, and people with Maru Desktop can install it and receive your new releases as updates.

Maru doesn't review a listed plugin's source, and doesn't build, sign or test it. Its page and Maru Desktop say so: the files are a community release from your GitHub repository, and people download and install them at their own risk. The [Terms](https://maru.audio/terms) cover work other people publish on Maru. Clear install notes and an accurate signing state help people decide whether to install it.

Take Glass Hall, an example reverb built with JUCE and given away without its source. Its repository, `your-login/glass-hall-releases`, holds a README, screenshots in `images/`, a licence and a changelog. Its GitHub release `v1.0.0` has one file, `GlassHall-1.0.0-macOS-arm64.zip`, which unzips to `Glass Hall.vst3` and `Glass Hall.app`. It runs on Apple Silicon Macs with macOS 11 or later, isn't signed, and has been tested in Ableton Live 12.

### What to add

Add `.maru/listing.json` and nothing else. The README and screenshots are already in the repository; the file points at them and allows Maru to show them. Draft it with `maru listing init --family plugins --kind effect`, then complete it by hand:

```json
{
  "$schema": "https://maru.audio/schema/repository/listing/alpha.json",
  "format": "maru-listing/v1",
  "listings": [
    {
      "family": "plugins",
      "slug": "glass-hall",
      "name": "Glass Hall",
      "summary": "A bright hall reverb with a freeze switch and a shimmer octave.",
      "kind": "effect",
      "tags": ["reverb", "shimmer"],
      "license": "LicenseRef-GlassHall-Freeware",
      "readme": { "path": "README.md" },
      "media": [
        { "path": "images/panel.png", "alt": "The Glass Hall panel with its decay and shimmer controls", "role": "cover" },
        { "path": "images/freeze.png", "alt": "The freeze switch holding a chord", "role": "screenshot" }
      ],
      "links": { "support": "https://github.com/your-login/glass-hall-releases/issues" },
      "credits": [{ "github": "your-login", "role": "author" }],
      "plugin": {
        "framework": "juce",
        "formats": ["vst3", "standalone"],
        "platforms": ["macos"],
        "compatibility": {
          "macos": { "minVersion": "11.0", "architectures": ["arm64"], "signing": "unsigned" }
        },
        "hosts": [{ "name": "Ableton Live", "version": "12", "status": "tested" }],
        "install": {
          "method": "archive",
          "notes": "Unzip, move the VST3 to ~/Library/Audio/Plug-Ins/VST3 and the app to Applications. The build isn't notarized: allow it in System Settings, Privacy & Security."
        },
        "releaseAssets": [
          {
            "match": "GlassHall-*-macOS-arm64.zip",
            "platforms": ["macos"],
            "architectures": ["arm64"],
            "formats": ["vst3", "standalone"]
          }
        ]
      }
    }
  ],
  "display": { "readme": true, "media": true }
}
```

The `*` in `match` stands for the version, so the same pattern names the file in every later release. Run `maru listing check` and commit the file.

### Publish it

Publishing needs a Maru account with the GitHub account that owns the repository linked at [Connections](https://maru.audio/account/connections). That link is what makes the listing yours. For a repository owned by a GitHub organization, the file's `credits` on the default branch must name your GitHub login with the role `owner` or `maintainer`; committing the file there shows you can write to the repository. The organization's community page then owns the listing, and you manage it.

Then use one of these:

- **Website:** open [Repository listings](https://maru.audio/account/listings), choose **Add a repository** and enter `your-login/glass-hall-releases`. The result lists every problem the file had.
- **CLI:** run `maru login` once, then `maru listing publish` from your checkout. It reads the file first and stops, sending nothing, when the file is missing or can't be read; problems Maru would ignore are only noted, and `maru listing check` lists them. It finds the repository from your `origin` remote, and prints your listing's page and the releases Maru read.
- **CI:** an access token with only the `listings:publish` permission, saved as the `MARU_TOKEN` secret, and a workflow that runs `maru listing publish` each time you publish a GitHub release. [Publish a repository listing from CI](https://maru.audio/docs/publish-a-listing-from-ci.md) has the workflow.

Maru reads the repository at its current commit, records the listing, and records your releases: up to the 20 newest, each file with its size and the SHA-256 checksum GitHub recorded for it. Drafts are never read. Nothing is uploaded to Maru, and download links go to your GitHub releases.

### What your page shows

Glass Hall's page is at `/plugins/@your-login/glass-hall`. Beside the README and screenshots it shows:

- **Downloads.** A notice that the files are a community release, downloaded at the reader's own risk, then the newest stable release first, with a row for each file a `releaseAssets` pattern matched: its name, platform, architectures, formats, minimum system version, size and SHA-256, and a link to the file on GitHub. Files no pattern matched are listed under other files, and older releases are collapsed. Prereleases are betas and are shown only when `releases.channel` is `all`.
- **Compatibility, declared by the author.** Your `compatibility` and `hosts`, with the signing state in plain words: an unsigned or un-notarized macOS build says that macOS asks the person to allow it the first time.
- **Install.** Your `install` method and notes, and a link to your README on GitHub.
- **Open in Maru Desktop.** Shown when a release has a bundle archive for macOS, Windows or Linux, with a line saying that Desktop marks it as a community release Maru hasn't reviewed.

The header shows your licence and, with `framework` set, "Built with JUCE".

### What Maru Desktop does

Maru Desktop installs a bundle archive from your release, and only that kind of file: a `.zip` of plug-in bundles, on a Mac. It offers **Install** when the archive matches the Mac's architecture, or is `universal`. For every other file, and on Windows and Linux, it offers the download from GitHub and your install instructions.

Desktop labels the plug-in a community release on its page, and a community release not reviewed by Maru in the Library, the installed plug-ins and updates. Before anything downloads, Desktop says the plug-in comes from your GitHub release, not from Maru, that Maru hasn't reviewed, built or signed it and can't guarantee it's safe, and repeats the signing state you declared. The person confirms, and an update asks again. Desktop then downloads the archive, up to 512 MiB, and installs it only when it matches the SHA-256 GitHub recorded. A release file without a checksum on GitHub can be downloaded, not installed.

Desktop opens the archive without running anything in it and shows the `.vst3`, `.component`, `.clap` and `.app` bundles it will install, and where. It installs them in the usual plug-in folders and can remove them later like any other plug-in. Other files in the archive are named and left out.

Desktop never signs your build and never removes the quarantine mark macOS adds to downloads. An unsigned build still goes through macOS's own prompt the first time it opens, which is why your install notes should say how to allow it.

### How updates reach people

A new GitHub release reaches your page the next time Maru reads the repository: when `maru listing publish` runs, which the CI workflow does for each release, or when you choose **Read again** on [Repository listings](https://maru.audio/account/listings). Edits to the file arrive the same way, and a release you delete from GitHub disappears from the page.

When the newest stable release has an archive for their computer, Maru Desktop offers people who installed your plugin an update to that version. Updates never install on their own.

### What a listing can't do

A plugin listed this way has no browser preview, can't be loaded inside other Maru instruments, effects and racks, has no verified or tested badge, and has no downloads that Maru builds or signs. Those come from building the plugin with the Maru framework and [publishing](https://maru.audio/docs/publishing.md) it on Maru.

### Go further: build it with Maru

You can port a listed plugin to the Maru framework whenever you're ready, and the listing keeps working while you do. Building it with Maru adds:

- **A web demo.** People play the plugin on its page, in the browser, before they download anything.
- **Recomposition.** Other people can put it in a live rack or load it inside another module, with its controls and presets.
- **Remixing, when you release it open source.** People can fork the source and publish their own version, which keeps your credit. See the [Maru Remix License](https://maru.audio/docs/maru-remix-license.md).
- **Automated builds.** Maru builds the plug-in for each DAW format and operating system it supports, on its servers or in your CI, so you don't keep a build machine for each one. [Pricing](https://maru.audio/pricing) lists the plans with hosted builds, and [Build and publish a module in CI](https://maru.audio/docs/build-and-publish-in-ci.md) covers your own runners.

If the plugin relies on unusual technology, such as a custom machine-learning model, a video feed or other demanding processing, the Maru team works with you to sort it out. [Contact Maru](https://maru.audio/contact) with what the plugin does and what it depends on.

To start, [Porting an existing plugin](https://maru.audio/docs/constraints-for-plugin-developers.md#porting-an-existing-plugin) maps a JUCE plugin onto a Maru module, the [Quickstart](https://maru.audio/docs/quickstart.md) sets up a local project, and [Choosing Maru](https://maru.audio/docs/choosing-maru.md) compares the approach with other frameworks.

## Your address and your account

Your listing's address uses a Maru profile for your GitHub account, or a community page for a GitHub organization. Maru creates it the first time it lists one of your repositories, and uses your login as the handle when that's free. Until the owner has a handle, the page is at `/plugins/id/` followed by the listing's ID, the address `maru listing publish` and Repository listings show; that address keeps working afterwards. Renaming the repository keeps the listing. Transferring it to another account moves nothing until the new owner asks.

The first time you publish a listing while signed in with the same GitHub account, Maru moves the listings it already made for that account into yours, and their old addresses keep working. A repository whose listing belongs to another Maru account can't be published from yours; [contact Maru](https://maru.audio/contact) if that listing is wrong.

## Change or remove a listing

Edit and commit the file. Maru picks up the change the next time it reads the repository. To stop Maru showing your README and images, set `display` to `false` or delete the file. If you manage the listing, [Repository listings](https://maru.audio/account/listings) also lets you hide it, show it again or withdraw it. To have the listing taken down entirely, [contact Maru](https://maru.audio/contact) from the email on your GitHub profile, or ask in a GitHub issue on your repository that mentions the listing.

## If Maru opened a pull request

Maru sometimes proposes this file to projects it would like to list. The pull request adds `.maru/listing.json` and nothing else, and links to the page your project would get. Merging it agrees to the name and the display permission in the file; you can edit the file before or after merging. Closing it is a fine answer: Maru records that and never opens another one on your repository.
