Skip to content

Repository files navigation

Code Check Coverage Status

Holoscan CLI

Command-line tool for creating, discovering, building, running, testing, and packaging Holoscan Modules and applications. Published as the holoscan-cli PyPI package and installs the holoscan console script.

Overview

The CLI presents a single command surface for the source-project development lifecycle:

  • Project lifecycle: build, run, test, install, package
  • Container: build-container, run-container
  • Discovery / diagnostics: list, modes, status, env-info, env-check, autocompletion_list, version
  • Workspace: lint, setup, clear-cache, create

Run holoscan <command> --help for per-command flags.

Per-repo wrappers install this package and delegate to holoscan, layering on their own configuration via HOLOSCAN_CLI_* environment variables:

Repo Wrapper Adds
HoloHub ./holohub source-project metadata search paths, container/workspace names
I4H Workflows ./i4h RTI DDS license auto-download + mount, TTY serial device passthrough

Common env vars:

  • HOLOSCAN_CLI_ROOT — repo root
  • HOLOSCAN_CLI_SEARCH_PATH — subdirs to scan for metadata.json
  • HOLOSCAN_CLI_PATH_PREFIX — placeholder prefix in metadata templates
  • HOLOSCAN_CLI_REPO_PREFIX — container image name prefix
  • HOLOSCAN_CLI_CONTAINER_PREFIX — standalone Module image name prefix
  • HOLOSCAN_CLI_CREATE_TEMPLATE — default template for holoscan create

holoscan env-info lists every env var the CLI reads in the current shell.

Project trust model

Holoscan source projects are executable code, not passive data. In particular, metadata.json can define a run.command (directly or through a mode), and holoscan run executes that project-defined command. Build files, Dockerfiles, setup scripts, and test configuration can execute project code as well. Review the source and metadata before building or running a repository you do not trust.

For a plain run.command string, the CLI expands Holoscan placeholders, parses the result into an argument vector, and launches it without an implicit shell. A project can still request a shell explicitly (for example, bash -c ...) or name any other executable. Local execution runs with the invoking user's permissions; elevation happens only when the user explicitly passes --as-root.

Use holoscan run <project> --dryrun --local --verbose to inspect the resolved local build and run commands without executing them. A dry run helps with review, but it is not a sandbox and does not make untrusted project code safe.

JSON output

list, modes, status, env-info, env-check, and version accept --json and print a single machine-readable document instead of prose.

Every payload starts with a schema_version field, currently 1. Within a version the payloads change additively: new keys may appear, existing keys are not removed or renamed. Consumers should ignore keys they do not recognize; a removal or rename bumps schema_version.

env-info --json reports host state, so the values vary by machine — the docker, cuda_gpu, and git sections are null when unavailable.

Source layout

src/holoscan_cli/
  cli.py              top-level argparse + dispatch (HoloscanCLI)
  configuration.py    effective-configuration reporting
  commands/           one file per subcommand + a central registry
  container/          HoloscanContainer + docker arg helpers + parser builders
  cmake/              packaged CMake support copied into standalone Modules
  utils/              io.py, text.py, sdk.py, docker.py, host_setup.py,
                      env_info.py, holohub.py
  setup_scripts/      bundled bash scripts backing `setup --scripts` and
                      `build-container --extra-scripts`
  metadata/           project metadata JSON schemas
  templates/module/   standalone Module cookiecutter
  testing/            CTest helpers shipped in the wheel

Prerequisites

A platform supported by the NVIDIA Holoscan SDK: an x64 PC with Ubuntu and an NVIDIA GPU, or a supported NVIDIA ARM development kit.

Installation

Python 3.12 or 3.13 is recommended for this walkthrough. Check the selected release's Python requirement before using another interpreter.

With uv, try the CLI without a persistent install:

uvx holoscan-cli --help

The package also provides the canonical holoscan command. For a persistent pip environment:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install holoscan-cli
holoscan --help

Create and work on a standalone module

Creating a module requires the create extra. For the CLI 5.0.0a1 integration release, use NVIDIA's package index (uv 0.4.23 or later):

uvx --index https://pypi.nvidia.com --from 'holoscan-cli[create]==5.0.0a1' holoscan create my-sensor --language python --interactive false --context holoscan_version=4.6.0 --dryrun
uvx --index https://pypi.nvidia.com --from 'holoscan-cli[create]==5.0.0a1' holoscan create my-sensor --language python --interactive false --context holoscan_version=4.6.0
cd holoscan-my-sensor
uv run holoscan list --json
uv run holoscan build my_sensor_pipeline --dryrun --verbose

Replace 4.6.0 with the module's intended minimum SDK version. CLI and SDK versions are independent. Review the preview before running the build without --dryrun; builds require the module's documented SDK/container prerequisites. The generated project records the creating CLI version, and uv run prepares its development environment without installing the module itself.

For the pip alternative, install the same creation extra in the activated .venv, then run holoscan create with the same arguments:

python -m pip install --extra-index-url https://pypi.nvidia.com 'holoscan-cli[create]==5.0.0a1'

In an existing generated module, use its requirements-cli.txt to provision a pip environment. Follow its README.md and DEVELOPER.md for implementation, tests, packaging, and consumer verification. No HoloHub checkout or copied wrapper is needed.

See the CLI reference for project selection, command semantics, previews, diagnostics, and cleanup. For contributing to the CLI itself, see CONTRIBUTING.md.

Project configuration

Standalone Modules can persist a small set of settings that cannot be inferred from metadata.json or the host:

[tool.holoscan]
cuda = 13
ctest-script = "ci/container.ctest"
forward-env = ["IS_CI_BUILD"]
docker-build-args = ["--build-arg", "PROJECT_FEATURE=ON"]
docker-run-args = ["--network=host"]

