MISSION CONTROL · EXTENSIONSShipping

Customize the GCS without forking it.

Extensions add panels, overlays, and whole workflows to Mission Control. Each one runs inside a sandboxed iframe with capability-gated bridges to telemetry, command, and video, and mounts through named UI slots. Signed, scoped, and consented to at install.
plugin-workspace
iframe
Sandbox Model
Ed25519
Signed Archives
Token
Capability-Gated
GPLv3
Open Source

CONTRIBUTIONS

Three ways an extension shows up.

Mission Control exposes named slots across the node tabs, the map and video panes, the settings surface, and the Cockpit Skill Bar. An extension declares which slots it contributes to and the host renders it where it belongs.

Panels

Add a tab, a card, a setting

Contribute a node-detail tab, a hardware view, or a settings section. The slot system handles placement and layout. The plugin handles the content.

Overlays

Paint over the live view

Draw on the map, paint a HUD over video, or push a notification into the operator channel. The plugin gets a scoped canvas. The host owns z-order, gestures, and dismissal.

Workflows

Wire it into the flows

Ship a mission template or a Cockpit Skill. Extension contributions run through the same registries as built-in features, so an extension Skill sits on the Skill Bar next to Arm.

Named slots

node.detail.tabsettings.sectionfc.tabhardware.tabmap.overlayvideo.overlaynotification.channelmission.templateflight.skill

RUNTIME

A plugin lives in its own iframe.

Each plugin loads inside an iframe with the allow-scripts sandbox flag and no same-origin access. There is no DOM bridge, no shared global, and no shared cookie.

The plugin iframe and the host talk over postMessage. Each call carries a capability token minted by the host at install time, and the host validates that token against the granted permission set on every message. Untrusted plugin code never sees host state directly.

Content security policy locks down connect-src, so a plugin cannot reach the network on its own. If it needs an external endpoint, it requests an allowlisted domain in the manifest and the operator approves it at install.

A plugin that hangs its renderer never freezes the GCS. Mission Control runs each iframe on its own task and falls back to a placeholder card with a reload button if the plugin stops responding.

SANDBOX SURFACE
┌─ iframe ─────────────────────────┐
│  sandbox="allow-scripts"          │
│  csp: connect-src 'none'          │
│  (no same-origin, no top-nav)     │
└──────────────┬────────────────────┘
               │  postMessage
        token-checked ↑ ↓
┌──────────────┴────────────────────┐
│  host                             │
│    telemetry.subscribe            │
│    vehicle.command                │
│    mission.read                   │
│    map.overlay.draw               │
│    video.overlay.paint            │
└───────────────────────────────────┘
No allow-same-origin. No allow-top-navigation. The plugin sees its own iframe and nothing else.

TRUST

Signed, scoped, and consented to.

Signing

  • Plugins ship as signed .adosplug archives
  • Ed25519 verification at install and on every reload
  • A revocation list checked on each session start
  • Unsigned plugins load only when developer mode is on
  • First-party publishers carry an allowlist marker

Permissions

  • The manifest declares every capability the extension needs
  • A two-stage install dialog: summary, then permission grant
  • Sensitive capabilities are flagged in the permission list
  • Vehicle command requires an explicit re-confirm at install
  • Every permission is revocable from Mission Control
Permission review

Every capability the extension requests is listed at install. The ones that touch sensitive surfaces (vehicle command, external network access, mission write, recording) are flagged so you grant them deliberately, and every one is revocable afterward.

CODE

A panel in thirty lines.

One YAML manifest, one TypeScript entry. The example renders a battery card in a node tab and updates as telemetry arrives.

manifest.yaml
name: battery-health-panel
version: 0.1.0
gcs:
  entry: dist/index.js
  slots: [node.detail.tab]
  capabilities:
    - telemetry.read
    - ui.slot.node_detail_tab
index.tsx
import { definePlugin } from "@altnautica/plugin-sdk";
import { BatteryCard } from "./BatteryCard";

export default definePlugin({
  slot: "node.detail.tab",
  title: "Battery Health",
  render({ telemetry }) {
    const battery = telemetry.subscribe("battery");
    return <BatteryCard data={battery} />;
  },
});

The host injects telemetry, vehicle, mission, and other context objects matched to the granted permissions. The plugin never imports a global, never reaches into the GCS DOM, and never shares state with another plugin.

EXTENSIONS

Reference extensions, ready to read.

First-party extensions live in the public ADOSExtensions repository. Read the code, fork it, and build your own.

GCS only

Battery Health Panel

A node-detail tab that reads battery frames, displays per-cell voltage and temperature, predicts time to minimum, and raises an anomaly alert when cell spread or thermal gradient cross a threshold. A canonical reference for a GCS-only plugin.

  • ·Live per-cell voltage and temperature
  • ·Predictive time-to-minimum calculation
  • ·Anomaly alerts on the notification channel

Hybrid

Thermal Camera, GCS half

A video overlay with palette swap, a spot meter, isotherm bands, and a flat-field correction trigger, plus a hardware view for camera settings. It pairs with the agent half that decodes the thermal stream on the vehicle.

  • ·Palette swap, spot meter, and isotherm bands
  • ·Flat-field correction and gain-mode toggle
  • ·A survey-grid mission template

Build an extension for Mission Control.

The reference extensions are open source. Read them, fork them, ship your own.

View ADOSExtensions
Get Early Access