/docs / plugin-publishing

Shipping a Plugin

Shipping a plugin means building one binary per platform, uploading each with the plugin's manifest and skills, and submitting a version for review. NeboAI signs the binaries when the version is approved, and every bot verifies them before it runs them.

Prepare the files

notes-sync/
├── PLUGIN.md                 # marketplace listing
├── plugin.json               # runtime manifest
├── skills/
│   └── notes-sync/
│       └── SKILL.md
└── dist/
    ├── darwin-arm64/notes-sync
    ├── linux-amd64/notes-sync
    └── windows-amd64/notes-sync.exe
FilePurpose
PLUGIN.mdThe marketplace listing people read before installing. Sent as manifestContent.
plugin.jsonThe runtime manifest. Uploaded once with the first binary. See plugin.json Reference.
skills/Skills that teach employees to use the plugin. Uploaded once as a .tar.gz whose entries start with skills/.
BinariesOne executable per platform. Name each after binaryName; add .exe on Windows.
---
name: Example Notes
description: Search, read and create notes in Example Notes.
version: 1.0.0
category: productivity
---

# Example Notes

Connect each employee to its own Example Notes account. Employees can search
notebooks, read notes and create new ones.

Platforms

Upload a binary for each platform you support: darwin-arm64, darwin-amd64, linux-arm64, linux-amd64, windows-arm64 or windows-amd64. macos- is accepted as a synonym for darwin-. A bot installs the binary for its own platform.

Upload and submit

You work through the NeboAI MCP server; Publishing covers connecting and developer accounts. Select your developer account, then create the plugin and ask for an upload token.

plugin(action: "create", name: "Example Notes", description: "Search, read and create notes in Example Notes.",
       category: "productivity", version: "1.0.0", manifestContent: "<PLUGIN.md>")

plugin(action: "binary-token", id: "<plugin id>")

The token lasts five minutes and covers any number of uploads. Upload each platform's binary. Send config (the plugin.json) and skills with one of them.

TOKEN=<token from binary-token>
ID=<plugin id>

tar czf skills.tar.gz -C notes-sync skills

curl -X POST "https://neboai.com/api/v1/developer/apps/$ID/binaries" \
  -H "Authorization: Bearer $TOKEN" \
  -F file=@notes-sync/dist/darwin-arm64/notes-sync \
  -F platform=darwin-arm64 \
  -F config=@notes-sync/plugin.json \
  -F skills=@skills.tar.gz

curl -X POST "https://neboai.com/api/v1/developer/apps/$ID/binaries" \
  -H "Authorization: Bearer $TOKEN" \
  -F file=@notes-sync/dist/linux-amd64/notes-sync \
  -F platform=linux-amd64

curl -X POST "https://neboai.com/api/v1/developer/apps/$ID/binaries" \
  -H "Authorization: Bearer $TOKEN" \
  -F file=@notes-sync/dist/windows-amd64/notes-sync.exe \
  -F platform=windows-amd64
Form fieldRequiredMeaning
fileyesThe binary.
platformyesOne of the six platform keys.
confignoThe plugin.json, at most 1 MB.
skillsnoA .tar.gz of the skills/ folder. Entries outside skills/ are ignored.

Each binary is stored against the plugin's current version, and uploading the same platform again replaces it. To ship a new version, first change the version with plugin(action: "update", id, version), then upload. Each upload request is limited to 100 MB.

When every platform is uploaded, submit that version.

On a plugin that is already listed, only the new version waits for review. The approved version stays listed and installable, and it is what bots update to. Approval switches the listing to the new version; if the new version is rejected, the approved one stays live.

A version goes live only complete: every platform your plugin.json lists under platforms must have an approved binary first. Until the last one is approved, people keep getting the previous version, and a plugin that has never been listed stays unlisted. Bots that installed the plugin are told about the new version once, when it goes live.

plugin(action: "submit", id: "<plugin id>", version: "1.0.0")

Review and signing

Every upload is scanned. A version with no binaries is flagged for manual review. When a version is approved, NeboAI signs each binary and the manifest with Ed25519, writes the real hash, size, signature and download URL into plugin.json, and builds one signed package per platform.

On a bot

  • Nebo downloads the package for its platform, checks the SHA-256 hash and the signature, and installs it to <data>/nebo/plugins/<slug>/<version>/.
  • Nebo keeps one version of each plugin. Installing a new version replaces the old one.
  • The plugin's data folder, <data>/appdata/plugins/<slug>/, survives updates and uninstalls.
  • Nebo checks for updates a minute after it starts and then every six hours. An update installs by itself when the owner has turned on automatic updates for that plugin; otherwise the owner is notified.

Test before you ship

Build for your own machine and put the binary and plugin.json in <data>/user/plugins/<slug>/. A plugin there overrides the marketplace version with the same slug and skips signature checks, so you can iterate without publishing. See Plugins.