Marketplace extension
Publishing puts your extension in the catalog every WAMP install browses, under a slug you own from then on. This page covers what has to be true of your manifest first, what actually gets uploaded, and the parts of the model that surprise people — chiefly that catalog scoping is curation and not access control.
Before you publish
Section titled “Before you publish”Three manifest facts are checked, and two of them are checked only by the catalog, so an extension that runs on your machine can still be rejected.
| Requirement | Where it is enforced |
|---|---|
engines.wamp — a semver range such as "^12.0.0" |
required by the catalog; optional to the host |
version — exactly MAJOR.MINOR.PATCH |
required by the catalog |
| The slug is your extension’s id — its directory name, lowercase kebab-case | the id is the address; the manifest has no separate slug field |
engines.wamp is worth being precise about, because its name suggests more than
it does. The catalog stores it and the listing displays it as Requires Wamp <range>, and that is all it does — no host compares its own version
against that range at install time. The range that is enforced is
compat.pluginApi: an extension whose declared plugin-API range does not match
the host refuses to activate, with the mismatch reported as the reason. Declare
engines.wamp because the upload demands it; declare compat.pluginApi if you
actually need a floor. Both are described in
The manifest.
Everything else the listing shows comes from fields you already have, with
defaults where you left them out: name (required), description (empty),
author (Wamp Team), icon (a Lucide icon name, Package), plus counts
derived from your contributes block. longDescription is optional Markdown and
becomes the overview on the detail page.
Publishing from inside WAMP
Section titled “Publishing from inside WAMP”This is the path that needs nothing but the app you already have.
- Sign in. The listing is owned by your account — that is what lets you update or withdraw it later, so publishing without a session is refused.
- Open the Marketplace view and find your app among your own.
- From its
⋯menu choose Publish. The host zips the app, uploads it, and the listing is live immediately.
Publishing again is how you ship an update: the catalog keeps one listing per slug and replaces its contents. Withdraw takes the listing out of the catalog without deleting it, so people who already installed the app keep their copy and keep getting update checks.
The name is the address. Once your account has published a slug, nobody else can publish under it, and there is no way to hand it over. If you intend to rename the app, rename it before the first publish.
What gets uploaded
Section titled “What gets uploaded”The package is not your working directory. One staging step decides its shape, and the same shape is what a branded product bundles, so an extension has one published form rather than one per destination.
An extension is classified as editable if it has no build script of its own
and does have source (a page entry point or a main-process entry point).
Editable apps ship their source — ui/, main/, shared/,
tsconfig.json, and CLAUDE.md / AGENTS.md if present — with no dist/,
because the host rebuilds them from source with its own bundler, and because a
recipient can then open and fork the app. Their runtime dependencies are
vendored into node_modules/ so that rebuild needs no npm on the user’s
machine.
Everything else is sealed and ships dist/ only — the built bundles are the
only JavaScript that runs.
Both forms additionally carry extension.json, a sanitized package.json with
scripts and devDependencies stripped, icons/, assets/, and the
declarative content per-component loaders read: .md and .json files under
agents/, skills/, commands/, prompts/, hooks/, and mcp/. Nothing
else is included. If a file you need at runtime is not in that list, it will not
be there after install.
The upload contract
Section titled “The upload contract”The in-app publish is one client of a plain HTTP endpoint. Use the endpoint directly if you are automating releases.
curl -X POST "https://api.vampikez.fun/marketplace/extensions/reading-list/upload" \ -H "Authorization: Bearer $WAMP_TOKEN" \ -F "version=1.2.0" \ -F "file=@reading-list.zip;type=application/zip"version must precede file. The storage key is chosen while the bytes are
still streaming — before anything can read the manifest inside the zip — so a
version field that arrives after the file is not seen, and the package lands
under 1.0.0.
Authorization: Bearer takes a signed-in WAMP account token; that account
claims the slug on first publish and owns it afterwards. The zip must contain
extension.json at its root, and must be under 500 MB.
| Response | Meaning |
|---|---|
200 with { success: true, item } |
published; the catalog cache is invalidated, so the listing is visible at once |
400 ZIP must contain extension.json at root |
you zipped the parent directory |
400 Manifest failed validation: … |
a schema failure, most often a missing engines.wamp or a non-X.Y.Z version |
401 Sign in to publish an extension |
no credential |
403 The slug "…" belongs to someone else |
the slug is taken |
Re-uploading the same version is allowed and overwrites the stored package. The catalog keeps no version history — one row per slug, one version column — so there is nothing to roll back to. Keep your own build artifacts.
contributes and products do less than they look like
Section titled “contributes and products do less than they look like”contributes is your declaration of what the extension adds — views, pages,
agents, tools, MCP servers, project templates, and the rest. For the catalog it
does two things: the counts drive the badge and the “primary contribution”
facet, and the full manifest is served on the detail page so a visitor can see
what they are installing. It grants nothing. What each contribution means at
runtime is the host’s business, described in
Extensions and apps.
One divergence to know about: the catalog accepts and counts a
contributes.tools array, and the host ignores it. Tools are registered in code
at activation — see Contributing tools — so declaring them in
the manifest changes the badge and nothing else.
products is an array of product slugs, and it scopes which catalogs list
your extension. Absent or empty means every catalog lists it; ["forge"]
means only a product whose id is forge shows it while browsing.
That is curation, not access control. The scope is applied to one query — the
browse listing — and only when the request names a product. The detail route,
the manifest route, and the download route consult products nowhere, and the
download route does not even require a signed-in account. Anyone who knows the
slug can fetch and install a listing that no catalog shows them. Do not use
products to keep an extension private.
What publisher identity is today
Section titled “What publisher identity is today”Honest state, because it decides whether the catalog fits your plans:
- Ownership is first-come. The first account to publish a slug owns it. There
is no publisher namespace — listings are
reading-list, notyou.reading-list— so the global slug space is the only namespace, and renaming means claiming a second slug. - The operator can publish anything. A build-time admin token bypasses ownership; that is how the curated first-party catalog is maintained.
- There is no review queue and no signing. A published listing is live immediately, and what a user installs is whatever bytes you last uploaded.
- There is no transfer, and no per-listing collaborator. One account, one slug, forever.
After it is published
Section titled “After it is published”Users find your extension in the Marketplace view inside WAMP and install it there; the host fetches a presigned download of the package and installs it the same way it installs a sideloaded extension. Your listing carries the permissions your manifest declared, and the user sees them before installing — which is the main reason to declare no more than you use. See Permissions.
If your extension turns out to want its own window, its own name, and its own installer rather than a place inside WAMP, that is the next page: Branded desktop product.