[tool.holoscan.base-images]
x86_64 = "registry.example.com/holoscan/sdk-build-x86_64:4.5.0-cuda13"
aarch64 = "registry.example.com/holoscan/sdk-build-aarch64:4.5.0-cuda13"

cuda and ctest-script provide Module-wide toolchain defaults, forward-env contains names only, the Docker argument arrays provide static defaults, and base-images contains exact images for the supported target architectures. Use command options for one-off choices. See Configuring Holoscan CLI for the complete user-facing behavior.

Versioning

holoscan-cli release versions are aligned with Holoscan SDK GA release versions. For example, the CLI released with Holoscan SDK 4.4.0 is published as holoscan-cli==4.4.0; the CLI released with Holoscan SDK 4.5.0 is published as holoscan-cli==4.5.0.

CLI-only fixes between SDK releases use the patch component for the current SDK release line, for example holoscan-cli==4.4.1 before the next SDK-aligned 4.5.0 release.

Version alignment does not imply that the CLI selects, installs, or requires a matching Holoscan SDK runtime or container base image. For container builds, the base image can be set with the CLI when your component's Dockerfile is configured with FROM ${BASE_IMAGE}, using any of the methods below:

  1. Pass the image to the --base-img flag:

    holoscan build-container my_app --base-img nvcr.io/nvidia/clara-holoscan/holoscan:v4.4.0-cuda13
  2. Set HOLOSCAN_CLI_BASE_IMAGE to an exact tagged or digested image. It is used without adding another tag:

    export HOLOSCAN_CLI_BASE_IMAGE=nvcr.io/nvidia/clara-holoscan/holoscan:v4.4.0-cuda13
    holoscan build-container my_app
  3. Set HOLOSCAN_CLI_BASE_IMAGE to an image repository (no tag) and HOLOSCAN_CLI_BASE_SDK_VERSION to a Holoscan semantic version. The base image then resolves to $HOLOSCAN_CLI_BASE_IMAGE:v$HOLOSCAN_CLI_BASE_SDK_VERSION-$CUDA_TAG, with the CUDA tag chosen dynamically from your host environment:

    export HOLOSCAN_CLI_BASE_IMAGE=nvcr.io/nvidia/clara-holoscan/holoscan
    export HOLOSCAN_CLI_BASE_SDK_VERSION=4.4.0
    # Resolves to nvcr.io/nvidia/clara-holoscan/holoscan:v4.4.0-cuda13 on hosts with NVIDIA drivers >= 580
    holoscan build-container my_app

If none of these is configured, the CLI asks for a base image instead of inferring one from its own package version.

Advanced wrappers can set HOLOSCAN_CLI_BASE_IMAGE_FORMAT with {base_image}, {sdk_version}, and {cuda_tag}, or HOLOSCAN_CLI_DEFAULT_IMAGE_FORMAT with {container_prefix}, {sdk_version}, and {cuda_tag}. An explicit base-image format controls composition; without one, tagged images and digests are exact while an untagged environment repository uses the SDK/CUDA-derived tag.

Build from source

Python 3.11–3.14 and Poetry 2.0+ required.

# Create + activate a virtual environment
poetry env use python3.12
eval $(poetry env activate)

# Install dependencies + dev tooling
poetry install --with test
pre-commit install

# Run the test suite
poetry run pytest

# Build sdist + wheel
poetry build

Testing against an in-tree source-project fixture

The repo ships a minimal HoloHub-style fixture at tests/fixtures/holohub_smoke/ (one application with a metadata.json that validates against the application schema). Point the CLI at it without needing a HoloHub / I4H checkout:

HOLOSCAN_CLI_ROOT=tests/fixtures/holohub_smoke holoscan list
HOLOSCAN_CLI_ROOT=tests/fixtures/holohub_smoke holoscan modes smoke_app

The same fixture is what .github/scripts/smoke_test.sh exercises against the installed wheel on every CI run, so a passing fixture run locally is a strong proxy for the smoke-test job passing on push.

Testing against the downstream wrappers

Each consuming repo (HoloHub / I4H Workflows) carries a test_holoscan_cli_consolidation.py that exercises the unified holoscan CLI against its project tree. Point the wrapper at a local checkout via HOLOSCAN_CLI_SOURCE:

cd /path/to/holohub
HOLOSCAN_CLI_SOURCE=/path/to/holoscan-cli \
  python -m pytest -q -o addopts='' utilities/cli/tests/test_holoscan_cli_consolidation.py

The wrapper prepends <HOLOSCAN_CLI_SOURCE>/src to PYTHONPATH, so an in-progress branch can be exercised end-to-end without publishing a wheel first.

Contributing

See CONTRIBUTING.md for details. .github/CI.md covers the CI/release pipelines that back the workflow badges at the top of this page.

Deprecations

HAP/MAP application packaging

Application packaging (HAP/MAP) is no longer part of this CLI: holoscan nics and the monai-deploy console script are intentionally not provided. The current holoscan package command is for building Holoscan Module distribution artifacts; it is not the legacy HAP/MAP application packager. Before holoscan v4.3.0, holoscan run was the HAP/MAP packaged-image runner; since v4.3.0 the same name now drives the HoloHub-style source-project runner, so it no longer launches packaged images. Developers that still rely on HAP/MAP packaging should pin both holoscan-cli<=4.2.0, the last CLI release that shipped that interface, and holoscan<=4.2.0, because the legacy package command depends on the artifacts JSON manifest and was only tested with those SDK versions. Otherwise, migrate to the Holoscan SDK packaging workflows directly. See issue #164 for the deprecation timeline.

About

Command-line tool for discovering, building, running, and testing Holoscan-based projects.

Resources

Contributing

Stars

1 star

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages