# oakctl tool

oakctl is a command-line tool that allows you to interact with your OAK4 cameras. It can be used to create, deploy, and manage
apps and devices that are running the oak-agent service and are on the local network.

Note that oak-agent is pre-installed on OAK4 devices (it's baked into the [Luxonis
OS](https://docs.luxonis.com/software-v3/sw-stack/luxonis-os.md)), so you can start using oakctl right away.

## Installation

#### Linux/MacOS

On 64bit system, run:

```bash
bash -c "$(curl -fsSL https://oakctl-releases.luxonis.com/oakctl-installer.sh)"
```

#### Windows

Download and install using the [Windows Installer](https://oakctl-releases.luxonis.com/data/latest/windows_x86_64/oakctl.msi).

## Update

You can update the oakctl tool later like this:

```bash
oakctl self-update
```

> **Problems updating on Windows**
> If you have problems updating the oakctl version on Windows, download the installer from
> [here](https://oakctl-releases.luxonis.com/data/latest/windows_x86_64/oakctl.msi)
> .

## Usage

### Connect to a device

If only one device is available within the network, you can connect to it with the following command:

```bash
oakctl connect
```

If you have multiple devices or the device is not in the same network as your PC, you can specify the device's IPv4 address to
connect to it:

```bash
oakctl connect 10.0.1.24
```

Optionally, you can store your device's password using --with-password flag. This will prevent you from entering the password
every time the session expires.

### Find devices

oakctl allows you to interact with your devices that have oak-agent installed. You can list all available devices (found on your
network) with the following command:

```bash
oakctl list
+---+---------------+---------------+------------+----------------+---------------+-------+
| # | Serial Number | Device        | Connection | OS             | Agent Version | Setup |
+=========================================================================================+
| 1 | 1623452492    | Luxonis, Inc. | 10.0.1.24  | OS RVC4 1.18.0 | 0.13.7        | OK    |
|   |               |  OAK4-D R7    |            |                |               |       |
+---+---------------+---------------+------------+----------------+---------------+-------+
```

### App Development

You can run the app with the command below:

```bash
oakctl app run /app/path/to/source
```

By default, oakctl app run uses oakapp.toml from the provided app directory. Use --oakapp-file to select an alternative config
file (for example oakapp.dev.toml or oakapp.prod.toml), as long as that file is inside the same app directory tree.

#### Optional flags:

| Flag | Description |
| --- | --- |
| `-b, --detach` | Run the app in detached mode. You can stop it with `oakctl app stop <APP_ID>`. |
| `-d, --device [<DEVICE>]` | Specify device using IP, `IP:PORT`, index, or Serial Number from `oakctl list`. |
| `-i, --invalidate` | Invalidate cache and force rebuild. |
| `-e, --env <KEY=VALUE>` | Export runtime environment variable to the app (can be provided multiple times). |
| `--env-file <FILE>` | Export runtime environment variables from a `.env` file. |
| `--oakapp-file [<PATH>]` | Use an alternative `oakapp.toml` file (for example dev/prod variants) from inside the provided app
directory tree. |
| `--preserve-line-endings` | Disable automatic CRLF to LF conversion before uploading files to device. |

#### Example apps

We prepared [example apps](https://github.com/luxonis/oak-examples/tree/main/neural-networks) that you can run on your OAK4
device. Below we'll use [Human pose
detection](https://github.com/luxonis/oak-examples/tree/main/neural-networks/pose-estimation/human-pose) example, which also
contains the [oakapp.toml](#oakapp.toml):

```bash
git clone https://github.com/luxonis/oak-examples.git
cd oak-examples
# Run an app
oakctl app run ./neural-networks/pose-estimation/human-pose # or some other example
```

#### Environment variables

You can pass environment variables to the app using -e, --env flag or --env-file flag. These variables will be available in the
app's runtime environment and can be used to configure the app without changing the code.

```bash
oakctl app run ./app/path --env KEY1=VALUE1 --env KEY2=VALUE2
```

Some apps may require specific environment variables to be set for them at build time (for example API keys, model download links,
etc.). In that case, you can set those variables in the oakapp.toml file using build_env field or pass them during build with
--build-arg flag:

```bash
oakctl app build ./app/path --build-arg KEY1=VALUE1 --build-arg KEY2=VALUE
```

Some environment variables are set in each app by default:

| Variable | Description |
| --- | --- |
| `OAKAGENT_APP_ID` | Unique app ID. |
| `OAKAGENT_CONTAINER_ID` | Container ID (may differ from App ID if the app was updated). |
| `OAKAGENT_APP_IDENTIFIER` | App identifier from `oakapp.toml`. |
| `OAKAGENT_APP_VERSION` | App version from `oakapp.toml`. |
| `DEPTHAI_ZOO_MODELS_PATH` | Path to DepthAI Zoo models directory; set based on `depthai_models` field in `oakapp.toml`; prefer
to not modify manually. |
| `DEPTHAI_ZOO_CACHE_PATH` | Path to DepthAI Zoo cache directory; used for caching downloaded models; prefer to not modify
manually. |
| `DEPTHAI_ZOO_INTERNET_CHECK` | Enable internet connectivity check for model downloads; set based on `depthai_models` field in
`oakapp.toml`; prefer to not modify manually. |
| `DEPTHAI_DEVICE_NAME_LIST` | Set to `127.0.0.1` on all RVC4 devices to make sure that standalone apps use only the device they
are running on, even if there are multiple devices on the same network. |
| `OAKAPP_STATIC_FRONTEND_PATH` | Path to static frontend files for the app. |
| `OAKAPP_STATIC_FRONTEND_PORT` | Port for serving static frontend files. It is set from range 9000-9128 to avoid conflicts with
the ports used by the agent or other apps. |
| `OAKAGENT_STORAGE_APP` | App-specific persistent storage path. |
| `OAKAGENT_STORAGE_SHARED` | Shared storage path accessible across apps with the same identifier. |
| `OAKAGENT_STORAGE_GLOBAL` | Global storage path on the device. |

> **Persistent Storage**
> Persistent storage paths are used to store data that should persist across app restarts and updates. These paths are mounted
into the app's container. You can choose the target directory name for the storage in the container with
> `oakapp.toml`
> configuration (
> `storage_dir_name`
> ).
> - `OAKAGENT_STORAGE_APP`
> is a storage path that is unique to each app and is not shared with other apps. It is useful for storing app-specific data that
should not be accessible by other apps.
> - `OAKAGENT_STORAGE_SHARED`
> is a storage path that is shared between all apps with the same identifier. It is useful for storing data that should be
accessible by different installations of the same app.
> - `OAKAGENT_STORAGE_GLOBAL`
> is a global storage path that is not tied to any specific app. It is useful for storing data that should be accessible
regardless of which apps are installed or running.

### App Management

You can install multiple apps on the device. If you are developing an app, you can share compiled apps with others within the
team.

Be sure you run only one DepthAI app at a time.

Most of the app management commands have optional flags -d, --device <DEVICE> to specify the device to run the command on (IP
address or index from the oakctl list).

#### List installed apps

If you setup the device and adopted in the Hub, you probably have one app installed (com.luxonis.default).

```bash
$ oakctl app list
+---+--------+---------------------------+---------+-------------------+
| E | App Id | Identifier                | Status  | Frontend URL      |
+====================================================================================================+
| * | f8da5  | com.luxonis.default:1.3.8 | running | 10.0.1.24:9000    |
+---+--------+---------------------------+---------+-------------------+
```

First column (E) has asterisk if the app is enabled.

Any app can be in one of the following states: installing, building, ready, starting, running, stopping, stopped, deleting,
deleted, unknown.

Ready means the app is installed and ready to run, but it was not started since the agent was started, while stopped means the app
is installed but not running, it was stopped by the user.

> **Note**
> App IDs are truncated in the list for better readability. If there are multiple apps with the same prefix, the truncation length
increases until all app IDs are unique. You can also use the
> `--long`
> flag to show full app IDs in the list. All app control commands accept both full and truncated App IDs as long as they are
unique.

#### App control flow

The basic commands to control the app are start, stop, and delete. First, let's start the app:

```bash
$ oakctl app start 612a745c-8d68-4264-a3d6-d06d14275ef5
Starting app 612a745c-8d68-4264-a3d6-d06d14275ef5 ...
  App has been started!
```

You can also use a unique App ID prefix:

```bash
$ oakctl app start 612a745c
```

Now, let's read app logs - this command will read the app's logs and print them to the console as they are received:

```bash
$ oakctl app logs <app-id>
Reading logs ...
  Press Ctrl+C to stop reading logs.
  App output:
    [2025-02-12T14:37:54Z] Hello cli 1 / Wed Feb 12 14:37:54 UTC 2025
```

Optionally, you can specify the number of previous lines to read with the -n flag:

```bash
oakctl app logs <app-id> -n 10
```

If you only want historical logs without attaching to live output, use:

```bash
oakctl app logs <app-id> --no-follow
```

Now you can stop the app:

```bash
$ oakctl app stop 612a745c-8d68-4264-a3d6-d06d14275ef5
Stopping app 612a745c-8d68-4264-a3d6-d06d14275ef5 ...
  App has been stopped!
```

And here is how you can delete the app:

```bash
$ oakctl app delete 612a745c-8d68-4264-a3d6-d06d14275ef5
Deleting app 612a745c-8d68-4264-a3d6-d06d14275ef5 ...
  App has been deleted!
```

Any app can be enabled or disabled. If the app is enabled, it will start automatically when the device is booted.

```bash
oakctl app enable <app-id>
```

You can also disable the app with the disable command:

```bash
oakctl app disable <app-id>
```

To interactively attach to the already running App on the device use the exec command:

```bash
oakctl app exec <app-id> -i /bin/bash
```

This will open an interactive bash shell inside the app's container, allowing you to inspect files, processes, and environment
variables.

> **Note**
> Be careful when modifying files or saving data inside the container, as changes can be lost when the container is stopped or
removed. Better approach is to mount a persistent folder from the host device into the container using mounts (see
> [`oakapp.toml` configuration](https://docs.luxonis.com/software-v3/oak-apps/configuration.md)
> ) or persistent storage that is managed by the OAK agent (see
> `OAKAGENT_STORAGE_APP`
> ,
> `OAKAGENT_STORAGE_SHARED`
> ,
> `OAKAGENT_STORAGE_GLOBAL`
> environment variables).

#### Install an app

App can be found in Hub in section [OAK4 Apps](https://hub.luxonis.com/control/apps/team-apps?tab=oak4). There are apps that are
shared with the team and apps that are shared with your team or public apps. By default, a newly installed app stops all others
and is enabled and running. You can modify this behavior by using --enable=false or --keep-others flags.

App installation is done by following command:

```bash
$ oakctl app install com-example-emotion_recognition_1-0-1.oakapp
Sending data to agent ...
  Data sent successfully!

✔ Oakapp package built successfully.                                                                                                         
Installed app has ID: ddb8a884-d9e1-4779-a88b-c30d5d1e265f

Start the app:  oakctl app start ddb8a884-d9e1-4779-a88b-c30d5d1e265f
```

App can be installed from an *.oakapp file, from Hub (by identifier) or from URL.

If you want to install app from Hub, do this:

```bash
# Install app by identifier
oakctl app install -i com.example.app
```

There is also an option to install app by URL if the app is somewhere on the internet:

```bash
# Install app by URL
oakctl app install -u https://example.com/app.oakapp
```

#### Update an app

App updates can be performed using the oakctl app install command. By default, oakctl app install attempts to update an existing
app with the same identifier. Use the --force-new flag to install a new instance instead of updating (this is useful for
self-hosted oak-agent; Luxonis OS does not allow multiple DepthAI apps at the same time).

If multiple apps share the same identifier, specify which one to update using the --update <APP_ID> flag.

The update process follows these steps:

 1. The new app version is downloaded from the Hub, URL, or local *.oakapp file (depending on the source: -i, -u, or file path).
    The current version remains running during this step.
 2. Once the new version is downloaded and validated, the current version stops and the new version starts. Any previous rollback
    version is then removed.

For more control, you can perform updates manually:

 1. Stage the new version: oakctl app install --manual-update downloads and prepares the new version without stopping the current
    one. Verify readiness with oakctl app list.
 2. Commit the update: oakctl app update <APP_ID> --commit stops the current version and starts the new one.
 3. Rollback if needed: oakctl app update <APP_ID> --rollback reverts to the previous version if issues occur.
 4. Finalize when ready: oakctl app update <APP_ID> --finalize removes the old version kept for rollback once you confirm the new
    version is stable.

#### Build And Publish App

You can build your own app. The process will produce *.oakapp file that can be installed on other devices:

```bash
oakctl app build ./folder/app/src
```

By default, oakctl app build uses oakapp.toml from the provided app directory. Use --oakapp-file to select an alternative config
file (for example oakapp.dev.toml or oakapp.prod.toml), as long as that file is inside the same app directory tree.

Optional flags:

 * -d, --device [<DEVICE>] - specify device using IP, IP:PORT, index, or Serial Number from oakctl list
 * -k, --keep - keep the container after the build (useful if you want to oakctl app start it right after the build)
 * -p, --publish - publish the app to the Hub after the build (the app will show up in the Hub's [OAK4
   Apps](https://hub.luxonis.com/control/apps/team-apps?tab=oak4)).
 * -O, --optimized - build the app in optimized mode (smaller size, longer build time)
 * -U, --update-description - update the app description on the Hub if the app is published
 * -N, --no-download - do not download the *.oakapp file to host after build
 * -o, --output [<PATH>] - path to the directory where the built *.oakapp file should be downloaded
 * --oakapp-file [<PATH>] - use an alternative oakapp.toml file from inside the provided app directory tree
 * --preserve-line-endings - disable automatic CRLF to LF conversion before uploading files to device

If you publish the app, you need to specify the app's identifier and unique version in oakapp.toml file.

### Hub connection

For some operations, you need to connect the device to the Hub. You can do this with the following command:

```bash
oakctl hub login
```

After you log in, you can check the status of the connection with the following command:

```bash
oakctl hub status
```

To change the active team, run oakctl hub login again and select the team in the web login flow. oakctl hub switch-team is an
alias to oakctl hub login.

Logout using:

```bash
oakctl hub logout
```

Once you're logged in, you can publish built *.oakapp packages:

```bash
oakctl hub publish <oakapp-file>
```

You can also run local scripts that require the Hub token for model downloads, etc.:

```bash
oakctl hub run-script <script-file>
```

### Device Management

#### Device Info

Device info command will show you the device's information, such as OS version, agent version, architecture, serial number, and
model.

```bash
$ oakctl device info
Device Info:
  OS:                   Luxonis OS RVC4 1.4.0
  Agent Version:        2.0.11 (rvc4)
  Architecture:         linux/arm64
  Serial Number:        2713799968
  Model:                Luxonis, Inc. KalamaP OAK4-D R1
```

Use --check_internet flag to check internet connectivity as well.

#### Device Update

Device can be updated with the following command - possible values for CHANNEL are stable and beta:

```bash
oakctl device update --channel=[CHANNEL]
```

This command will check the latest available version and update the device if the version is different.

You can select the specific version to update to using --select flag:

```bash
oakctl device update --select --channel=[CHANNEL]
```

Update command works only if the device is connected to the internet.

#### Device Reboot

You can reboot the device using oakctl:

```bash
oakctl device reboot
```

This command will reboot the device and wait for it to come back online.

#### Device Unlock

New devices have disabled SSH access by default. You can enable it using the following command:

```bash
oakctl device unlock
```

This command will prompt you to set a password.

#### Device Flash

You can flash the device (USB only) with a new Luxonis OS image using the following command:

```bash
oakctl device flash [<path-to-tar.xz>]
```

Path to the *.tar.xz image is optional; if not specified, the latest stable image will be downloaded and flashed. For detailed
flashing and OS update instructions see [updating OS page](https://docs.luxonis.com/software-v3/sw-stack/luxonis-os.md).

## oak-agent

oak-agent is a service that runs on the OAK4 device and manages the containers. It's responsible:

 * Managing apps, running containers
 * Communicating with the oakctl tool
 * Communicating with the Hub (cloud platform)

### Containers

oak-agent uses runc as a lightweight container runtime, which is also what Docker/Podman uses. We opted-in for runc because it's
lightweight and gives us full control over the container lifecycle.

## Release Notes for oakctl and oak-agent

### agent v0.18.6, oakctl v0.18.6 (April 8, 2026)

#### Added

 * oakctl app install now deletes unnecessary files after installation to save storage space.
 * oakctl app prune-storage now removes installation and download files too.
 * oakctl app delete now also deletes malformed apps.
 * oakctl device info now shows:
   * date
   * network information
   * HTTP API port for downloading built apps
 * oakctl app run no longer rebuilds the whole app if a command fails during build steps; it keeps successfully built layers
   instead.
 * New oakapp.toml definition:
   * Added shell field to specify the default shell for RUN commands, build_steps, and entrypoint (default: ["/bin/sh", "-c"]).
   * Commands can now be written in shell form (string) or exec form (array of strings).
   * Removed shlex-based parsing because it did not support constructs like redirection and pipes.
   * Added optional arg section for build-time environment variables and --build-arg flag for oakctl app build and oakctl app run.
   * Added optional additional_build_mounts section for mounts used only during the build stage.
 * All Hub service endpoints can now be configured by API.
   * Use OAKCTL_HUB_API_URL in oakctl.
   * Use api= in setup-utility config for oak-agent.

#### Changed

 * Renamed the env variable that selects the Hub services environment in oakctl from ENV to OAKCTL_ENV.

### agent v0.18.3, oakctl v0.18.2 (February 17, 2026)

#### Added

 * Image download progress reporting during oakctl app build and oakctl app run commands.
 * GPU support for self-hosted agent, which allows oak apps to use the host's Nvidia GPU if enabled.
 * oakctl app [build|run] --oakapp-file [PATH] arg to specify a custom path to the oakapp.toml file.
 * oakctl app logs --no-follow arg to avoid attaching to the log stream.
 * Remote command execution from Luxonis Hub.
 * Replaced --*-b64 arguments of oakctl setup with a new subcommand oakctl setup-b64.
 * Rejection of relative paths in oakapp.toml mount fields: required_mounts, required_devices, optional_mounts, optional_devices,
   additional_mounts.
 * oakctl device update support for self-hosted oak-agent.

#### Fixed

 * Failed to mount overlayfs error on oakctl app build when trying to use a base image with many layers (around 30).
 * oakctl adb on jetson.
 * Added installation of QDL udev rules to oakctl self-update.
   * Fixes some instances of qdl: Failed to open device during oakctl device flash.
 * /etc/resolv.conf missing in container on second app run after editing oakapp.toml.

### agent v0.17.4, oakctl v0.17.4 (January 15, 2026)

#### Added

 * oakctl app build --output [PATH] argument to indicate where to download the *.oakapp file after building it.
 * Base64-encoded arguments of oakctl setup command to ensure cross-OS-compatible escaping of special characters for the
   Hub-generated setup command.
 * Automated check for new oakctl versions once per day.
 * oakctl app prune-storage command to remove unnecessary app files.
 * oakctl app list --long flag to show full App ID.
 * oak-agent tests WebRTC connection.
 * oakctl device info and oakctl list show adoption status.
 * Welcome ACK factory reset support.
 * oakctl app install updates an existing app by default.
   * Can be modified with --force-new flag to install as a new app.
   * Can be modified with --update flag to update a specific existing app.
 * oakctl app install --env / --env-file to set environment variables during app installation.
 * Multiplatform self-hosted Docker image.

#### Changed

 * oakctl app list now shows App IDs truncated to 3 characters by default; truncation increases automatically when there are
   collisions.
 * oak-agent saves new app build metadata.
 * Self-hosted WebRTC terminal opens host shell instead of container shell.
 * oakctl app <ACTION> <app-id> commands now accept both full and truncated App IDs.

#### Fixed

 * Fixed an issue where OTA update status deserialization failed if multiple messages were received in a single read.
 * oakctl on Windows converts CRLF to LF automatically.
 * Self-hosted oak-agent/oakctl fixes:
   * fixed oakctl device info --check_internet
   * fixed oakctl device reboot
   * fixed oakctl setup command (failed on some devices like RPi)
   * adb binary for ARM devices was missing (mistakenly included x86 binary instead)
 * Fixed app publish upload with OAKCTL_HUB_TOKEN.
 * oakctl builds for macOS ARM and Windows were not signed.
 * Fixed build cache invalidation for oak-agent.
 * Fixed an issue where oakctl did not save and/or read sn-data.json correctly.

#### Deprecated

 * OAKCTL_HUB_LOGIN_TOKEN env renamed to OAKCTL_HUB_TOKEN.
 * oakctl hub switch-team is now an alias to oakctl hub login (team is selected in web login flow).
 * --enabled flag renamed from -e to -E.

### oakctl v0.16.5 (December 15, 2025)

#### Added

 * New flag --yes for non-interactive oakctl device update.
 * New flag --check_internet for oakctl device update to check internet connectivity before updating.
 * oakctl viewer command to open Viewer is enabled.
 * New flag --no-download for oakctl app build to skip downloading built *.oakapp file to host; useful for tests.
 * New flags --enable and --disable-others for oakctl app start.

#### Changed

 * oakctl hub login now uses web-based authentication flow.
 * Minor improvements for integration into Viewer.
