Building

Publishing

Drafts, immutable versions, private-first listing, yanking, and how installs follow updates.

View as Markdown

The path from code to installs

Save draft  →  Publish x.y.z  →  (private: only your account)  →  List in Browse  →  anyone can install
                     ↑                                                    ↓
                  next version  ←───────────  installs on "Latest" follow (with consent for new access)
  1. Create the plugin. Plugins → Created → Upload a plugin takes a .zip: the readme's name (and optional slug) creates it for you. Write in the browser asks for a name, an address (the slug) and a one-line description. The slug (lowercase letters, digits, hyphens and underscores, up to 64 characters, not starting with agentparley- or mcp_) is your plugin's permanent identity; tool names are prefixed with it.
  2. Draft (optional): Save (⌘S) in the editor builds and validates exactly like a publish but takes no version number. Your saved draft reopens on any device. Switch your own install to it with Use my draft on the Try it tab to test on your account.
  3. Publish a version: Publish… in the editor (choose patch, minor or major; the first is 1.0.0), or upload a .zip — on the Created page, or Working on your own computer? on the plugin's page. A zip's readme version: decides the number (see Versions below). The editor only sends text files, so a plugin with models, images or several script files shows Upload a .zip… in place of Publish…. A plugin with a gallery can still publish from the editor: the gallery you manage on the Store page tab goes with it.
  4. List in Browse (in the ⋯ menu at the top of the plugin's page) when you're ready for everyone: requires at least one published version.

What a publish does

In one step, all or nothing:

  1. Checks every file fits the package format and requires a readme.md.
  2. Bundles your code with esbuild into one readable script.
  3. Runs it once to discover its capabilities and manifest; derives permissions from its host.* calls.
  4. Validates the manifest, tools, commands, skills and companion assets.
  5. Stores the version. A crash half-way leaves no half-visible version.

A readme-only package is refused too ("version declares no capabilities"): it needs at least one command, skill, code capability or companion/portrait folder.

Any problem fails the publish with a message naming the file, key or line: "tool 'Lookup' must match ^[a-z][a-z0-9_]{0,63}$", "unknown globalThis.manifest key 'egres'", "the code calls host.fetch but declares no egress hosts", "a decision provider must implement modelProvider.noul, choose and score together".

If the platform is busy bundling other plugins you may get a retry shortly response — just publish again.

Versions

  • A version is major.minor.patch, digits only (1.0.0, 1.4.12). The first publish from the editor is 1.0.0.
  • Versions are immutable. Publishing the same number twice is refused. Fix forward with a new version.
  • Installs on Latest follow the highest published version.

Use the numbers the usual way: patch for fixes, minor for additions, major for anything that breaks users — a renamed setting, a removed tool.

The version: key in readme.md (<major>.<minor> only, default 1.0) is used whenever you upload a zip to POST /plugins/upload (the console's zip uploads) and by the official-plugin pipeline. The platform picks the patch automatically: unchanged files publish nothing, changed files publish the next patch, a raised major.minor publishes <major>.<minor>.0, and a lowered one is refused. When you publish from the editor's Publish… or through POST /plugins/{id}/versions or …/versions/zip, you choose the number and this key is ignored.

Visibility

State Who can find and install it
Private (default) only your account — Browse shows it to you with a Private tag
Listed in Browse every AgentParley account

Remove from Browse takes it off the catalog: accounts that already installed it keep working on their version and see the optional message you write ("Why you're taking it down"). You can list it again later.

How installs follow your updates

Each install has a version policy:

Policy Behaviour
Latest (default) moves to your newest version within about five minutes
Pinned stays on one version until the user changes it
Draft your own account only: follows your latest draft

New access waits for consent. If a new version asks for anything the owner hasn't agreed to — a permission, an egress host, an agent in manifest.agents, a schedule in manifest.schedules, a failClosed hook, or channelSenderPolicy: "anyone" — installs stay on the old version and show Update waiting for your OK, listing exactly what the new version adds. Nothing from the new version runs until they accept. A version that asks for the same or less moves silently.

On every version change your plugin receives events.pluginUpdated — see Lifecycle events.

Yanking

Pull a bad version with yank (on the version in the console, or the API). A yanked version stops being offered: installs on Latest move to the highest remaining version they have already agreed to, and an install pinned to it has no version to run until its owner picks another. You can't yank a plugin's last remaining published version. A plugin that has ever published a version, even a yanked one, can't be deleted; only a plugin that never published can. To take a published plugin out of sight, use Remove from Browse.

Official plugins

Plugins with the Official badge — Brave Search, Caveman, DC Portraits, DevOps on-call, Discord, Google Workspace, Inbox Triage, Microsoft 365, Morning Briefing, My Dude, Ponytail, Sales Lead Crew, Wiki Web and Yuzuki — are published by AgentParley from its own repository as agentparley-<name>, through the same bundling, validation and SDK described here. Community slugs can't start with agentparley-.

Checklist before you list

  • The readme explains setup, every setting, and what the plugin reaches.
  • npx tsc -p . passes against the downloaded SDK types.
  • You tested the published version on your own account, including a fresh install.
  • Lifecycle handlers are idempotent; middleware is fast; tool descriptions say when to use the tool.
  • You call host.* literally (no aliases), so the permission list is complete.
  • Nothing secret is stored in live-connection state or logged with host.log.