The blueye CLI
The SDK ships with a blueye command line interface for working with the drone from
the terminal. It is installed together with the SDK:
pip install blueye.sdk
Running blueye --help lists the available commands. One command needs an extra:
blueye bundle-model inspects ONNX files and requires the heavyweight onnx package,
installed with the SDK's cli extra:
pip install "blueye.sdk[cli]"
(Keep the quotes — most shells treat square brackets specially.) If the extra is
missing, bundle-model detects it and prints the install command for your platform
instead of failing.
Bundling CV models — blueye bundle-model
The Blueye X3 Ultra can run your own computer vision models: object
detection, instance segmentation, and single-object tracking. The drone's vision
pipeline consumes model packages — a zip containing an ONNX model and a
model_meta.json file that describes how to preprocess frames and decode the model's
outputs.
The blueye bundle-model command turns an exported ONNX file into such a package. It
- validates that the model is of a supported type,
- auto-generates
model_meta.jsonfrom the ONNX graph and any embedded metadata (Ultralytics exports carry their class names and input size along), - interactively asks about anything that cannot be inferred, and
- writes a deployable zip.
Interactive use
Point the command at your ONNX file and answer the prompts:
blueye bundle-model path/to/model.onnx
The CLI inspects the model, shows what it inferred (output format, class count, input size, labels), and walks through the remaining choices with interactive prompts — model name, tracking algorithm, and the runtime configuration for the drone:
- Execution device — the CLI analyzes the network and recommends the Jetson DLA
cores (
tensorrt-dla0/tensorrt-dla1) for convolution-style models, which frees the GPU for other work. Models with layers the DLA cannot run (NMS-in-graph, transformers) gettensorrtrecommended instead. You can always pick any device. - Inference rate — maximum rate in Hz, defaulting to unlimited.
- Autolaunch — whether the drone should start this model automatically. Defaults
to enabled; pass
--no-runtime-enabledto bundle the package disabled. - Package metadata — a version string (default
1.0.0) plus optional description, author, and license. These are informational fields carried insidemodel_meta.jsonso the package stays self-describing wherever it travels (drone web UI, Blueye App, Blueye Cloud). Use an SPDX identifier for the license when you can (MIT,Apache-2.0,AGPL-3.0,Proprietary).
The result is a zip with model.onnx and model_meta.json at its root.
Scripted use
Every prompt can be answered with a flag, and --yes accepts all inferred defaults:
blueye bundle-model yolov8n.onnx --yes \
--name "YOLOv8n (COCO)" \
--model-version 1.0.0 --author "Ultralytics" --license AGPL-3.0 \
--description "YOLOv8n nano object detector trained on COCO (80 classes)" \
--tracking byte_track \
--runtime-device tensorrt-dla0 --runtime-hz 10 --runtime-enabled \
--output yolov8n_package.zip
Use --dry-run to print the generated model_meta.json without writing anything, and
--labels labels.txt (one class name per line) when the model does not embed its class
names.
Supported model types
| Output format | Model family |
|---|---|
yolov2_grid |
YOLOv2 / TinyYOLOv2 (grid + anchors) |
yolov5_flat |
YOLOv5 ONNX export |
yolov8_flat |
YOLOv8 / YOLO11 ONNX export |
yolov8_seg |
YOLOv8/v11 segmentation |
yolo_e2e |
End-to-end YOLO with NMS in the model (YOLO26) |
yolo_e2e_seg |
End-to-end YOLO segmentation |
ssd_multi |
SSD (multi-output, e.g. TensorFlow exports) |
detr |
DETR transformer detectors |
ostrack |
OSTrack single-object tracker |
mixformerv2 |
MixFormerV2 single-object tracker |
The model must take float32 image input; models with a clearly unsupported structure (image classifiers, float16 inputs, non-image inputs) are rejected with an explanation.
Deploying to the drone
The easiest way is to push the package directly: interactive runs offer it after the
zip is written, and scripts pass --push (with --drone-ip if the drone is not at
the default 192.168.1.101):
blueye bundle-model yolov8n.onnx --yes --push
If the drone cannot be reached, the command fails with a clear message — the zip is still written and can be pushed later.
The same operations are available programmatically through the SDK:
import blueye.sdk
drone = blueye.sdk.Drone(auto_connect=False) # HTTP only, takes no control
model = drone.cv_models.upload("yolov8n_package.zip")
drone.cv_models.set_enabled(model.directory, True)
Without the SDK installed, the drone's HTTP endpoint accepts the package zip as a
multipart upload (field name file):
curl -F "file=@yolov8n_package.zip" http://192.168.1.101/api/cv-models/upload
or use the Blunux Web App — open http://192.168.1.101 in a browser and upload the
zip from the Computer Vision tab.
Managing models on the drone — blueye models
Installed models are managed with the blueye models command, or interactively by
running it without arguments on a terminal:
blueye models list
blueye models enable yolov8n-coco
blueye models set-device yolov8n-coco tensorrt-dla0
blueye models warmup yolov8n-coco # pre-build the TensorRT engine
blueye models delete yolov8n-coco
Model names are the directory slugs shown by blueye models list. Note: the
enabled state is the autolaunch configuration; the API does not expose a live
"running" status.
Downloading dive logs — blueye logs
The drone's binary dive logs (.bez) can be listed and downloaded from the terminal.
The command connects to the drone as an observer — taking no control:
blueye logs list # table of logs on the drone
blueye logs download --latest 1 # newest log to the current directory
blueye logs download --latest 1 --mcap # ...and convert it for Foxglove
blueye logs download BYEDP000000_ea9ac92e1817a1d4_00002 -o ~/dives
blueye logs convert mydive.bez # convert an already-downloaded log (no drone)
blueye logs # interactive: pick logs to download
list, download, and the interactive view accept --dives-only, --since
YYYY-MM-DD, and --until YYYY-MM-DD to narrow the selection; the interactive view
is a single scrollable table (type to filter, space to select, sorted newest first).
--mcap converts each downloaded log to a Foxglove-ready .mcap next to the
.bez — blueye logs convert does the same for files already on disk. See
visualizing dive logs with Foxglove.
For working with logs from Python (streaming, filtering, plotting), see
logs from the drone.
Third-party tools — blueye tools
The blueye command is built to grow: besides the built-in commands, anyone can drop
single-file Python tools into a per-user directory. The CLI discovers them
automatically, lists them in blueye --help, and runs them as
blueye <tool-name> ... — no SDK changes needed.
Writing a tool
A tool is a normal Python script carrying PEP 723
inline metadata, extended with a [tool.blueye] table:
# /// script
# requires-python = ">=3.10"
# dependencies = ["pandas"]
#
# [tool.blueye]
# name = "export-logs"
# description = "Export dive logs to CSV"
# min-sdk-version = "2.7.0"
# ///
import sys
import pandas as pd
def main() -> int:
print(f"exporting with args: {sys.argv[1:]}")
return 0
if __name__ == "__main__":
sys.exit(main())
The [tool.blueye] keys:
| Key | Required | Meaning |
|---|---|---|
name |
yes | The subcommand name (blueye export-logs). Lowercase letters, digits, and hyphens; must start with a letter; at most 32 characters. |
description |
yes | One line shown in blueye --help and blueye tools list. |
min-sdk-version |
no | Minimum blueye.sdk version; a mismatch prints a warning but never blocks. |
Arguments after the tool name are passed to the script verbatim, and its exit code
becomes the CLI's exit code. Invocation is strictly blueye <tool-name> args....
Dependencies: when the script declares PEP 723 dependencies and
uv is installed, the CLI runs it with uv run, giving
the script an isolated environment with those dependencies — your tool can use pandas
without pandas ever being installed next to the SDK. Without uv, the script runs with
the current interpreter and must find its dependencies there.
Installing and managing tools
blueye tools validate my_script.py # check the metadata before installing
blueye tools install my_script.py # copy it into the tools directory
blueye tools list # built-ins + installed tools
blueye tools uninstall export-logs
blueye tools dir # print the resolved tools directory
Discovery scans the tools directory on every invocation and parses only the metadata block — tool code is never executed during discovery or listing.
The directory is resolved from the BLUEYE_CLI_TOOLS_DIR environment variable when
set, otherwise from the platform default:
| Platform | Default tools directory |
|---|---|
| macOS | ~/Library/Application Support/blueye/cli-tools |
| Linux | $XDG_DATA_HOME/blueye/cli-tools (or ~/.local/share/blueye/cli-tools) |
| Windows | %APPDATA%\blueye\cli-tools |
Name collisions always resolve in favor of built-in commands; blueye tools list
shows shadowed or invalid tools with the reason.
SDK contributors adding a built-in command should follow the recipe and
invariants documented in the blueye.sdk.cli.commands module docstring.