.adosplug) that adds behaviour to a node: a driver, a flight behaviour, a Mission Control panel. The SDK and the CLI call these packages plugins. This page covers how the agent installs and runs them. To write one, start with Your first plugin.
The plugin host, ados-plugin-host, runs on every node profile whether or not an extension is installed; with none installed it idles. Each extension’s agent half runs as its own service unit: a systemd unit in ados-plugins.slice on Linux, a per-user LaunchAgent on macOS. The agent never loads extension code into its own processes.
The ados plugin CLI
The full command set (
info, perms, lint, test, pin, auto-update, sign, keygen and more) with flags and exit codes is in the Plugin CLI reference.
Install an extension
github.com or its release asset hosts); every redirect is checked against the same list. The agent pins the archive’s SHA-256 between the preview and the install, so it installs the bytes you reviewed.
A catalog id installs the version pinned in the agent’s bundled catalog. To install a specific release, use its URL.
The CLI prints the plugin id, version, risk and the requested permissions, then asks once: Approve permissions?. Approving installs the extension and grants every requested permission; declining installs nothing. Change single grants afterwards with ados plugin perms <id> --grant <perm> or --revoke <perm>.
--yes skips the question for scripts, but refuses a high- or critical-risk extension. Approve those interactively.
Mission Control installs the same way from a node’s Extensions page; see Install extensions from Mission Control.
Signatures and trust
Every.adosplug contains a SIGNATURE entry: a signer id and a base64 Ed25519 signature over the archive’s canonical payload hash (a SHA-256 over every entry except SIGNATURE).
- The agent loads
/etc/ados/plugin-keys/<signer-id>.pemand verifies the signature against it. - It refuses an archive that is unsigned or does not verify, whose signer is listed in
/etc/ados/plugin-revocations.json, or whose archive digest is listed there. - Trust follows the key that verifies the signature. Nothing in
manifest.yamlnames or vouches for a signer. - First-party privileges (an inline Mission Control module,
resources.class: heavy, an agent half on the unsandboxed macOS backend) go only to a verified signer on the agent’s built-in first-party list,altnautica-2026-Aandaltnautica-2026-B. Those key bytes are pinned in the agent, so a key file dropped in under a first-party name verifies only as a third party. - With
ADOS_PLUGIN_REQUIRE_SIGNED=0(developer mode) an unsigned or unverifiable archive installs as unsigned and gets no first-party privileges.
Permissions
Every extension declares the capabilities it needs inmanifest.yaml:
mavlink.write grant gets capability_denied back and the call never runs.
Each manifest also declares a risk level, one of four: low, medium, high or critical. The full capability list and what each one allows are in Agent capabilities.
Built-in extensions
Three extensions ship inside the agent package. They are not installed by default; list them withados plugin list --all and install one by id, for example ados plugin install io.altnautica.geofence. A built-in has no archive signature (it is recorded as builtin:<id>) and runs as a sandboxed subprocess unit like any other extension. All three are low risk.
io.altnautica.geofencesubscribes tovehicle.geofence_breachand republishes a structured alert underplugin.io.altnautica.geofence.alert. A template for turning a vehicle event into a notification.io.altnautica.telemetry-loggersubscribes to seven lifecycle topics (armed, disarmed, mode change, battery low, geofence breach, agent ready, agent shutdown) and writes one structured line per event to its log.io.altnautica.mavlink-inspectorfolds vehicle state (mode, armed state, battery and the last event time) into a snapshot and republishes it underplugin.io.altnautica.mavlink-inspector.snapshot.
Isolation and restarts
On Linux each extension’s unit runs inados-plugins.slice with cgroup CPU, memory and process limits from the manifest’s agent.resources block, or the agent’s defaults when the manifest sets none. Its stdout and stderr go to a log file under /var/log/ados/plugins/, which ados plugin logs reads. On macOS each extension is a per-user LaunchAgent; launchd enforces neither the sandbox nor the limits, so the agent installs only first-party agent halves there.
A unit that exits with an error is restarted by systemd every 2 seconds with no retry limit. Stop a crash-looping extension with ados plugin disable <id>.
Install across a fleet
Install per node. In Mission Control, open each node’s Extensions page, or pick a node from Settings → Extensions. From your own tooling, runados plugin install over SSH on each node. There is no fleet-wide install.
Next steps
Extensions catalog
The first-party extensions and their permissions.
Install from Mission Control
The per-node Extensions page and the install review.
Plugin CLI reference
Every
ados plugin command and exit code.Your first plugin
Write and sign your own.