blueye.sdk.cli
commands
First-party command registry for the blueye CLI.
Every built-in command lives in its own package under blueye/sdk/cli/commands/ and
exposes a module-level COMMAND: CommandSpec. Registering a new command means adding
it to :func:all_commands — nothing else in the CLI changes.
Invariants command packages must uphold:
- The package (and everything it imports at module level) must be importable with zero
optional extras installed; heavy imports (onnx, rich, questionary, ...) belong inside
run. This keepsblueye --helpworking before the[cli]extra is installed. add_parseruses only argparse.- User-facing failures raise :class:
blueye.sdk.cli.errors.CliError;mainturns them into a clean message and exit code 1.
The CommandSpec contract is also the intended payload for future pip-installable
plugins (a blueye.cli entry-point group): an external distribution would expose the
same object, and the registry would grow a second discovery source.
Modules:
-
bundle_model–The
blueye bundle-modelcommand: bundle an ONNX model into a BlueyeCV package. -
logs–The
blueye logscommand: list and download dive logs from the drone. -
models–The
blueye modelscommand: manage the CV models installed on the drone. -
tools–The
blueye toolscommand: manage third-party CLI tools.
Classes:
-
CommandSpec–One first-party
blueyesubcommand.
Functions:
-
all_commands–Return every built-in command, in the order shown in
blueye --help.
CommandSpec
dataclass
CommandSpec(
name: str,
help: str,
requires: tuple[str, ...],
add_parser: Callable[[_SubParsersAction], None],
run: Callable[[Namespace], int],
)
One first-party blueye subcommand.
Attributes:
-
name(str) –The subcommand name (e.g. "bundle-model").
-
help(str) –One-line description shown in
blueye --help. -
requires(tuple[str, ...]) –Import names of optional dependencies that must be installed before
runexecutes;maingates on these and prints install guidance. -
add_parser(Callable[[_SubParsersAction], None]) –Registers the subcommand's arguments on the root subparsers (argparse only, no optional imports).
-
run(Callable[[Namespace], int]) –Executes the command and returns the process exit code.
all_commands
all_commands() -> tuple[CommandSpec, ...]
Return every built-in command, in the order shown in blueye --help.
Source code in blueye/sdk/cli/commands/__init__.py
52 53 54 55 56 57 58 59 | |
meta
model_meta.json construction and validation.
Pure, stdlib-only functions implementing the BlueyeCV model package contract (BlueyeCV/docs/model-meta-spec.md). The generated JSON mirrors the field order used by the reference packages so diffs against hand-written files stay readable.
Classes:
-
MetaOptions–Everything needed to build a model_meta.json, after prompting/flags.
Functions:
-
build_meta–Build the model_meta.json dict from the collected options.
-
default_preprocessing–Return (normalize_scale, normalize_mean, normalize_std) defaults per format.
-
validate_meta–Check a model_meta dict against the BlueyeCV parser's validation rules.
MetaOptions
dataclass
MetaOptions(
name: str = "",
version: str = "",
description: str = "",
author: str = "",
license: str = "",
output_format: str = "",
kind: str = "detection",
num_classes: int | None = None,
labels: list[str] = list(),
input_width: int | None = None,
input_height: int | None = None,
grid_size: int | None = None,
anchors: list[list[float]] = list(),
confidence_threshold: float = 0.3,
nms_threshold: float = 0.45,
one_indexed_classes: bool = False,
color_order: str = "rgb",
normalize_scale: float = SCALE_1_OVER_255,
normalize_mean: list[float] = list(),
normalize_std: list[float] = list(),
template_size: int | None = None,
search_size: int | None = None,
sot_overrides: dict[str, object] = dict(),
tracking_algorithm: str = "none",
tracking_overrides: dict[str, object] = dict(),
runtime_device: str | None = None,
runtime_hz: float | None = None,
runtime_enabled: bool = False,
)
Everything needed to build a model_meta.json, after prompting/flags.
Attributes mirror the spec's blocks; None/empty means "omit or use the default".
build_meta
build_meta(options: MetaOptions) -> dict
Build the model_meta.json dict from the collected options.
Parameters:
-
options(MetaOptions) –The fully-resolved options (inference results merged with prompt/flag answers).
Returns:
-
dict–A JSON-serializable dict in the reference packages' field order.
Source code in blueye/sdk/cli/commands/bundle_model/meta.py
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | |
default_preprocessing
default_preprocessing(
output_format: str,
) -> tuple[float, list[float], list[float]]
Return (normalize_scale, normalize_mean, normalize_std) defaults per format.
Matches every reference package: YOLOv2 and TF-SSD models take raw 0-255 pixels, DETR and the SOT trackers use ImageNet normalization, everything else scales to [0, 1].
Source code in blueye/sdk/cli/commands/bundle_model/meta.py
114 115 116 117 118 119 120 121 122 123 124 125 | |
validate_meta
validate_meta(meta: dict) -> list[str]
Check a model_meta dict against the BlueyeCV parser's validation rules.
Parameters:
-
meta(dict) –The dict produced by :func:
build_meta(or hand-assembled).
Returns:
-
list[str]–A list of human-readable problems; empty when the metadata is valid.
Source code in blueye/sdk/cli/commands/bundle_model/meta.py
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | |
heuristics
Model-type inference for the blueye bundle-model CLI.
Pure functions over :class:~blueye.sdk.cli.introspect.ModelInfo-shaped data: no
onnx import, no I/O, no terminal — everything here is unit-testable with hand-built
dataclasses. The rules mirror what the BlueyeCV output decoders expect (see
BlueyeCV/docs/model-meta-spec.md).
Classes:
-
DlaAssessment–Whether the model is a good fit for the Jetson DLA cores, and why.
-
InferredConfig–What could be derived from the model, plus how sure we are.
-
UnsupportedModelError–The model is clearly not usable by BlueyeCV; the message explains why.
Functions:
-
assess_dla_fitness–Judge whether the model is a good candidate for the Jetson DLA cores.
-
infer–Infer the BlueyeCV model configuration from the ONNX graph and metadata.
-
parse_ultralytics_metadata–Parse the metadata_props Ultralytics embeds in its ONNX exports.
DlaAssessment
dataclass
DlaAssessment(good_fit: bool, reason: str)
Whether the model is a good fit for the Jetson DLA cores, and why.
InferredConfig
dataclass
InferredConfig(
kind: Literal[
"detection", "sot", "unknown"
] = "unknown",
output_format: str | None = None,
confidence: Literal["high", "low"] = "low",
num_classes: int | None = None,
input_width: int | None = None,
input_height: int | None = None,
grid_size: int | None = None,
template_size: int | None = None,
search_size: int | None = None,
labels: list[str] | None = None,
suggested_name: str | None = None,
notes: list[str] = list(),
)
What could be derived from the model, plus how sure we are.
Attributes:
-
kind(Literal['detection', 'sot', 'unknown']) –"detection", "sot", or "unknown" (format must be chosen manually).
-
output_format(str | None) –The inferred model_meta output_format, or None.
-
confidence(Literal['high', 'low']) –"high" when the shape/metadata evidence is unambiguous; "low" when the format should be confirmed with the user.
-
num_classes(int | None) –Class count derived from the output shape or metadata.
-
input_width(int | None) –Model input width in pixels (None if dynamic/unknown).
-
input_height(int | None) –Model input height in pixels (None if dynamic/unknown).
-
grid_size(int | None) –Feature-map grid size (yolov2_grid only).
-
template_size(int | None) –SOT template crop size (from the template input).
-
search_size(int | None) –SOT search crop size (from the search input).
-
labels(list[str] | None) –Class labels from embedded metadata, index order preserved.
-
suggested_name(str | None) –Human-readable name suggestion (metadata description or None).
-
notes(list[str]) –Human-readable reasoning, shown in the inference summary.
UnsupportedModelError
The model is clearly not usable by BlueyeCV; the message explains why.
assess_dla_fitness
assess_dla_fitness(info: ModelInfo) -> DlaAssessment
Judge whether the model is a good candidate for the Jetson DLA cores.
The DLA natively executes convolution-style networks; NMS/TopK and attention/normalization layers fall back to the GPU, negating the benefit. This is a heuristic over the op histogram — TensorRT has the final word when the engine is built on the drone.
Parameters:
-
info(ModelInfo) –The introspected model.
Returns:
-
DlaAssessment–A DlaAssessment with the verdict and a one-line reason.
Source code in blueye/sdk/cli/commands/bundle_model/heuristics.py
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | |
infer
infer(info: ModelInfo) -> InferredConfig
Infer the BlueyeCV model configuration from the ONNX graph and metadata.
Parameters:
-
info(ModelInfo) –The introspected model.
Returns:
-
InferredConfig–An InferredConfig;
kind == "unknown"means the format must be chosen manually.
Raises:
-
UnsupportedModelError–When the model clearly cannot run in BlueyeCV (classifier, no image input, float16 input, too many inputs).
Source code in blueye/sdk/cli/commands/bundle_model/heuristics.py
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | |
parse_ultralytics_metadata
parse_ultralytics_metadata(
metadata: dict[str, str],
) -> dict[str, object]
Parse the metadata_props Ultralytics embeds in its ONNX exports.
Parameters:
-
metadata(dict[str, str]) –The raw metadata_props key/value dict.
Returns:
-
dict[str, object]–A dict possibly containing "labels" (list[str]), "imgsz" ((height, width)), "task" (str), and "description" (str). Keys are absent when not parseable.
Source code in blueye/sdk/cli/commands/bundle_model/heuristics.py
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | |
introspect
ONNX model introspection for the blueye bundle-model CLI.
This is the only CLI module that imports the onnx package. It is imported lazily by
the subcommand, after the dependency gate in main has verified the [cli] extra is
installed.
Classes:
-
IntrospectionError–The file could not be read or is not a valid ONNX model.
-
ModelInfo–Everything the bundler needs to know about an ONNX model.
-
TensorSpec–Shape and type of one graph input or output.
Functions:
-
check_model–Run the strict onnx checker on the model file.
-
load_model_info–Load an ONNX file and extract the information the bundler needs.
IntrospectionError
The file could not be read or is not a valid ONNX model.
ModelInfo
dataclass
ModelInfo(
path: Path,
inputs: tuple[TensorSpec, ...] = (),
outputs: tuple[TensorSpec, ...] = (),
metadata: dict[str, str] = dict(),
external_data_files: tuple[str, ...] = (),
op_histogram: dict[str, int] = dict(),
)
Everything the bundler needs to know about an ONNX model.
Attributes:
-
path(Path) –Path to the .onnx file.
-
inputs(tuple[TensorSpec, ...]) –Graph inputs (initializers excluded).
-
outputs(tuple[TensorSpec, ...]) –Graph outputs.
-
metadata(dict[str, str]) –The model's metadata_props as a plain dict (Ultralytics exports embed "names", "imgsz", "task", "stride", ... here).
-
external_data_files(tuple[str, ...]) –Unique file names referenced by tensors stored as external data. These files must live next to the .onnx and travel with it.
-
op_histogram(dict[str, int]) –Node op_type -> count over the whole graph (used for the DLA fitness assessment).
TensorSpec
dataclass
TensorSpec(
name: str,
dtype: int,
dims: tuple[int | str | None, ...],
)
Shape and type of one graph input or output.
Attributes:
-
name(str) –Tensor name in the graph.
-
dtype(int) –onnx.TensorProto element type as a plain int (see FLOAT32/FLOAT16).
-
dims(tuple[int | str | None, ...]) –One entry per dimension: a fixed int, a symbolic name (str, e.g. "batch"), or None when the dimension is completely unknown.
dtype_name
property
dtype_name: str
Human-readable element type name (e.g. "FLOAT", "FLOAT16").
shape_str
property
shape_str: str
Shape rendered like [1, 3, 640, 640] with ? for unknown dims.
check_model
check_model(path: Path) -> str | None
Run the strict onnx checker on the model file.
Parameters:
-
path(Path) –Path to the .onnx file. The path form is used so external data is found.
Returns:
-
str | None–None when the model passes, otherwise the checker's error message. Some perfectly deployable models fail strict checking, so the caller decides whether this is fatal.
Source code in blueye/sdk/cli/commands/bundle_model/introspect.py
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | |
load_model_info
load_model_info(path: Path) -> ModelInfo
Load an ONNX file and extract the information the bundler needs.
External tensor data is not loaded into memory (the file may be gigabytes); only the referenced file names are recorded.
Parameters:
-
path(Path) –Path to the .onnx file.
Returns:
-
ModelInfo–The extracted ModelInfo.
Raises:
-
IntrospectionError–If the file does not exist or is not a parseable ONNX model.
Source code in blueye/sdk/cli/commands/bundle_model/introspect.py
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | |
bundle
Zip writing for the blueye bundle-model CLI.
Stdlib-only. The bundle is a flat zip: model.onnx, any external weight files under
their exact embedded names, and model_meta.json — all at the archive root, matching
how BlueyeCV packages are unpacked onto the drone (unzip -d <package_dir>).
Classes:
-
BundleError–A user-facing bundling problem (missing files, name collisions, ...).
Functions:
-
bundle_size–Total input size in bytes (for progress reporting).
-
write_bundle–Write the model package zip.
BundleError
A user-facing bundling problem (missing files, name collisions, ...).
bundle_size
bundle_size(
onnx_path: Path, external_files: list[str]
) -> int
Total input size in bytes (for progress reporting).
Parameters:
-
onnx_path(Path) –Path to the .onnx file.
-
external_files(list[str]) –External-data file names living next to the .onnx.
Raises:
-
BundleError–When an external file is missing or otherwise unusable — sizing runs before :func:
write_bundle, so it validates too instead of leaking a FileNotFoundError.
Source code in blueye/sdk/cli/commands/bundle_model/bundle.py
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | |
write_bundle
write_bundle(
meta: dict,
onnx_path: Path,
external_files: list[str],
output_path: Path,
progress: Callable[[int], None] | None = None,
) -> None
Write the model package zip.
The archive is written to <output>.part and atomically renamed on success, so
an interrupted run never leaves a truncated zip behind.
Parameters:
-
meta(dict) –The validated model_meta dict.
-
onnx_path(Path) –The source .onnx file (stored as
model.onnx). -
external_files(list[str]) –External-data file names (must exist beside the .onnx; stored under their exact names because the .onnx references them by name).
-
output_path(Path) –Destination zip path.
-
progress(Callable[[int], None] | None, default:None) –Optional callback receiving the number of bytes just written.
Raises:
-
BundleError–When an external file is missing or collides with a reserved name.
Source code in blueye/sdk/cli/commands/bundle_model/bundle.py
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | |
metadata
PEP 723 inline-metadata parsing for third-party blueye tools.
A tool script declares itself with the standard PEP 723 block, 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"
# ///
TOML parsing is tiered: :mod:tomllib (Python 3.11+), then :mod:tomli when
installed (shipped in the [cli] extra for Python 3.10), then a minimal regex
fallback so a stdlib-only Python 3.10 environment can still discover tools. The
fallback only understands single-line double-quoted string values inside
[tool.blueye] (arrays and multi-line strings need tomli) — enough for the keys the
CLI reads.
Classes:
-
MetadataError–The script's inline metadata is missing or invalid; the message says why.
-
ToolMetadata–The metadata the CLI reads from a tool script.
Functions:
-
extract_script_block–Extract the un-commented TOML text of the PEP 723
scriptblock. -
parse_tool_metadata–Parse a tool script's source into its ToolMetadata.
MetadataError
The script's inline metadata is missing or invalid; the message says why.
ToolMetadata
dataclass
ToolMetadata(
name: str,
description: str,
min_sdk_version: str | None = None,
has_dependencies: bool = False,
parsed_with_fallback: bool = False,
)
The metadata the CLI reads from a tool script.
Attributes:
-
name(str) –The subcommand name the tool is invoked as (
blueye <name>). -
description(str) –One-line description shown in listings and
blueye --help. -
min_sdk_version(str | None) –Optional minimum blueye.sdk version; mismatches warn at dispatch time but never block execution.
-
has_dependencies(bool) –True when the PEP 723 block declares
dependencies— execution then prefersuv runso the script gets an isolated environment. -
parsed_with_fallback(bool) –True when the regex fallback (not a real TOML parser) produced this metadata.
extract_script_block
extract_script_block(source: str) -> str | None
Extract the un-commented TOML text of the PEP 723 script block.
Parameters:
-
source(str) –The tool script's full source text.
Returns:
-
str | None–The TOML text, or None when no
scriptblock is present.
Raises:
-
MetadataError–When more than one
scriptblock exists (invalid per PEP 723).
Source code in blueye/sdk/cli/external/metadata.py
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | |
parse_tool_metadata
parse_tool_metadata(source: str) -> ToolMetadata
Parse a tool script's source into its ToolMetadata.
Parameters:
-
source(str) –The tool script's full source text.
Returns:
-
ToolMetadata–The parsed metadata.
Raises:
-
MetadataError–When the block is absent, unparseable, or missing/violating the required
[tool.blueye]keys.
Source code in blueye/sdk/cli/external/metadata.py
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | |
discovery
Tools-directory resolution and third-party tool discovery.
Classes:
-
DiscoveredTool–One script found in the tools directory.
Functions:
-
discover_tools–Return the runnable tools, keyed by name (valid metadata, not shadowed).
-
format_tools_epilog–Build the
blueye --helpsection listing discovered tools (None when empty). -
scan_tools_dir–Scan the tools directory and parse every candidate script's metadata.
-
tools_dir–Resolve the third-party tools directory.
-
tools_dir_source–Describe where the resolved tools directory came from (for display).
DiscoveredTool
dataclass
DiscoveredTool(
path: Path,
metadata: ToolMetadata | None = None,
error: str | None = None,
shadowed_by: str | None = None,
)
One script found in the tools directory.
Attributes:
-
path(Path) –The script file.
-
metadata(ToolMetadata | None) –The parsed metadata, or None when parsing failed.
-
error(str | None) –The parse-failure reason when metadata is None.
-
shadowed_by(str | None) –Set when the tool's name is unusable: "built-in command" or the file name of an earlier tool that claimed the same name.
discover_tools
discover_tools(
builtin_names: frozenset[str] = frozenset(),
) -> dict[str, DiscoveredTool]
Return the runnable tools, keyed by name (valid metadata, not shadowed).
Source code in blueye/sdk/cli/external/discovery.py
103 104 105 106 107 108 109 | |
format_tools_epilog
format_tools_epilog(
tools: dict[str, DiscoveredTool],
) -> str | None
Build the blueye --help section listing discovered tools (None when empty).
Source code in blueye/sdk/cli/external/discovery.py
112 113 114 115 116 117 118 119 120 121 122 | |
scan_tools_dir
scan_tools_dir(
builtin_names: frozenset[str] = frozenset(),
) -> list[DiscoveredTool]
Scan the tools directory and parse every candidate script's metadata.
Returns every *.py file (non-recursive, sorted by file name) as a
DiscoveredTool, including invalid and shadowed entries — blueye tools list shows
them all. Never raises for a missing or empty directory.
Parameters:
-
builtin_names(frozenset[str], default:frozenset()) –First-party command names; tools with a colliding name are marked shadowed (built-ins always win).
Source code in blueye/sdk/cli/external/discovery.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | |
tools_dir
tools_dir() -> Path
Resolve the third-party tools directory.
Precedence: the :data:TOOLS_DIR_ENV environment variable, then the platform's
conventional per-user data location. The directory is not created here — only
blueye tools install creates it.
Source code in blueye/sdk/cli/external/discovery.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
tools_dir_source
tools_dir_source() -> str
Describe where the resolved tools directory came from (for display).
Source code in blueye/sdk/cli/external/discovery.py
40 41 42 43 44 | |
execution
Subprocess execution of third-party tools.
Functions:
-
run_tool–Run a discovered tool as a subprocess and return its exit code.
run_tool
run_tool(tool: DiscoveredTool, args: list[str]) -> int
Run a discovered tool as a subprocess and return its exit code.
Scripts that declare PEP 723 dependencies are run with uv run when uv is
available, giving them an isolated environment with those dependencies; otherwise
the current interpreter runs the script directly (its dependencies may already be
importable here).
Parameters:
-
tool(DiscoveredTool) –The tool to run (must have valid metadata).
-
args(list[str]) –Arguments passed through to the script verbatim.
Source code in blueye/sdk/cli/external/execution.py
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | |