Skip to main content
The ados plugin subcommand tree is the operator and developer interface to the agent’s plugin host: install, enable, inspect, sign, and lint plugins. This page documents all 16 subcommands, their flags, and the exit codes every command shares. Run ados plugin --help on the agent for the same list, or ados plugin <command> --help for a single command.

The --json flag

Every subcommand accepts --json. With it, the command prints a single machine envelope to stdout instead of human-readable text:
{ "ok": true, "code": 0, "kind": "ok", "data": ... }
On failure the envelope carries the error:
{ "ok": false, "code": 3, "kind": "signature_invalid", "detail": "...", "hint": "..." }
code is the process exit code (see Exit codes), kind is the stable string form of that code, data is the per-command payload, and hint (when present) is a suggested next step. Use the JSON form in scripts and CI; parse .ok and .code rather than the human text, which is not stable.

Exit codes

Every ados plugin subcommand returns one of these codes. The JSON envelope’s kind field carries the same meaning as a string.
CodeKindMeaning
0okSuccess
1generic_failureUnclassified failure
2manifest_invalidThe manifest.yaml is missing or fails validation
3signature_invalidThe archive signature did not verify against a trusted key
4permission_deniedA capability change was refused (for example, --yes on a high-risk plugin)
5plugin_not_foundNo plugin with that id is installed
6wrong_stateThe plugin is in a state the command cannot act on
7resource_limitA declared resource budget was exceeded
8compatibility_failedThe plugin’s compatibility block (ados version, board, tier) does not match this agent

Lifecycle commands

list

List installed plugins.
ados plugin list
ados plugin list --all
ados plugin list --json
FlagMeaning
--allInclude built-in plugins discovered via entry points, not just third-party installs
--jsonMachine-readable output
The human table prints ID, VERSION, STATUS, and SIGNER. Built-in plugins (with --all) show status builtin and signer altnautica.

install

Install a .adosplug archive from a local path.
ados plugin install dist/com.example.thermal-1.0.0.adosplug
Argument / flagMeaning
ARCHIVEPath to the .adosplug archive (must exist)
--allow-unsignedSkip signature verification. Developer mode only
--yesSkip the interactive permission-approval prompt. Refuses high-risk and critical-risk plugins
--jsonMachine-readable output
Install verifies the signature (unless --allow-unsigned), validates the manifest, and checks compatibility. It then prints the plugin id, its risk level, and the permissions requested, and prompts for approval. If you decline, the plugin is uninstalled and the command exits 0. --yes approves the listed permissions without a prompt, but it refuses any plugin whose risk is high or critical (exit 4); re-run those interactively. A signature failure exits 3, a bad manifest exits 2, a compatibility mismatch exits 8. After a successful install the plugin is installed but not yet running. Enable it next:
ados plugin enable com.example.thermal

enable

Enable an installed plugin so the host starts it.
ados plugin enable com.example.thermal
Argument / flagMeaning
PLUGIN_IDThe installed plugin id
--jsonMachine-readable output
Exits 5 if no plugin with that id is installed.

disable

Disable a plugin. It stays installed, with its grants intact, but the host stops running it.
ados plugin disable com.example.thermal
Argument / flagMeaning
PLUGIN_IDThe installed plugin id
--jsonMachine-readable output

remove

Stop, uninstall, and forget a plugin.
ados plugin remove com.example.thermal
ados plugin remove com.example.thermal --keep-data
Argument / flagMeaning
PLUGIN_IDThe installed plugin id
--keep-dataPreserve the plugin’s data directory instead of deleting it
--jsonMachine-readable output

Inspection commands

info

Print a manifest summary and runtime state for one plugin.
ados plugin info com.example.thermal
ados plugin info com.example.thermal --json
Argument / flagMeaning
PLUGIN_IDAn installed or built-in plugin id
--jsonMachine-readable output
The human output lists the version, status, signer, install source, and each permission with its grant state. Exits 5 if the id is neither installed nor a built-in.

perms

Show or revoke permissions on an installed plugin.
# show
ados plugin perms com.example.thermal

# revoke one capability
ados plugin perms com.example.thermal --revoke mavlink.write
ados plugin perms com.example.thermal --revoke mavlink.write --yes
Argument / flagMeaning
PLUGIN_IDThe installed plugin id
--revoke IDRevoke a specific capability id
--yes, -ySkip the revoke confirmation prompt
--jsonMachine-readable output
With no --revoke, the command lists each recorded permission as GRANTED or DENIED. With --revoke, it confirms intent (unless -y or --json), then revokes the grant. The plugin loses access to the protected resource on the next token rotation, which can interrupt a running workload. Exits 5 if the plugin is not installed.

logs

