/docs / plugin-capabilities

plugin.json Reference

plugin.json is the manifest Nebo reads to install and run a plugin. Keys are camelCase. This page lists every field Nebo reads today and what each one does.

Top-level fields

FieldTypeRequiredMeaning
idstringyesThe plugin’s marketplace identifier. Use the slug while developing.
slugstringyesStable identifier. [a-z0-9-], at most 64 characters, no leading, trailing or double hyphen. Names the plugin__<slug> tool and the <SLUG>_BIN variable.
namestringyesDisplay name. Name the service it connects to.
versionstringyesSemantic version, such as 0.1.0.
platformsmapyesPlatform key to binary. See Platforms.
descriptionstringnoOne sentence for people and employees.
authorstringnoPublisher name.
categorystringnoHelps employees find the plugin.
triggerslist of stringsnoWords that describe when the plugin applies. Used in search hints.
entrySkillslist of stringsnoBundled skills to name first in the plugin’s tool description.
dependencieslist of {name, version, optional}noOther plugins this one runs. version defaults to "*"; optional to false. Their <SLUG>_BIN paths are set on every call.
authobjectnoSign-in and accounts. See Auth.
capabilitiesobjectnoconfigSchema, hooks, commands, routes, providers.
permissionsobjectnoEnvironment filtering and the timeout ceiling.
eventslistnoWatchers that feed employee workflows.
interfaceBindingsmapnoTyped operations the plugin provides.
channelobjectnoA persistent bridge to a messaging service.
setupobjectnoA step-by-step setup wizard.

Nebo validates marketplace installs: the slug rules, a semantic version, at least one platform, a binaryName with no path separators or .., a login command unless auth.type is env, non-empty event names and commands, and binding templates that parse. Plugins in the user plugins directory skip validation.

Platforms

Keys are darwin-arm64, darwin-amd64, linux-arm64, linux-amd64, windows-arm64 and windows-amd64. Each entry has all five fields below. When you publish, the marketplace writes the real hash, size, signature and download URL, so leave them empty in the file you upload.

"platforms": {
  "darwin-arm64":  { "binaryName": "notes-sync",     "sha256": "", "signature": "", "size": 0, "downloadUrl": "" },
  "linux-amd64":   { "binaryName": "notes-sync",     "sha256": "", "signature": "", "size": 0, "downloadUrl": "" },
  "windows-amd64": { "binaryName": "notes-sync.exe", "sha256": "", "signature": "", "size": 0, "downloadUrl": "" }
}
FieldMeaning
binaryNameThe executable’s file name. Add .exe on Windows.
sha256Hash of the binary. Checked at install.
signatureSignature of the binary. Checked at install when a signing key is available.
sizeSize in bytes.
downloadUrlWhere Nebo downloads the package.

Auth

FieldMeaning
typeoauth_cli for a browser sign-in run by the plugin; env for credentials entered as values; neboai to receive the owner’s NeboAI token in every auth.env key ending in _TOKEN.
envMap of variable name to default value. Also the only credential names Nebo passes to login.
commands.loginSigns in. Required unless type is env. Runs with the account folder set.
commands.statusPrints JSON that says whether the account is signed in.
commands.refreshRenews a token without interaction.
commands.logoutSigns out. Only the owner can run it.
profileDirEnvVariable that receives a separate credential folder for each employee and account. Without it the plugin holds one shared account.
label, descriptionText on the connect card.
help{url, urlLabel, text} shown while connecting.
publicRedirectSet true when the provider refuses http://localhost redirects; sign-in then goes through NeboAI’s public redirect.

Nebo reads the first of authenticated, isAuthenticated, logged_in, loggedIn or token_valid in the status output. A non-empty token_error, or the value none in credential_source, auth_method, storage or status, means signed out. The status command has 45 seconds.

{"authenticated": true, "account": "finance@example.com"}

configSchema

capabilities.configSchema describes the values an owner sets for the plugin. Each value reaches the binary as an environment variable named by key. For credential keys also listed in auth.env, the schema labels the fields of the per-employee connect form.

FieldTypeDefaultMeaning
keystringrequiredEnvironment variable name.
labelstringrequiredField label.
descriptionstring""Help text.
fieldTypestring"string"Input type, such as string, number, boolean, select or password.
defaultstringnonePre-filled value.
requiredbooleanfalseThe plugin is not ready until the value is set.
secretbooleanfalseThe value is masked when read back.
optionslist of stringsnoneChoices for select.

permissions

FieldDefaultMeaning
envAllow[]Inherited variables the plugin may see. Empty allows all.
envDeny[]Inherited variables always removed.
maxTimeoutSeconds300Upper bound for any call’s timeout.
networkfalseDeclares network use. Informational; not enforced.

events

An event is a long-running watcher. Nebo starts it when an employee's workflow watches it, and restarts it if it exits. Each line the watcher writes to stdout is one event. The event name is prefixed with the slug at run time, so note.created becomes notes-sync.note.created.

