Skip to main content
@altnautica/plugin-sdk (v1.3.0, GPL-3.0-or-later) is the GCS-half SDK: the package a plugin’s Mission Control side imports. A plugin’s GCS half always uses it; its agent half uses the Python SDK or the Rust SDK. The SDK hides the postMessage envelope and gives you a typed PluginContext.

Install

The package is not published to npm. Develop your plugin inside the altnautica/ADOSExtensions monorepo as a pnpm workspace member; the scaffolder pins the SDK to workspace:^ against the in-tree packages/plugin-sdk. Your first plugin walks through the clone and scaffold flow. The package ships ESM only, with no runtime dependencies, and four entry points:

definePlugin

The single entry point:
mount is called once the bundle loads. A throw is not reported to the host, so catch errors and render your own error state. info is { id, version } from your definePlugin call. Before Mission Control destroys the frame it asks the plugin to unmount and waits up to 500 ms; keep unmount short and do not rely on it to persist state. See Lifecycle. definePlugin returns a PluginInstance with info, ctx and an unmount() you can call for your own teardown.

PluginContext

The argument the SDK hands to mount:
command.send and mission.write wait for the operator’s decision rather than a fixed deadline. A denial, a command the host does not allow, or a rate limit rejects with a HostError whose code is refused. events.subscribe reads one-way host pushes (video-overlay host props, an agent plugin’s state read-back) and needs no grant. events.listen and events.publish use the GCS plugin bus between installed plugin panels and need event.subscribe and event.publish. records reads and writes the plugin’s own cloud collection: list(opts), get(collection, key), put(collection, key, data) and remove(collection, key). definePlugin builds the context for you. To build one by hand (in a test, for example), use createPluginContext:

Wrappers and the bridge methods they call

Each wrapper delegates to one PluginClient call. The wire methods and their capabilities are on GCS bridge methods. For any other method, call ctx.client.request(method, capability, args).

PluginClient

The lower-level RPC client:
  • request(method, capability, args, options?): send a request and await the response. Default timeout 5 s.
  • on(method, handler): subscribe to host-pushed events.
  • subscribeTelemetry(topic, handler): does both the subscribe request and the telemetry.<topic> listener.
  • dispose(): tear down listeners and reject in-flight requests.
The client caches the capability token Mission Control pushes on the capability.token event (CAPABILITY_TOKEN_EVENT), so token rotation needs no plugin code. A request the host refuses with capability_denied:token_missing is held and sent again once the first token arrives. The capability argument is typed with the CapabilityId union of every known id.

HostError

Thrown when the host returns an error envelope:
Branch on code; the message is for humans. The codes are listed on GCS bridge methods.

Other exports

  • contributesModel: an identity helper that types a contributes literal (editor autocomplete and a compile-time shape check) and returns it unchanged, for manifest fixtures and codegen.
  • validateValue, clampValue, inferWidget, resolveBinding, defaultFor, PARAMETER_WIDGETS, PARAMETER_BINDINGS: the parameter schema helpers. See Parameter schema.
  • createWindowTransport, MemoryTransport: the transports under PluginClient.
  • PROTOCOL_VERSION, TELEMETRY_TOPICS and the envelope, telemetry, perception, records and contribution types.

Test harness

The harness:
  • mounts the plugin against an in-memory transport (no real iframe);
  • records every request in harness.calls, with harness.notifications and harness.recordingMarks as shortcuts;
  • pushes host traffic with pushTelemetry, pushEvent, pushConfig, pushTheme and pushPerceptionDetection, and stubs reads with stubPerceptionTier and stubPerceptionHealth;
  • simulates host failures with failNext(method, code, message);
  • gates calls by capability like the bridge: a telemetry subscription needs its topic grant (telemetry.subscribe.<topic>), and a ui.slot.* RPC needs that slot’s capability.

Building the bundle

The SDK has no build step of its own. The create-ados-plugin templates use esbuild:
Run from gcs/, the output is gcs/plugin.bundle.js, the path the manifest’s gcs.entrypoint names. The bundle is not hashed in the manifest; the archive signature covers it.

Next steps

Your first plugin

Build, test, sign and install a GCS-only tab.

GCS bridge methods

The wire methods, pushed events and error codes.
Last modified on October 11, 2026