Tail a plugin’s stdout and stderr log file.
ados plugin logs com.example.thermal
ados plugin logs com.example.thermal --lines 500
ados plugin logs com.example.thermal --follow
Argument / flagMeaning
PLUGIN_IDThe installed plugin id
--lines NNumber of trailing lines to print (default 100)
--followFollow the log like tail -f. Ctrl-C to stop
--jsonMachine-readable output (non-follow only)
The log file lives in the plugin log directory, named after the plugin id with dots replaced by dashes. Exits 5 if no log file exists (the plugin may never have started, or its log rotated out).

Update commands

pin

Pin a plugin to a version so auto-update skips it.
ados plugin pin com.example.thermal 1.2.0
Argument / flagMeaning
PLUGIN_IDThe installed plugin id
VERSIONThe version to pin to
--jsonMachine-readable output

unpin

Clear the pinned version so auto-update can run again.
ados plugin unpin com.example.thermal
Argument / flagMeaning
PLUGIN_IDThe installed plugin id
--jsonMachine-readable output

auto-update

Toggle auto-update on or off for one plugin.
ados plugin auto-update com.example.thermal on
ados plugin auto-update com.example.thermal off
Argument / flagMeaning
PLUGIN_IDThe installed plugin id
STATEon or off
--jsonMachine-readable output

check-updates

Run the auto-update poll once and print the outcome per plugin, instead of waiting for the daily cadence.
ados plugin check-updates
ados plugin check-updates --json
Argument / flagMeaning
--jsonMachine-readable output
It honours each plugin’s pin and auto-update flags. The agent must be paired to the cloud relay (the registry credentials live in the pairing state); if it is not paired, the command exits 1 and the hint suggests running ados pair first. Only enabled and running plugins are checked.
The hosted plugin registry is planned, not live. check-updates and the auto-update flags are wired against it for when it ships. See Distribution: registry.

Developer commands

These commands run on a developer workstation against a plugin directory or a packed archive, not against installed plugins.

lint

Run static analysis on a packed .adosplug archive before submission.
ados plugin lint dist/com.example.thermal-1.0.0.signed.adosplug
ados plugin lint --json dist/com.example.thermal-1.0.0.signed.adosplug
Argument / flagMeaning
ARCHIVE_PATHPath to the packed .adosplug archive (must exist)
--jsonMachine-readable output
Exits 0 when the report passes, 1 when it carries a finding at severity error or critical, 2 when the manifest is invalid. The full rule set is documented under Linting.

test

Run a plugin’s pytest suite under the SDK test harness.
ados plugin test ./my-extension
ados plugin test ./my-extension --tests-dir tests -k follow
Argument / flagMeaning
PLUGIN_DIRThe plugin directory (must contain a manifest.yaml)
--tests-dir DIRSubdirectory holding the pytest tests (default tests)
-k EXPRESSIONA pytest -k expression passed through to the runner
--jsonMachine-readable output
The command validates the manifest, sets ADOS_PLUGIN_ID, ADOS_PLUGIN_VERSION, ADOS_PLUGIN_ROOT, and (when declared) ADOS_PLUGIN_TEST_FIXTURES in the environment, then shells out to pytest so your tests run against the canonical runner. Exits 0 when pytest passes, 1 when it fails, 2 on a bad manifest, 5 when the tests directory is missing.

sign

Pack a plugin directory into a signed .adosplug archive.
ados plugin sign ./my-extension \
  --key keys/acme-2026-A.priv.pem \
  --signer-id acme-2026-A \
  --output dist/com.example.foo-1.0.0.adosplug
Argument / flagMeaning
PLUGIN_DIRThe plugin directory (must contain a manifest.yaml)
--key PATHThe Ed25519 private key in PEM format (required)
--signer-id IDThe signer id written to the SIGNATURE file. Must match the public-key filename on the agent (required)
--output PATHOutput path for the signed archive (required)
--jsonMachine-readable output
The command packs the directory, computes the canonical payload hash (SHA-256 over the sorted entry hashes), signs that digest with the Ed25519 key, and writes a SIGNATURE entry into the archive plus a .sha256 checksum file next to it. The signing details and the monorepo-CI alternative (pack.sh and sign.sh) are covered under Signing keys.

keygen

Generate a fresh Ed25519 keypair for plugin signing.
ados plugin keygen acme-2026-A --output-dir keys
ados plugin keygen acme-2026-A --output-dir keys --force
Argument / flagMeaning
SIGNER_IDThe signer id; becomes the key filenames
--output-dir DIRDirectory to write the keypair into (required)
--forceOverwrite existing key files at the target paths
--jsonMachine-readable output
Writes <signer-id>.pem (the public key, mode 0644) and <signer-id>.priv.pem (the private key, mode 0600) under the output directory, and prints a SHA-256 fingerprint of the public key for cross-checking. Install the public PEM on each agent at /etc/ados/plugin-keys/<signer-id>.pem and keep the private half offline.
keygen is a developer aid. Production publisher keys deserve a hardware-token or air-gapped workflow, not a one-liner. Never commit a .priv.pem file.

See also