AiHummer docs
v1.0.x
RU EN

Publishing a plugin

v1.0.x · updated 2026-06-27

Built a plugin with the Plugin SDK? You can publish it in two modes:

  • Private (for yourself) — side-load into your instance. The artifact never leaves it.
  • Public (for everyone) — submit to the curated official AiHummer catalog via a PR.

Analogy: installing a .vsix by hand (private) vs publishing to the VS Code Marketplace (public); a private npm registry vs the public one.

Private mode — side-load into your instance

Use this when only you need the plugin: an internal connector, a custom integration, a test build.

Steps

  1. Package and sign the bundle:
    aihummer plugin package ./my-plugin
    aihummer plugin sign --key author.key --manifest ./my-plugin/manifest.json my-plugin-1.0.0.tar.gz
  2. Upload it to the instance one of two ways:
    • Admin UI → Plugins → “Upload plugin” — drag the bundle; or
    • CLI:
      aihummer plugin publish --private --instance https://your-instance \
        --token <admin-token> my-plugin-1.0.0.tar.gz
  3. Under the hood this is POST /v1/admin/modules/upload (multipart, integrations:write): the artifact lands in the instance blob store (AIHUMMER_BLOB_DIR) under a blob: ref, and a catalog row is registered with origin = local-private, visibility = private.
  4. The plugin appears in the marketplace tagged Private and installs via the normal path — sandboxed systemd unit + health gate.

Trust: the pinned key and the trust store

Private artifacts must be signed. When you upload a plugin signed with an unknown key, the Admin UI prompts you to approve the author’s key into the instance trust store (one click). Once approved, the signature is verified on every install and update.

  • Artifacts from the official source verify against the registry key pinned in core — trusted by default, no extra step.
  • Private artifacts verify against keys in the instance trust store.
  • Unsigned bundles are rejected — except in dev mode for local iteration: AIHUMMER_PLUGIN_DEV_UNSIGNED=1.

[!WARNING] AIHUMMER_PLUGIN_DEV_UNSIGNED=1 disables signature verification and is meant only for local development. Never enable it on an externally reachable instance.

Public mode — the public registry

To make a plugin available to every instance, submit it to the public registry AiHummer/marketplace-catalog via a PR: automated checks + review, and on approval AiHummer counter-signs the release.

Steps

  1. One-time — register the publisher. Generate a key and reserve the namespace:
    aihummer plugin keygen                # prints the public key (base64) and key id
    This reserves the @you namespace. Keep the private key to yourself — it signs every submission.
  2. Host the artifact at a stable HTTPS URL (the artifact is hosted by the author, not by AiHummer).
  3. Open a PR to the catalog:
    aihummer plugin publish --public --dir ./my-plugin --key author.key \
      --artifact-url https://you.example.com/my-plugin-1.0.0.tar.gz \
      --publisher you --description "What the plugin does" --icon https://you.example.com/icon.svg \
      [--screenshot https://you.example.com/1.png ...] [--channel stable|beta] \
      [--register-key author.pub]
    --register-key adds publishers/<you>.json (needed only on your first submission).
  4. CI gates validate the submission (see below), AI review posts a risk verdict, and an AiHummer maintainer reviews and merges manually.
  5. On merge the release is counter-signed with the pinned registry key and published to a separate community-catalog.json on the CDN. Every instance that has added this source sees the plugin; core trusts it via the pinned key — no per-operator trust step needed.

The submission contract

A PR adds two files (the form is generated by publish --public and is stable):

publishers/<publisher>.json — one-time registration:

{
  "publisher": "acme",
  "public_key": "<base64 std ed25519 public key>",
  "key_id": "<sha256(public_key)[:16] in hex>",
  "contact": "you@example.com"
}

catalog/<publisher>/<slug>/plugin.json — a submission (one per version line):

{
  "publisher": "acme",
  "slug": "hello-tool",
  "namespaced_slug": "@acme/hello-tool",
  "version": "1.0.0",
  "channel": "stable",
  "artifact_url": "https://acme.example.com/hello-tool-1.0.0.tar.gz",
  "license": "MIT",
  "publisher_key_id": "bd68f2deedad25b1",
  "signature": "<base64 ed25519 over the release identity>",
  "manifest": { "...the full Manifest object..." }
}
  • namespaced_slug must equal @<publisher>/<slug>.
  • channelstable | beta.
  • artifact_url is the .tar.gz hosted by the author.
  • publisher_key_id must match the registered publisher’s key_id.
  • The release identity signed = the bytes slug \x00 version \x00 artifact_url.
  • For a public submission the embedded manifest must carry description, icon (and optionally screenshots) — see store-page fields.

[!TIP] aihummer plugin publish --public assembles these files in the right shape and opens the PR for you — there’s no need to hand-edit the JSON.

Moderation

Every submission goes through an automated check (the submission contract, signature and a security scan), then an advisory AI risk review, and finally a mandatory human review by the AiHummer team. Neither automation nor the AI ever merges on its own — the decision is always a maintainer’s, and nothing reaches the catalog without their approval. A published plugin later found to be malicious or broken can be revoked and dropped from the catalog on the next sync.

The community catalog as an extra source

Public plugins are published to a separate community-catalog.json that does not overwrite the curated first-party catalog. An instance adds it as an extra source in Plugins → Sources (or POST /v1/admin/modules/catalog/sources). See Install & updates and Overview & tiers.

Where next