"events": [
  {
    "name": "note.created",
    "description": "A note was created in the watched notebook.",
    "command": "watch --notebook {{notebook}} --format ndjson"
  }
]
FieldMeaning
nameEvent name, without the slug. Required.
commandArguments that start the watcher. Required. {{key}} is replaced from the employee’s input values.
descriptionWhat causes the event.
multiplexedWhen true, one watcher emits several event types and each line carries an "event" field.

Workflows subscribe to events with a watch trigger. See Triggers.

interfaceBindings

A binding maps an interface operation to one of your commands. Each binding becomes a typed tool for employees, named after the operation in lowercase with dots and hyphens as underscores: notes.search becomes notes_search. Bindings are how a plugin satisfies the capabilities an employee requires; see Capabilities.

"interfaceBindings": {
  "notes.search": "notes search --query {query} {tag[]:--tag} {limit?:--limit}",
  "invoice.create": "invoices create --amount {amount_cents:cents->dollars}"
}
PlaceholderExpands to
{field}The field’s value as one word. The field is not also passed as a flag.
{field[]:--flag}One --flag <item> pair for each item in a list field.
{field?:--flag}--flag <value> when the field is present; nothing when it is absent.
{field:cents->dollars}An integer amount in cents, written as dollars.

Input fields a template does not name are appended as --field value. List and optional placeholders must be whole words. An operation that requires approval cannot be reached by calling the same command through plugin__<slug>.

Hooks, slash commands and routes

"capabilities": {
  "hooks": [
    { "hook": "tool.post_execute", "hookType": "filter", "command": "hook redact", "priority": 50, "timeoutMs": 500 }
  ],
  "commands": [
    { "name": "notes", "description": "Show today's notes", "command": "notes today", "slash": true }
  ],
  "routes": [
    { "path": "/callback", "method": "GET", "command": "http callback" }
  ]
}

hooks

A hook runs your command at a point in an employee's turn. Nebo writes a JSON payload to stdin. An action hook's output is ignored. A filter hook returns {"payload": ..., "handled": false}; "handled": true stops later hooks. Errors and timeouts keep the previous payload and never block the turn. After three failures in a row a hook is paused for five minutes.

FieldDefaultMeaning
hookrequiredOne of tool.pre_execute, tool.post_execute, message.post_receive, session.message_append, steering.generate, agent.turn, agent.should_continue.
hookType"action"action or filter.
commandrequiredArguments for your binary.
priority100Lower runs first.
timeoutMs500Time limit in milliseconds.

commands

With "slash": true, typing /name args in chat runs command args directly, without the employee. The output is the reply. The time limit is 30 seconds.

routes

A route answers HTTP requests at /api/v1/plugins/<slug>/api/<path> on the bot, matched by path and method. The request body goes to stdin and your stdout is the response. The time limit is 30 seconds.

providers

A provider adds a chat model source. Declare id, displayName, providerType, modelsCommand and chatCommand. Nebo sends a chat request as JSON on stdin to chatCommand and reads streamed events as newline-delimited JSON on stdout, for up to 300 seconds. Only chat streaming is used today.

channel

A channel bridges a messaging service. Nebo keeps command running, reads inbound messages from its stdout and writes replies to its stdin, both as newline-delimited JSON.

FieldDefaultMeaning
commandrequiredArguments that start the bridge.
name, description""Shown in settings.
restartDelaySecs5Wait before restarting after a crash.
sharedfalseOne bridge for all employees; messages are routed by employee name and replies carry each employee’s identity.
needsLocalApifalseGive the bridge the bot’s local API address, a token and the employee id. Off unless you need it.

setup

A setup wizard walks the owner through steps that a single form cannot cover. Values from form steps fill {{key}} in later generate arguments. Values from credentials steps are saved as the plugin's environment variables.

"setup": {
  "title": "Connect Example Chat",
  "steps": [
    { "kind": "form", "title": "Bot name", "fields": [ { "key": "bot_name", "label": "Name", "required": true } ] },
    { "kind": "generate", "title": "App manifest", "command": "manifest", "args": ["--name", "{{bot_name}}"], "outputFormat": "yaml" },
    { "kind": "external", "title": "Create the app", "url": "https://example.com/apps", "urlLabel": "Open admin" },
    { "kind": "credentials", "title": "Paste the token", "fields": [ { "key": "EXAMPLE_CHAT_TOKEN", "label": "Token", "inputType": "password", "required": true } ], "verifyCommand": "auth status" }
  ]
}
Step kindFields
formtitle, description, fields
generatetitle, description, command, args, outputFormat (yaml, json, toml, text), buttonLabel. Shows the command’s output to copy.
externaltitle, description, url, urlLabel, instructions
credentialstitle, description, fields, verifyCommand. The step completes when verifyCommand succeeds.

Fields have key, label, default, placeholder, maxLength, help, inputType (text, textarea, password) and required.