Publishing a Module
Name a GitHub repo mutka-module-* and it's auto-discovered in the Modules catalog.
Mutka's in-app Modules catalog is backed by GitHub. There's no registry to
submit to and no approval step — a public repository is discovered
automatically as long as its name starts with mutka-module-.
The naming convention
mutka-module-<anything>The Modules overlay searches GitHub for repositories whose name begins with
mutka-module- (the search is mutka-module- in:name, sorted by stars). Any
public repo that matches shows up in the catalog — yours included, automatically,
once it's pushed.
Examples
mutka-module-git-status, mutka-module-image-tools,
mutka-module-s3 are all discoverable. A repo named my-mutka-plugin is
not — the name must start with the prefix.
The search box in the overlay appends your free-text terms to the prefix, and can
take GitHub qualifiers to narrow results (e.g. org:my-org).
What the repo must ship
When a user picks your repo, Mutka downloads the module's source straight from the repository's default branch. A repo ships its module in one of two ways:
1. A bare index.js at the root (single module)
The simplest case. Drop your built module at the repository root as index.js and
nothing else is required.
2. A mutka.config.json (one or more modules)
For built output in a subfolder, or to ship several modules from one repo, add a
mutka.config.json at the root listing the entry path(s) under projects:
{
"projects": ["sql/index.js", "webdav/index.js"]
}Each path is downloaded and installed as a separate module, and each shows up
as its own card in the catalog — a multi-module repo is not one lumped entry.
If no mutka.config.json is present, Mutka falls back to index.js at the root.
(The older { "modules": [{ "entry": "…" }] } form is still accepted.)
Card metadata — image & author
A module's catalog card (image, name, description, author) comes from its own
manifest, not from mutka.config.json. Set them in defineModule:
export default defineModule({
id: "ilian.sqlite-browser",
name: "SQLite Browser",
description: "Open and browse .sqlite files.",
icon: "data:image/png;base64,iVBORw0KGgo…", // or an https:// URL
author: { name: "Ilian", github: "ilianAZZ" }, // github = user OR org login
permissions: ["fs:read"],
// …
});iconis rendered with<img src>— use adata:URI (self-contained) or anhttps://URL. No raw HTML/CSS, so it's injection-safe.author.githubdrives the avatar and profile link. Omit it and Mutka defaults the author to the repo owner, so credit shows even with noauthorblock.
Validation, identity & consent
- Validated before install. Every entry is loaded in a throwaway Web Worker to confirm it's a real module that exports a valid manifest. A file that doesn't load is rejected, never written to disk.
- The manifest is the source of truth. The authoritative module ID comes from
the
idin yourdefineModule({ ... })manifest — not from the repo name. The install folder (~/.mutka/modules/<id>/) is named after it. - Permissions are shown up front. Before anything is written, the install
review dialog lists every permission your module declares, with dangerous ones
(
fs:write,network:public,network:local,secrets,clipboard:write,discovery,shell) flagged. The gateway still enforces those permissions at runtime regardless.
Checklist to get listed
- Build your module to a single ESM file (see Writing a module).
- Name the public GitHub repo
mutka-module-<name>. - Commit the entry as
index.jsat the root, or add amutka.config.jsonpointing at your entry path(s). - Push. It appears in the in-app Modules catalog — no submission step.
The catalog is a seam
GitHub is the catalog source of truth today. The underlying CatalogSource
interface is designed so a future source (a curated DB of links, a private
registry) can replace it without changing how modules are written or installed.