SDK overview
The Plugin SDK is versioned with the Host. Worker protocol is 1.1. App protocol is 1.0. API version 1.0. Current matrix: Host 0.1.3, SDK 1.0.0.
Pick an implementation from the Worker runtime:
| Runtime | Language | Package | Source | Template | Host launch |
|---|---|---|---|---|---|
node |
TypeScript | @vibex/plugin-sdk |
packages/plugin-sdk |
ts-worker |
node --max-old-space-size=128 dist/worker.mjs |
node |
JavaScript | @vibex/plugin-sdk |
packages/plugin-sdk |
node-worker |
same |
python |
Python | vibex-plugin |
sdk/python |
python-worker |
Host-locked CPython 3.12.11 plus runtime/worker.py |
native |
Rust | vibex-plugin-sdk |
crates/plugin-sdk |
rust-worker |
spawn the binary at entrypoints.worker.path |
All four share the stdio JSON-line protocol, handler rules, generation semantics, and Host capability names. App surfaces ship definePluginApp in the TypeScript / JavaScript SDK. Python and Rust SDKs cover Worker.
Language chapters:
vibex-plugin toolchainThe command prints local cli, contract, js, python, rust paths and templates. In the VibeX checkout, use node packages/plugin-cli/dist/cli.js toolchain. See Development workflow.
Transport
Each Worker has one stdio connection, one JSON object per line. Frame limit 1 MiB. Default request timeout 30 seconds. Cancellation is an explicit notification. stderr is scoped diagnostics.
Handshake:
- Host sends
initializewithprotocolRange: ["1.1"],hostVersion,pluginIdentity,packageDigest,generationId,declaredContributions,packageClass, andlimits(maxFrameBytes,requestTimeoutMs). - Worker replies
protocolVersion: "1.1",sdkVersion,registrations: [],requestedFeatures. - Host sends
activatewithpluginId,pluginVersion,generation,packageClass,grantedCapabilities. - Worker runs
setup, freezes the handler table, and replies with the registered handler list. - Later messages are
invoke/ping/dispose. Worker-to-Host useshost.callwithcapability,operation,input.
protocolVersion must be 1.1; otherwise the Host returns worker_protocol_unsupported.
Registration
Setup only registers handlers, then freezes. Duplicate ids, undeclared ids, or missing required handlers fail candidate activation. Handles from an old generation become stale after a new generation publishes. Further calls return a stable error. The Host starts a Runtime when a contribution needs it.
Handler regex: Contribution model.
Host capabilities
environment.host.call(capability, operation, input?) is the only Host RPC. Current Host behavior (crates/plugins/src/host_capability_broker.rs):
| capability.operation | Result |
|---|---|
runtime.execute plus any operation |
Spawn the locked Runtime, JSON on stdin, 120s timeout, 1 MiB input cap |
artifact.preview plus any operation |
Open preview. input needs a Host-issued artifactHandle (~30s, single use) and providerId |
artifact.readText / artifact.writeText |
artifact_not_found. Text I/O is on the artifact.editor App bridge |
storage.kv.get / put / delete / list |
In-process map keyed by plugin ID; cleared when the process exits |
storage.settings.get / put |
Read and write this plugin’s root config.json |
log.debug / info / warn / error |
Empty object; scoped diagnostics |
plugin.self.doctor |
{ pluginId, generation, diagnostics, recentCrashes } |
conversation.create |
Create and bind a Conversation. Omit workspaceId to use the plugin scratch workspace |
conversation.list / conversation.get / conversation.read.get |
Only conversations this plugin owns or was granted |
conversation.append.enqueueInput |
The same submit control plane |
conversation.steer / conversation.cancel |
In-flight steer and cancel |
conversation.cancelInput / conversation.listInputs |
Queued inputs |
conversation.respondPermission / conversation.respondQuestion |
Permission and question replies |
conversation.setMode / conversation.setConfigOption |
Session config |
conversation.catalog / conversation.archive |
Available agents and archive |
conversation.events.since |
Changed timeline rows |
remote.profile.list / upsert / forget |
Client-saved Hosts. provisionKind is a source tag |
remote.connect / disconnect |
Attach the app shell to a saved Host; call the provisioner by provisionKind |
provider.presets.list / save / bind |
Provider presets; bind uses Host confirmation UI |
secrets.get / put / delete |
{ "present": false } |
network.fetch |
network_denied. Full Trust uses the language runtime |
files.read / write / stat / list |
files_root_denied |
agent.invoke |
handler_not_visible |
events.subscribe / ack |
Placeholder success |
app.notify.toast |
Empty object |
| other | capability_unimplemented |
Structure surfaces (app.tab / app.panel / app.kanban.view / app.settings.page) receive Federation mount(root, environment) with workspaceId and invoke(handler, input). invoke reaches this plugin’s Worker.
Unbound conversation.* calls return conversation_scope_denied. Uninstall keeps saved Hosts; omit remote.profile.forget.
Execution class
v4 packages spawn Workers under Full Trust. packageClass=isolated does not change Host spawn. The Python managed interpreter is locked to CPython 3.12.11 (python-build-standalone). The Rust crate isolated feature omits filesystem and network helpers; the author API remains define_plugin_worker.

